/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2006 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: bottac@ee.ethz.ch */ #include "vector.h" #include "bsp_file.h" #include "bsp_manager.h" #include "bsp_tree_leaf.h" #include "p_node.h" #include "state.h" #include "debug.h" #include "material.h" #include "camera.h" #include "vertex_array_model.h" // STL Containers #include #include BspManager::BspManager() { // open a BSP file this->bspFile = new BspFile(); this->bspFile->read("/root/data/Kanti175.bsp"); this->bspFile->build_tree(); this->root = this->bspFile->get_root(); this->alreadyVisible = new bool [this->bspFile->numFaces]; } void BspManager::draw() { // Draw Debug Terrain /* this->bspFile->Materials[0]->select(); for(int i = 0; i < this->bspFile->numPatches ; i++) { this->bspFile->VertexArrayModels[i]->draw(); } */ // erase alreadyVisible for(int i = 0; i < this->bspFile->numFaces; i++) this->alreadyVisible[i] = false; float tmp = 0; this->opal.clear(); this->trasparent.clear(); // Find all visible faces... this->cam = State::getCamera()->getAbsCoor() ; this->ship = State::getCameraTargetNode()->getAbsCoor(); this->cam = State::getCameraTargetNode()->getAbsCoor(); this->viewDir= State::getCameraTarget()->getAbsCoor() - State::getCamera()->getAbsCoor() ; float d = (cam.x*viewDir.x + cam.y*viewDir.y + cam.z * viewDir.z); BspTreeNode* ActLeaf = this->getLeaf(this->bspFile->root, &ship); int viscluster = -1; viscluster =((leaf*)(this->bspFile->leaves))[ ActLeaf->leafIndex].cluster; // get the players cluster (viscluster) this->checkCollision(this->root, &this->cam); //!< Test Collision Detection if ((((int *)(this->bspFile->header))[35] == 0) || viscluster < 0) //!< if (sizeof(Visdata) == 0) { /** Do Frustum culling and draw 'em all **/ // Iterate through all Leafs for(int i = 0; i < this->bspFile->numLeafs ; i++ ) { // cluster = (this->bspFile->leaves)[i].cluster; leaf& curLeaf = (this->bspFile->leaves)[i]; // Iterate through all faces for (int j = 0; j < curLeaf.n_leaffaces ; ++j) { const int f = ( j + ((leaf *) (this->bspFile->leaves))[i].leafface) % this->bspFile->numFaces; if (f >=0 && !this->isAlreadyVisible(f)) { this->alreadyVisible[f] = true; /* if(ActLeaf->leafIndex == i) { this->alreadyVisible[i] = false; this->draw_debug_face(f); this->alreadyVisible[i] = true; } else */ addFace(f); // "visibleFaces.append(f)" } } } //for } else { int cluster; int seven = 7; unsigned char one = 1; unsigned int v; unsigned char visSet; // Iterate through all Leafs for(int i = 0; i < this->bspFile->numLeafs ; ++i ) { leaf& camLeaf = (this->bspFile->leaves)[ActLeaf->leafIndex] ; leaf& curLeaf = (this->bspFile->leaves)[i] ; cluster = curLeaf.cluster; if(cluster <0) continue; v = ((viscluster * ( ((int *)this->bspFile->visData)[1]) ) + (cluster / 8)); visSet =((unsigned char*) (this->bspFile->visData))[v+8]; if( ((visSet) & ((unsigned char)1 <<(unsigned char) (cluster & 7))) == 0 ) { // Iterate through all faces for (int j = 0; j < curLeaf.n_leaffaces ; ++j) { const int f = (j + curLeaf.leafface) % this->bspFile->numFaces; if (!this->isAlreadyVisible(f) && f>=0) { this->addFace(f); this->alreadyVisible[f] = true; } } }// if }//for }//else while(!this->opal.empty()) { this->draw_face(this->opal.front()); this->opal.pop_front(); } while(!this->trasparent.empty()) { this->draw_face(this->trasparent.back()); this->trasparent.pop_back(); } }//draw void BspManager::draw_leaf() {} void BspManager::draw_face(int curface) { face& curFace = (this->bspFile->faces)[curface]; const BspVertex* curVertex = (BspVertex *) this->bspFile->vertice; int stride = sizeof(BspVertex); // sizeof(Vertex) int offset = curFace.vertex; // PRINTF(0)("BSP Manager: "); // PRINTF(0)("BSP Manager: type: %i \n", curFace.texture); // if( curFace.texture < 0 ) return; if(curFace.type == 2) { this->draw_patch( &curFace); return; } if(curFace.type == 3) return; // if(this->bspFile->Materials[curFace.texture] != NULL) if(this->lastTex != curFace.texture) { this->bspFile->Materials[curFace.texture].mat->select(); this->lastTex = curFace.texture; } glEnableClientState(GL_VERTEX_ARRAY ); glEnableClientState(GL_TEXTURE_COORD_ARRAY ); glEnableClientState(GL_NORMAL_ARRAY ); // glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, stride, &(curVertex[offset].position[0])); // glClientActiveTextureARB(GL_TEXTURE0_ARB); glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[0])); // glClientActiveTextureARB(GL_TEXTURE1_ARB); // glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[1])); glNormalPointer( GL_FLOAT, stride, &(curVertex[offset].normal[0])); // glColorPointer(4, GL_BYTE, stride, &(curVertex[offset].color[0])); glDrawElements(GL_TRIANGLES, curFace.n_meshverts, GL_UNSIGNED_INT, &(((meshvert *)this->bspFile->meshverts) [curFace.meshvert])); glDisableClientState(GL_VERTEX_ARRAY ); glDisableClientState(GL_TEXTURE_COORD_ARRAY ); glDisableClientState(GL_NORMAL_ARRAY ); // glDisableClientState(GL_COLOR_ARRAY); } void BspManager::draw_debug_face(int curface) { face& curFace = (this->bspFile->faces)[curface]; const BspVertex* curVertex = (BspVertex *) this->bspFile->vertice; int stride = 44; // sizeof(Vertex) int offset = curFace.vertex; // PRINTF(0)("BSP Manager: "); // PRINTF(0)("BSP Manager: type: %i \n", curFace.texture); // if( curFace.texture < 0 ) return; if(curFace.type == 2) { this->draw_patch( &curFace); return; } if(curFace.type == 3) return; // if(this->bspFile->Materials[curFace.texture] != NULL) this->bspFile->Materials[2].mat->select(); this->lastTex = 2; glEnableClientState(GL_VERTEX_ARRAY ); glEnableClientState(GL_TEXTURE_COORD_ARRAY ); glEnableClientState(GL_NORMAL_ARRAY ); //glEnableClientState(GL_COLOR_ARRAY); // glEnableClientState(GL_VERTEX_ARRAY ); glVertexPointer(3, GL_FLOAT, stride, &(curVertex[offset].position[0])); // glClientActiveTextureARB(GL_TEXTURE0_ARB); glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[0])); // glClientActiveTextureARB(GL_TEXTURE1_ARB); // glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[1])); //glEnableClientState(GL_NORMAL_ARRAY ); glNormalPointer( GL_FLOAT, stride, &(curVertex[offset].normal[0])); // glColorPointer(4, GL_BYTE, stride, &(curVertex[offset].color[0])); glDrawElements(GL_TRIANGLES, curFace.n_meshverts, GL_UNSIGNED_INT, &(((meshvert *)this->bspFile->meshverts) [curFace.meshvert])); } void BspManager::draw_patch(face* Face) { if(this->lastTex != Face->texture) { this->bspFile->Materials[Face->texture].mat->select(); this->lastTex = Face->texture; } for(int i = 0; i < Face->n_meshverts ; i++) { //glFrontFace(GL_CW); //PRINTF(0)("BSP Manager: Face->size[0]: %i . \n", Face->size[0]); glEnableClientState(GL_VERTEX_ARRAY ); glEnableClientState(GL_TEXTURE_COORD_ARRAY ); glEnableClientState(GL_NORMAL_ARRAY ); glVertexPointer(3, GL_FLOAT,44, &((((BspVertex*)(this->bspFile->patchVertice))[8*8*(Face->meshvert+i)]).position[0])); glTexCoordPointer(2, GL_FLOAT, 44, &((((BspVertex*)(this->bspFile->patchVertice))[8*8*(Face->meshvert+i)]).texcoord[0][0])); glNormalPointer( GL_FLOAT, 44,&((((BspVertex*)(this->bspFile->patchVertice))[8*8*(Face->meshvert+i)]).normal[0]) ); // We'll need multitexture suport for lightning //glClientActiveTextureARB(GL_TEXTURE0_ARB); //glTexCoordPointer(2, GL_FLOAT,0, &vertex[0].textureCoord); //glClientActiveTextureARB(GL_TEXTURE1_ARB); //glTexCoordPointer(2, GL_FLOAT, sizeof(BSPVertex), &vertex[0].lightmapCoord); for(int row=0; row<7; ++row) { glDrawElements(GL_TRIANGLE_STRIP, 2*(8), GL_UNSIGNED_INT, & ( (((GLuint*) (this->bspFile->patchIndexes))[7*8*2*(Face->meshvert+i)+ row*2*8] )) ); } //glFrontFace(GL_CCW); } } bool BspManager::isAlreadyVisible(int Face) { return this->alreadyVisible[Face]; } BspTreeNode* BspManager::getLeaf(BspTreeNode* node, Vector* cam) { float dist = 0; while(!(node->isLeaf)) { dist = (node->plane.x * this->cam.x + node->plane.y*this->cam.y + node->plane.z*this->cam.z) - node->d; if(dist >= 0.0f) { node = node->left; } else { node = node->right; } } return node; } void BspManager::checkCollision(BspTreeNode* node, Vector* cam) { float dist = 0; if(!(node->isLeaf)) { dist = (node->plane.x * this->cam.x + node->plane.y*this->cam.y + node->plane.z*this->cam.z) - node->d; if(dist > 4.0f) { checkCollision(node->left,cam); return; } if(dist < -4.0f) { checkCollision(node->right,cam); return; } if(dist<=4.0f && dist >= -4.0f) { checkCollision(node->left,cam); checkCollision(node->right,cam); return; } return; } else { leaf& camLeaf = ((leaf *)(this->bspFile->leaves))[(node->leafIndex ) ]; if (camLeaf.cluster < 0) {this->drawDebugCube(&this->cam);} /* for(int i = 0; i < camLeaf.n_leafbrushes && i < 10; i++ ) { brush& curBrush = ((brush*)(this->bspFile->brushes))[(camLeaf.leafbrush_first +i)%this->bspFile->numLeafBrushes]; if(curBrush.n_brushsides < 0) return; for(int j = 0; j < curBrush.n_brushsides; j++) { float dist = -0.1; brushside& curBrushSide = ((brushside*)(this->bspFile->brushSides))[(curBrush.brushside +j)%this->bspFile->numBrushSides]; plane& testPlane = ((plane*)(this->bspFile->planes))[curBrushSide.plane % this->bspFile->numPlanes]; dist = testPlane.x * this->cam.x + testPlane.y * this->cam.y + testPlane.z * this->cam.z -testPlane.d ; if(dist < -0.01f) dist = -1.0f *dist; if(dist < 1.0f){ this->drawDebugCube(&this->cam); return; } } } */ } return; } void BspManager::drawDebugCube(Vector* cam) { glBegin(GL_QUADS); // Bottom Face. Red, 75% opaque, magnified texture glNormal3f( 0.0f, -1.0f, 0.0f); // Needed for lighting glColor4f(0.9,0.2,0.2,.75); // Basic polygon color glTexCoord2f(0.800f, 0.800f); glVertex3f(cam->x-1.0f, cam->y-1.0f,cam->z -1.0f); glTexCoord2f(0.200f, 0.800f); glVertex3f(cam->x+1.0f, cam->y-1.0f,cam->z -1.0f); glTexCoord2f(0.200f, 0.200f); glVertex3f(cam->x+ 1.0f,cam->y -1.0f,cam->z + 1.0f); glTexCoord2f(0.800f, 0.200f); glVertex3f(cam->x-1.0f, cam->y-1.0f, cam->z + 1.0f); // Top face; offset. White, 50% opaque. glNormal3f( 0.0f, 1.0f, 0.0f); glColor4f(0.5,0.5,0.5,.5); glTexCoord2f(0.005f, 1.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z -1.0f); glTexCoord2f(0.005f, 0.005f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z +1.0f); glTexCoord2f(1.995f, 0.005f); glVertex3f(cam->x+ 1.0f, cam->y+1.0f, cam->z +1.0f); glTexCoord2f(1.995f, 1.995f); glVertex3f(cam->x+ 1.0f, cam->y+ 1.0f, cam->z -1.0f); // Far face. Green, 50% opaque, non-uniform texture cooridinates. glNormal3f( 0.0f, 0.0f,-1.0f); glColor4f(0.2,0.9,0.2,.5); glTexCoord2f(0.995f, 0.005f); glVertex3f(cam->x-1.0f, cam->y-1.0f, cam->z -1.3f); glTexCoord2f(2.995f, 2.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z -1.3f); glTexCoord2f(0.005f, 0.995f); glVertex3f(cam->x+ 1.0f,cam->y+ 1.0f, cam->z -1.3f); glTexCoord2f(0.005f, 0.005f); glVertex3f( cam->x+1.0f,cam->y -1.0f, cam->z -1.3f); // Right face. Blue; 25% opaque glNormal3f( 1.0f, 0.0f, 0.0f); glColor4f(0.2,0.2,0.9,.25); glTexCoord2f(0.995f, 0.005f); glVertex3f(cam->x+ 1.0f,cam->y -1.0f, cam->z -1.0f); glTexCoord2f(0.995f, 0.995f); glVertex3f(cam->x+ 1.0f, cam->y+ 1.0f, cam->z -1.0f); glTexCoord2f(0.005f, 0.995f); glVertex3f(cam->x+ 1.0f, cam->y+ 1.0f, cam->z + 1.0f); glTexCoord2f(0.005f, 0.005f); glVertex3f(cam->x+ 1.0f, cam->y-1.0f, cam->z +1.0f); // Front face; offset. Multi-colored, 50% opaque. glNormal3f( 0.0f, 0.0f, 1.0f); glColor4f( 0.9f, 0.2f, 0.2f, 0.5f); glTexCoord2f( 0.005f, 0.005f); glVertex3f(cam->x-1.0f, cam->y-1.0f, cam->z +1.0f); glColor4f( 0.2f, 0.9f, 0.2f, 0.5f); glTexCoord2f( 0.995f, 0.005f); glVertex3f(cam->x+ 1.0f, cam->y-1.0f, cam->z +1.0f); glColor4f( 0.2f, 0.2f, 0.9f, 0.5f); glTexCoord2f( 0.995f, 0.995f); glVertex3f( cam->x+1.0f, cam->y+1.0f, cam->z +1.0f); glColor4f( 0.1f, 0.1f, 0.1f, 0.5f); glTexCoord2f( 0.005f, 0.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z +1.0f); // Left Face; offset. Yellow, varying levels of opaque. glNormal3f(-1.0f, 0.0f, 0.0f); glColor4f(0.9,0.9,0.2,0.0); glTexCoord2f(0.005f, 0.005f); glVertex3f(cam->x-1.0f, cam->y-1.0f, cam->z -1.0f); glColor4f(0.9,0.9,0.2,0.66); glTexCoord2f(0.995f, 0.005f); glVertex3f(cam->x-1.0f,cam->y -1.0f, cam->z +1.0f); glColor4f(0.9,0.9,0.2,1.0); glTexCoord2f(0.995f, 0.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z +1.0f); glColor4f(0.9,0.9,0.2,0.33); glTexCoord2f(0.005f, 0.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z -1.0f); glEnd(); } void BspManager::addFace(int f) { face& curFace = ((face *)(this->bspFile->faces))[f]; if(this->bspFile->Materials[curFace.texture].alpha) this->trasparent.push_back(f); else this->opal.push_back(f); }