#include "map.h"
#include
#include
#include "camera.h"
#include "console.h"
#include "glextensions.h"
#include "state.h"
Octet::Octet()
: numFaces(0), data(0), vboID(0)
{
memset(child, 0, sizeof(Octet *)*8);
}
Octet::~Octet()
{
delete [] data;
if(GL_ARB_vertex_buffer_object_supported && glIsBufferARB(vboID) == GL_TRUE)
{
glDeleteBuffersARB(1, &vboID);
}
}
Map::Map()
: head(0), numVerts(0), numFaces(0), verts(0), faces(0)
{
}
Map::~Map()
{
Unload();
}
void Map::Render(const unsigned int &time) const
{
glColor3f(1.0f, 1.0f, 1.0f);
StateMgr::Inst()->StateEnable(GL_CULL_FACE);
StateMgr::Inst()->StateEnable(GL_TEXTURE_2D);
material.Apply();
DrawOctets (head, CamMgr::Inst()->GetFrustum());
StateMgr::Inst()->StateDisable(GL_TEXTURE_2D);
StateMgr::Inst()->StateDisable(GL_CULL_FACE);
}
void Map::DeleteOctets(Octet *&node)
{
if(node)
{
for(int x = 0; x < 8; x++)
{
if(node->child[x])
{
DeleteOctets(node->child[x]);
}
}
delete node;
}
}
bool Map::Load(const char *filename)
{
if(head) // If there is already a map loaded...
{
Unload();
}
if(LoadMof(filename))
{
GenLists(head);
return true;
}
else
{
Unload();
ConsoleMgr::Inst()->AddText("* Unable to load \'%s\'", filename);
return false;
}
}
void Map::Unload()
{
material.Unload();
delete [] verts; verts = 0;
delete [] faces; faces = 0;
numVerts = 0;
numFaces = 0;
if(head)
{
DeleteOctets(head);
}
head = 0;
}
bool Map::LoadMof(const char *filename)
{
FILE *infile;
infile = fopen(filename, "rb");
if(infile)
{
float version;
fread(&version, sizeof(float), 1, infile);
if(version == MOFVERSION)
{
material.Read(infile);
material.LoadTexture();
fread(&numVerts, sizeof(unsigned int), 1, infile); // Number of verticies
fread(&numFaces, sizeof(unsigned int), 1, infile); // Number of faces
verts = new MeshVertex [numVerts];
faces = new MeshFace [numFaces];
fread(verts, sizeof(MeshVertex), numVerts, infile); // List of MeshVertex's
fread(faces, sizeof(MeshFace), numFaces, infile); // List of MeshFace's
LoadOctets(head, infile);
fclose(infile);
return true;
}
else
{
ConsoleMgr::Inst()->AddText("* Map version mismatch");
fclose(infile);
return false;
}
}
else
{
return false;
}
}
void Map::LoadOctets(Octet *&node, FILE *&infile)
{
node = new Octe
GLubyte children;
fread(&children, sizeof(GLubyte), 1, infile); // Number of children
fread( node->center, sizeof(GLfloat), 3, infile); // 3d point, center of the node
fread(&node->radius, sizeof(GLfloat), 1, infile); // Radius
fread(&node->numFaces, sizeof(GLfloat), 1, infile); // Number of faces in the node. (0 if its a parent)
if(node->numFaces) // If this isn't 0, this node is a leaf, and we need to ouput which faces are in this node
{
node->data = new GLfloat[24*node->numFaces];
fread(node->data, sizeof(GLfloat), 24*node->numFaces, infile);
}
else // If it isn't a leaf, it has children which need loading.
{
for(GLubyte x = 0; x < children; ++x)
{
LoadOctets(node->child[x], infile);
}
}
}
void Map::GenLists(Octet *&node)
{
if(node)
{
if(node->numFaces > 0)
{
if(GL_ARB_vertex_buffer_object_supported)
{
if(node->vboID)
{
glDeleteBuffersARB(1, &node->vboID);
}
glGenBuffersARB(1, &node->vboID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, node->vboID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, node->numFaces*24*sizeof(GLfloat), node->data, GL_STATIC_DRAW_ARB);
}
}
else
{
for(unsigned int x = 0; x < 8; ++x)
{
GenLists(node->child[x]);
}
}
}
}
void Map::DrawOctets(const Octet *node, const GLfloat *frustum) const
{
if(node && frustum)
{
if(NodeInFrustum(frustum, node))
{
if(node->numFaces)
{
if(GL_ARB_vertex_buffer_object_supported /*&& glIsBufferARB(node->vboID) == GL_TRUE*/)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, node->vboID);
glInterleavedArrays(GL_T2F_N3F_V3F, 0, 0);
}
else
{
glInterleavedArrays(GL_T2F_N3F_V3F, 0, node->data);
}
glDrawArrays(GL_TRIANGLES, 0, node->numFaces*3);
}
else
{
for(unsigned int x = 0; x < 8; ++x)
{
DrawOctets(node->child[x], frustum);
}
}
}
}
}
bool Map::NodeInFrustum(const GLfloat *frustum, const Octet *node) const
{
for(unsigned int p = 0; p < 6; p++ )
{
unsigned int i = p*4;
if(frustum[i] * (node->center[0] - node->radius) + frustum[i+1] * (node->center[1] - node->radius) + frustum[i+2] * (node->center[2] - node->radius) + frustum[i+3] > 0)
continue;
if(frustum[i] * (node->center[0] + node->radius) + frustum[i+1] * (node->center[1] - node->radius) + frustum[i+2] * (node->center[2] - node->radius) + frustum[i+3] > 0)
continue;
if(frustum[i] * (node->center[0] - node->radius) + frustum[i+1] * (node->center[1] + node->radius) + frustum[i+2] * (node->center[2] - node->radius) + frustum[i+3] > 0)
continue;
if(frustum[i] * (node->center[0] + node->radius) + frustum[i+1] * (node->center[1] + node->radius) + frustum[i+2] * (node->center[2] - node->radius) + frustum[i+3] > 0)
continue;
if(frustum[i] * (node->center[0] - node->radius) + frustum[i+1] * (node->center[1] - node->radius) + frustum[i+2] * (node->center[2] + node->radius) + frustum[i+3] > 0)
continue;
if(frustum[i] * (node->center[0] + node->radius) + frustum[i+1] * (node->center[1] - node->radius) + frustum[i+2] * (node->center[2] + node->radius) + frustum[i+3] > 0)
continue;
if(frustum[i] * (node->center[0] - node->radius) + frustum[i+1] * (node->center[1] + node->radius) + frustum[i+2] * (node->center[2] + node->radius) + frustum[i+3] > 0)
continue;
if(frustum[i] * (node->center[0] + node->radius) + frustum[i+1] * (node->center[1] + node->radius) + frustum[i+2] * (node->center[2] + node->radius) + frustum[i+3] > 0)
continue;
return false;
}
return true;
} |