home *** CD-ROM | disk | FTP | other *** search
- /*!
- \file Quadtree.cpp
- \author Karsten Schwenk
-
- See header for description (quadtree.h).
- */
-
-
- #include "Quadtree.h"
- #include "intersection.h"
- #include "matrixmath.h"
- #include "log.h"
- #include "Camera.h"
- //#include "Light.h"
-
- #include "Renderer.h"
- #include "RendererInfo.h"
-
- #define QUADTREE_MIN_EDGELENGTH 5.0f
- #define QUADTREE_MAX_LEVEL 10
- #define QUADTREE_MIN_FACES_PER_LEAF_NODE 200
-
- Quadtree::Quadtree(Model* model):SpacePartitioningTree(model){
- log("Building quadtree (min=(%.2f, %.2f, %.2f) max=(%.2f, %.2f, %.2f))...\n", min[0],min[1],min[2], max[0], max[1], max[2]);
- root=new QuadtreeNode(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("Quadtree constructed: %i nodes in %i levels having a minEdgelength of %.2f.\n", numNodes, numLevels, QUADTREE_MIN_EDGELENGTH);
- }
-
- Quadtree::~Quadtree(){
- }
-
-
-
-
- QuadtreeNode::QuadtreeNode(Quadtree* tree):SpacePartitioningTreeNode(tree){
- int i;
-
- // this->tree=tree;
-
- parent=NULL;
-
- numChilds=QUADTREE_NUM_CHILDS;
- childs=new SpacePartitioningTreeNode*[numChilds];
- for(i=0;i<numChilds;i++)
- childs[i]=NULL;
-
- numNeighbours=QUADTREE_NUM_NEIGHBOURS;
- neighbours=new SpacePartitioningTreeNode*[numNeighbours];
- for(i=0;i<numNeighbours;i++)
- neighbours[i]=NULL;
-
- }
-
- QuadtreeNode::~QuadtreeNode(){
- }
-
- void QuadtreeNode::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;
- }
- if(tree->numLevels<level)
- tree->numLevels=level;
-
- nodeId=tree->numNodes;
- tree->numNodes++;
-
- // 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] < QUADTREE_MIN_EDGELENGTH || max[2]-min[2] < QUADTREE_MIN_EDGELENGTH
- || level>=QUADTREE_MAX_LEVEL
- || faceCount<QUADTREE_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 quadtree>";
- mesh->createSecondaryColors();
- mesh->setRenderMode();
- if(_glGenBuffersARB!=NULL && Renderer::info.var.useVBOs==true){
- mesh->createVBOs();
- mesh->updateSecondaryColorVBO();
- }
- // mesh->sortFacesByMaterial();
-
- if(mesh->numVertices==0){
- // printf("min: %f %f %f ; max: %f %f %f\n", min[0], min[1], min[2], max[0],max[1],max[2]);
- vectorInit3d(0.0f, 0.0f, 0.0f, min);
- vectorInit3d(0.0f, 0.0f, 0.0f, max);
- }
-
- min[1]=FLT_MAX;
- max[1]=-FLT_MAX;
- for(i=0;i<mesh->numVertices;i++){ // THINKABOUTME: numV==0???
- if(mesh->vertices[i*3+1] < min[1])
- min[1]=mesh->vertices[i*3+1];
-
- if(mesh->vertices[i*3+1] > max[1])
- max[1]=mesh->vertices[i*3+1];
-
- }
- min[1]-=0.1f; // THINKABOUTME
- max[1]+=0.1f;
- leafNode=true;
-
-
- }else{ // divide it further
- childs[QUADTREE_CHILD_LOWER_RIGHT]=new QuadtreeNode((Quadtree*)tree);
- childs[QUADTREE_CHILD_LOWER_RIGHT]->parent=this;
- vectorInit3d(min[0], min[1], min[2], childs[QUADTREE_CHILD_LOWER_RIGHT]->min);
- vectorInit3d((max[0]+min[0])*0.5f, max[1], (max[2]+min[2])*0.5f, childs[QUADTREE_CHILD_LOWER_RIGHT]->max);
-
- childs[QUADTREE_CHILD_LOWER_LEFT]=new QuadtreeNode((Quadtree*)tree);
- childs[QUADTREE_CHILD_LOWER_LEFT]->parent=this;
- vectorInit3d((max[0]+min[0])*0.5f, min[1], min[2], childs[QUADTREE_CHILD_LOWER_LEFT]->min);
- vectorInit3d(max[0], max[1], (max[2]+min[2])*0.5f, childs[QUADTREE_CHILD_LOWER_LEFT]->max);
-
- childs[QUADTREE_CHILD_UPPER_RIGHT]=new QuadtreeNode((Quadtree*)tree);
- childs[QUADTREE_CHILD_UPPER_RIGHT]->parent=this;
- vectorInit3d(min[0], min[1], (max[2]+min[2])*0.5f, childs[QUADTREE_CHILD_UPPER_RIGHT]->min);
- vectorInit3d((max[0]+min[0])*0.5f, max[1], max[2], childs[QUADTREE_CHILD_UPPER_RIGHT]->max);
-
- childs[QUADTREE_CHILD_UPPER_LEFT]=new QuadtreeNode((Quadtree*)tree);
- childs[QUADTREE_CHILD_UPPER_LEFT]->parent=this;
- vectorInit3d((max[0]+min[0])*0.5f, min[1], (max[2]+min[2])*0.5f, childs[QUADTREE_CHILD_UPPER_LEFT]->min);
- vectorInit3d(max[0], max[1], max[2], childs[QUADTREE_CHILD_UPPER_LEFT]->max);
-
- leafNode=false;
-
- min[1]=FLT_MAX;
- max[1]=-FLT_MAX;
- for(i=0;i<QUADTREE_NUM_CHILDS;i++){
- childs[i]->buildNode();
-
- if(childs[i]->min[1]<min[1])
- min[1]=childs[i]->min[1];
-
- if(childs[i]->max[1]>max[1])
- max[1]=childs[i]->max[1];
- }
- }
- }
-
- void QuadtreeNode::buildNeighbourhoodInfo(){
- vec3_t point, mid;
- float xSize=max[0]-min[0];
- float zSize=max[2]-min[2];
- vectorLinCombi3d(0.5, min, 0.5, max, mid);
-
- vectorInit3d(mid[0]-xSize, mid[1], mid[2], point);
- neighbours[QUADTREE_NEIGHBOUR_RIGHT]=(QuadtreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0]+xSize, mid[1], mid[2], point);
- neighbours[QUADTREE_NEIGHBOUR_LEFT]=(QuadtreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0], mid[1], mid[2]+zSize, point);
- neighbours[QUADTREE_NEIGHBOUR_UP]=(QuadtreeNode*)tree->getNodeContainingPoint(point, level);
-
- vectorInit3d(mid[0], mid[1], mid[2]-zSize, point);
- neighbours[QUADTREE_NEIGHBOUR_DOWN]=(QuadtreeNode*)tree->getNodeContainingPoint(point, level);
-
- tree->nodes[nodeId]=this;
-
- if(leafNode)
- return;
-
- for(int i=0;i<QUADTREE_NUM_CHILDS;i++){
- childs[i]->buildNeighbourhoodInfo();
- }
-
- }
-