home *** CD-ROM | disk | FTP | other *** search
- /*!
- \file octree.cpp
- \author Karsten Schwenk
-
- See header for description (octree.h).
- */
-
- #include "Octree.h"
- #include "intersection.h"
- #include "matrixmath.h"
- #include "log.h"
- //#include "camera.h"
- //#include "light.h"
-
- #include "Renderer.h"
- #include "RendererInfo.h"
-
-
-
- #define OCTREE_MIN_EDGELENGTH 5.0f
- #define OCTREE_MAX_LEVEL 10
- #define OCTREE_MIN_FACES_PER_LEAF_NODE 200
-
- Octree::Octree(Model* model):SpacePartitioningTree(model){
- log("Building octree (min=(%.2f, %.2f, %.2f) max=(%.2f, %.2f, %.2f))...\n", min[0],min[1],min[2], max[0], max[1], max[2]);
-
- root=new OctreeNode(this);
- vectorCopy3d(min, root->min);
- vectorCopy3d(max, root->max);
- root->buildNode();
-
- nodes=new SpacePartitioningTreeNode*[numNodes];
-
- log("building neightbourhood info...\n");
- root->buildNeighbourhoodInfo();
-
- for(int i=0;i<model->numMeshes;i++){
- numFaces+=model->meshes[i]->numFaces;
- }
- facesDrawn=new BitSet(numFaces);
-
- log("Octree constructed: %i nodes in %i levels having a minEdgelength of %.2f.\n", numNodes, numLevels, OCTREE_MIN_EDGELENGTH);
- }
-
- Octree::~Octree(){
- // delete facesDrawn;
- // delete root; // this destroys recursively all nodes
-
- if(pvs!=NULL){
- delete pvs;
- }
- }
-
-
-
- OctreeNode::OctreeNode(Octree* tree):SpacePartitioningTreeNode(tree){
- int i;
-
- //this->tree=tree;
-
- parent=NULL;
-
- numChilds=OCTREE_NUM_CHILDS;
- childs=new SpacePartitioningTreeNode*[numChilds];
- for(i=0;i<numChilds;i++)
- childs[i]=NULL;
-
- numNeighbours=OCTREE_NUM_NEIGHBOURS;
- neighbours=new SpacePartitioningTreeNode*[numNeighbours];
- for(i=0;i<numNeighbours;i++)
- neighbours[i]=NULL;
- }
-
- OctreeNode::~OctreeNode(){
- }
-
- void OctreeNode::buildNode(){
- int i,j;
- Model* m=tree->model;
- vec4_t p1, p2, p3;
- vec4_t n1, n2, n3, n;
-
- if(parent==NULL){
- level=0;
- }else{
- level=parent->level+1;
- }
- nodeId=tree->numNodes;
- tree->numNodes++;
-
- if(tree->numLevels<level)
- tree->numLevels=level;
-
- // count faces that COULD be in node
- int faceCount=0;
- for(i=0;i<m->numMeshes;i++){
- for(j=0;j<m->meshes[i]->numFaces;j++){
- vectorInit4d(m->meshes[i]->faces[j]->vertices[0], m->meshes[i]->faces[j]->vertices[1], m->meshes[i]->faces[j]->vertices[2], 1.0f, p1);
- vectorInit4d(m->meshes[i]->faces[j]->vertices[3], m->meshes[i]->faces[j]->vertices[4], m->meshes[i]->faces[j]->vertices[5], 1.0f, p2);
- vectorInit4d(m->meshes[i]->faces[j]->vertices[6], m->meshes[i]->faces[j]->vertices[7], m->meshes[i]->faces[j]->vertices[8], 1.0f, p3);
- matrixMultVector(m->matrices[0][i], p1, 4, p1);
- matrixMultVector(m->matrices[0][i], p2, 4, p2);
- matrixMultVector(m->matrices[0][i], p3, 4, p3);
-
- if(triangleIntersectsAABB(p1, p2, p3, min, max)){
- faceCount++;
- }
- }
- }
-
-
- if(max[0]-min[0] < OCTREE_MIN_EDGELENGTH || max[1]-min[1] < OCTREE_MIN_EDGELENGTH || max[2]-min[2] < OCTREE_MIN_EDGELENGTH
- || level>=OCTREE_MAX_LEVEL
- || faceCount<OCTREE_MIN_FACES_PER_LEAF_NODE){ // make it a leaf node
-
- faceIds=new unsigned int[faceCount];
-
- mesh=new Mesh();
-
- int faceIdInModel=-1; // id in model
- int faceIdInMesh=0; // id in mesh
- for(i=0;i<m->numMeshes;i++){
- for(j=0;j<m->meshes[i]->numFaces;j++){
- faceIdInModel++;
-
- vectorInit4d(m->meshes[i]->faces[j]->vertices[0], m->meshes[i]->faces[j]->vertices[1], m->meshes[i]->faces[j]->vertices[2], 1.0f, p1);
- vectorInit4d(m->meshes[i]->faces[j]->vertices[3], m->meshes[i]->faces[j]->vertices[4], m->meshes[i]->faces[j]->vertices[5], 1.0f, p2);
- vectorInit4d(m->meshes[i]->faces[j]->vertices[6], m->meshes[i]->faces[j]->vertices[7], m->meshes[i]->faces[j]->vertices[8], 1.0f, p3);
- matrixMultVector(m->matrices[0][i], p1, 4, p1);
- matrixMultVector(m->matrices[0][i], p2, 4, p2);
- matrixMultVector(m->matrices[0][i], p3, 4, p3);
-
- if(!triangleIntersectsAABB(p1, p2, p3, min, max)){
- continue;
- }
-
- Face* face=new Face();
-
- face->numVertices=3;
- face->vertices=new GLfloat[3*3];
- vectorCopy3d(p1, &face->vertices[0]);
- vectorCopy3d(p2, &face->vertices[3]);
- vectorCopy3d(p3, &face->vertices[6]);
-
- vectorInit4d(m->meshes[i]->faces[j]->normals[0], m->meshes[i]->faces[j]->normals[1], m->meshes[i]->faces[j]->normals[2], 0.0f, n1);
- vectorInit4d(m->meshes[i]->faces[j]->normals[3], m->meshes[i]->faces[j]->normals[4], m->meshes[i]->faces[j]->normals[5], 0.0f, n2);
- vectorInit4d(m->meshes[i]->faces[j]->normals[6], m->meshes[i]->faces[j]->normals[7], m->meshes[i]->faces[j]->normals[8], 0.0f, n3);
- matrixMultVector(m->matrices[0][i], n1, 4, n1);
- matrixMultVector(m->matrices[0][i], n2, 4, n2);
- matrixMultVector(m->matrices[0][i], n3, 4, n3);
-
- face->numNormals=3;
- face->normals=new GLfloat[3*3];
- vectorCopy3d(n1, &face->normals[0]);
- vectorCopy3d(n2, &face->normals[3]);
- vectorCopy3d(n3, &face->normals[6]);
-
- face->numColors=3;
- face->colors=new GLfloat[3*3];
- vectorCopy3d(&m->meshes[i]->faces[j]->colors[0], &face->colors[0]);
- vectorCopy3d(&m->meshes[i]->faces[j]->colors[3], &face->colors[3]);
- vectorCopy3d(&m->meshes[i]->faces[j]->colors[6], &face->colors[6]);
-
- face->numTexCoords=3;
- face->texCoords1=new GLfloat[3*2];
- vectorCopy2d(&m->meshes[i]->faces[j]->texCoords1[0], &face->texCoords1[0]);
- vectorCopy2d(&m->meshes[i]->faces[j]->texCoords1[2], &face->texCoords1[2]);
- vectorCopy2d(&m->meshes[i]->faces[j]->texCoords1[4], &face->texCoords1[4]);
-
- face->texCoords2=new GLfloat[3*2];
- vectorCopy2d(&m->meshes[i]->faces[j]->texCoords2[0], &face->texCoords2[0]);
- vectorCopy2d(&m->meshes[i]->faces[j]->texCoords2[2], &face->texCoords2[2]);
- vectorCopy2d(&m->meshes[i]->faces[j]->texCoords2[4], &face->texCoords2[4]);
-
- //vectorCopy3d(m->meshes[i]->faces[j]->normal, face->normal);
- vectorInit4d(m->meshes[i]->faces[j]->normal[0], m->meshes[i]->faces[j]->normal[1], m->meshes[i]->faces[j]->normal[2], 0.0f, n);
- matrixMultVector(m->matrices[0][i], n, 4, n);
- vectorNormalize3d(n, n);
- vectorCopy3d(n, face->normal);
-
- face->material=m->meshes[i]->faces[j]->material;
-
- mesh->addFace(face);
-
- faceIds[faceIdInMesh]=faceIdInModel;
- faceIdInMesh++;
- }
- }
-
- mesh->name="<name destroyed by octree>";
- mesh->createSecondaryColors();
- mesh->setRenderMode();
- if(_glGenBuffersARB!=NULL && Renderer::info.var.useVBOs==true){
- mesh->createVBOs();
- mesh->updateSecondaryColorVBO();
- }
-
- // mesh->sortFacesByMaterial();
- leafNode=true;
-
- }else{ // divide it further
- vec3_t center;
- vectorInit3d((min[0]+max[0])*0.5f, (min[1]+max[1])*0.5f, (min[2]+max[2])*0.5f, center);
-
- childs[OCTREE_CHILD_LOWER_RIGHT_FRONT]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_LOWER_RIGHT_FRONT]->parent=this;
- vectorInit3d(center[0], min[1], center[2], childs[OCTREE_CHILD_LOWER_RIGHT_FRONT]->min);
- vectorInit3d(max[0], center[1], max[2], childs[OCTREE_CHILD_LOWER_RIGHT_FRONT]->max);
-
- childs[OCTREE_CHILD_LOWER_LEFT_FRONT]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_LOWER_LEFT_FRONT]->parent=this;
- vectorInit3d(min[0], min[1], center[2], childs[OCTREE_CHILD_LOWER_LEFT_FRONT]->min);
- vectorInit3d(center[0], center[1], max[2], childs[OCTREE_CHILD_LOWER_LEFT_FRONT]->max);
-
- childs[OCTREE_CHILD_UPPER_RIGHT_FRONT]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_UPPER_RIGHT_FRONT]->parent=this;
- vectorInit3d(center[0], center[1], center[2], childs[OCTREE_CHILD_UPPER_RIGHT_FRONT]->min);
- vectorInit3d(max[0], max[1], max[2], childs[OCTREE_CHILD_UPPER_RIGHT_FRONT]->max);
-
- childs[OCTREE_CHILD_UPPER_LEFT_FRONT]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_UPPER_LEFT_FRONT]->parent=this;
- vectorInit3d(min[0], center[1], center[2], childs[OCTREE_CHILD_UPPER_LEFT_FRONT]->min);
- vectorInit3d(center[0], max[1], max[2], childs[OCTREE_CHILD_UPPER_LEFT_FRONT]->max);
-
- childs[OCTREE_CHILD_LOWER_RIGHT_BACK]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_LOWER_RIGHT_BACK]->parent=this;
- vectorInit3d(center[0], min[1], min[2], childs[OCTREE_CHILD_LOWER_RIGHT_BACK]->min);
- vectorInit3d(max[0], center[1], center[2], childs[OCTREE_CHILD_LOWER_RIGHT_BACK]->max);
-
- childs[OCTREE_CHILD_LOWER_LEFT_BACK]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_LOWER_LEFT_BACK]->parent=this;
- vectorInit3d(min[0], min[1], min[2], childs[OCTREE_CHILD_LOWER_LEFT_BACK]->min);
- vectorInit3d(center[0], center[1], center[2], childs[OCTREE_CHILD_LOWER_LEFT_BACK]->max);
-
- childs[OCTREE_CHILD_UPPER_RIGHT_BACK]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_UPPER_RIGHT_BACK]->parent=this;
- vectorInit3d(center[0], center[1], min[2], childs[OCTREE_CHILD_UPPER_RIGHT_BACK]->min);
- vectorInit3d(max[0], max[1], center[2], childs[OCTREE_CHILD_UPPER_RIGHT_BACK]->max);
-
- childs[OCTREE_CHILD_UPPER_LEFT_BACK]=new OctreeNode((Octree*)tree);
- childs[OCTREE_CHILD_UPPER_LEFT_BACK]->parent=this;
- vectorInit3d(min[0], center[1], min[2], childs[OCTREE_CHILD_UPPER_LEFT_BACK]->min);
- vectorInit3d(center[0], max[1], center[2], childs[OCTREE_CHILD_UPPER_LEFT_BACK]->max);
-
- leafNode=false;
-
- for(i=0;i<OCTREE_NUM_CHILDS;i++){
- childs[i]->buildNode();
- }
- }
-
- }
-
- void OctreeNode::buildNeighbourhoodInfo(){
- vec3_t point, mid;
- float xSize=max[0]-min[0];
- float ySize=max[1]-min[1];
- float zSize=max[2]-min[2];
-
- vectorInit3d((min[0]+max[0])*0.5f, (min[1]+max[1])*0.5f, (min[2]+max[2])*0.5f, mid);
-
- vectorInit3d(mid[0]-xSize, mid[1], mid[2], point);
- neighbours[OCTREE_NEIGHBOUR_RIGHT]=(OctreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0]+xSize, mid[1], mid[2], point);
- neighbours[OCTREE_NEIGHBOUR_LEFT]=(OctreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0], mid[1]+ySize, mid[2], point);
- neighbours[OCTREE_NEIGHBOUR_UP]=(OctreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0], mid[1]-ySize, mid[2], point);
- neighbours[OCTREE_NEIGHBOUR_DOWN]=(OctreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0], mid[1], mid[2]-zSize, point);
- neighbours[OCTREE_NEIGHBOUR_FRONT]=(OctreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0], mid[1], mid[2]-zSize, point);
- neighbours[OCTREE_NEIGHBOUR_BACK]=(OctreeNode*)tree->getNodeContainingPoint(point, level);
-
- tree->nodes[nodeId]=this;
-
- if(leafNode)
- return;
-
- for(int i=0;i<OCTREE_NUM_CHILDS;i++){
- childs[i]->buildNeighbourhoodInfo();
- }
-
- }
-
-
-
-