Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/bsp/bsp_manager.cc @ 10598

Last change on this file since 10598 was 10519, checked in by patrick, 18 years ago

emitter fix

File size: 56.3 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2006 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: bottac@ee.ethz.ch
13
14   Inspired by:
15   Rendering Q3 Maps by Morgan McGuire                  http://graphics.cs.brown.edu/games/quake/quake3.html
16   Unofficial Quake 3 Map Specs by Kekoa Proudfoot      http://graphics.stanford.edu/~kekoa/q3/
17
18   Collision detection adapted from:
19   Quake 3 Collision Detection by Nathan Ostgard        http://www.devmaster.net/articles/quake3collision/
20*/
21
22
23#include "limits.h"
24#include "vector.h"
25#include "bsp_file.h"
26#include "bsp_manager.h"
27#include "bsp_tree_leaf.h"
28#include "p_node.h"
29#include "state.h"
30#include "debug.h"
31#include "material.h"
32#include "camera.h"
33#include "vertex_array_model.h"
34#include "world_entities/player.h"
35#include "world_entities/playable.h"
36
37// STL Containers
38#include <vector>
39#include <deque>
40#include "movie_player.h"
41
42#include "world_entity.h"
43
44#include "util/loading/resource_manager.h"
45#include "util/loading/load_param.h"
46#include "util/loading/factory.h"
47
48#include "aabb.h"
49#include "cr_engine.h"
50#include "collision_tube.h"
51
52
53//CREATE_FACTORY( BspManager, CL_BSP_MODEL);
54
55BspManager::BspManager(WorldEntity* parent)
56{
57
58  this->lastTex = -1;
59  this->parent = parent;
60  /*// open a BSP file
61  this->bspFile = new BspFile();
62  this->bspFile->scale = 0.4f;
63  this->bspFile->read(ResourceManager::getFullName("test.bsp").c_str());
64  this->bspFile->build_tree();
65  this->root  = this->bspFile->get_root();
66  this->alreadyVisible = new bool [this->bspFile->numFaces];
67  */
68
69}
70
71
72/*
73BspManager::BspManager(const TiXmlElement* root)
74{
75
76
77  if( root != NULL)
78    this->loadParams(root);
79
80  CDEngine::getInstance()->setBSPModel(this);
81} */
82
83BspManager::~BspManager()
84{
85  if(this->bspFile)
86    delete this->bspFile;
87}
88
89int BspManager::load(const char* fileName, float scale)
90{
91  // open a BSP file
92
93
94  this->bspFile = new BspFile();
95  this->bspFile->scale =  scale;
96  if(this->bspFile->read(Resources::ResourceManager::getInstance()->prependAbsoluteMainPath(fileName).c_str()) == -1)
97    return -1;
98
99  this->bspFile->build_tree();
100  this->root  = this->bspFile->get_root();
101  this->alreadyVisible = new bool [this->bspFile->numFaces];
102
103  this->outputFraction = 1.0f;
104
105  return 0;
106}
107
108
109/*
110BspManager::BspManager(const char* fileName, float scale)
111{
112  // open a BSP file
113  this->bspFile = new BspFile();
114  this->bspFile->scale =  scale;
115  this->bspFile->read(fileName);
116  this->bspFile->build_tree();
117  this->root  = this->bspFile->get_root();
118  this->alreadyVisible = new bool [this->bspFile->numFaces];
119
120  CDEngine::getInstance()->setBSPModel(this);
121}
122*/
123
124const void BspManager::tick(float time)
125{
126
127  if(!this->bspFile->MovieMaterials.empty()) {
128    ::std::vector<MoviePlayer *>::iterator it = this->bspFile->MovieMaterials.begin() ;
129    while(it != this->bspFile->MovieMaterials.end()) {
130      (*it)->tick(time);
131      it++;
132    }
133    //this->bspFile->MovieMaterials.front()->tick(time );
134
135
136  }
137
138}
139const void BspManager::draw()
140{
141
142  /*
143  this->drawDebugCube(&this->out);
144  this->out1 = this->out;
145  this->out2 = this->out;
146  if(this->collPlane != NULL) {
147    this->out1.x += this->collPlane->x*5.0;
148    this->out1.y += this->collPlane->y*5.0;
149    this->out1.z += this->collPlane->z*5.0;
150
151    this->out2.x += this->collPlane->x*10.0;
152    this->out2.y += this->collPlane->y*10.0;
153    this->out2.z += this->collPlane->z*10.0;
154  }
155  this->drawDebugCube(&this->out1);
156  this->drawDebugCube(&this->out2);
157
158  */
159
160
161  // Draw Debug Terrain
162  /*
163  this->bspFile->Materials[0]->select();
164  for(int i = 0; i <  this->bspFile->numPatches ; i++)
165        {
166                this->bspFile->VertexArrayModels[i]->draw();
167
168        }
169  */
170
171
172  this->lastTex = -1;
173  // erase alreadyVisible
174  for(int i = 0; i < this->bspFile->numFaces; i++) this->alreadyVisible[i] = false;
175  float tmp = 0;
176  //this->opal.clear();
177  //this->trasparent.clear();
178  // Find all visible faces...
179
180  this->cam = State::getCamera()->getAbsCoor() ;
181  //this->ship = State::getCameraTargetNode()->getAbsCoor();
182
183
184
185
186
187  this->viewDir=    State::getCamera()->getAbsDirX();
188  float d = (cam.x*viewDir.x + cam.y*viewDir.y + cam.z * viewDir.z);
189
190  BspTreeNode*  ActLeaf = this->getLeaf(this->bspFile->root, &ship);
191  int viscluster = -1;
192  viscluster =((leaf*)(this->bspFile->leaves))[ ActLeaf->leafIndex].cluster; // get the players cluster (viscluster)
193
194
195
196
197  // this->checkCollision(this->root, &this->cam);   //!< Test Collision Detection
198
199
200  this->outputStartsOut = true;
201  this->outputAllSolid = false;
202  this->outputFraction = 1.0f;
203
204  if ( viscluster < 0  || ((int *)(this->bspFile->header))[35] == 0 )  //!< if (sizeof(Visdata) == 0)
205  {
206
207
208
209    // Iterate through all Leafs
210    for(int i = 0; i <  this->bspFile->numLeafs   ; i++ )
211    {
212      // cluster =  (this->bspFile->leaves)[i].cluster;
213      leaf& curLeaf = (this->bspFile->leaves)[i];
214      if(curLeaf.cluster<0) continue;
215
216      /** Do Frustum culling and draw 'em all **/
217
218      Vector dir = State::getCameraNode()->getAbsDirX();
219
220      float dist =  dir.x*this->cam.x +dir.y*this->cam.y +dir.z*this->cam.z;
221      //if(dist < 0) dist = -dist;
222      const float dMins = dir.x*(float)curLeaf.mins[0] +dir.y*(float)curLeaf.mins[1] +dir.z*(float)curLeaf.mins[2] - dist ;
223      const float dMaxs = dir.x*(float)curLeaf.maxs[0] +dir.y*(float)curLeaf.maxs[1] +dir.z*(float)curLeaf.maxs[2] - dist ;
224
225      if(dMins < -300.0 && dMaxs < -300.0) {
226        continue;
227      }
228      if( (this->cam - Vector(curLeaf.mins[0],curLeaf.mins[1], curLeaf.mins[2])).len() > 2000  && (this->cam - Vector(curLeaf.maxs[0],curLeaf.maxs[1], curLeaf.maxs[2])).len() > 2000) {
229        continue;
230      }
231
232
233      // Iterate through all faces
234      for (int j = 0; j < curLeaf.n_leaffaces ; ++j) {
235        const int g = (j +  curLeaf.leafface);
236        const int f = ((int *)this->bspFile->leafFaces)[g];
237        if (f >=0 && !this->isAlreadyVisible(f)) {
238          this->alreadyVisible[f] = true;
239          addFace(f); // "visibleFaces.append(f)"
240        }
241      }
242
243
244
245
246    } //for
247  } else {
248
249
250    unsigned int v;
251    unsigned char  visSet;
252
253    // Iterate through all Leafs
254
255    for(int i = 0; i <  this->bspFile->numLeafs   ; ++i ) {
256      leaf& camLeaf =  (this->bspFile->leaves)[ActLeaf->leafIndex] ;
257      leaf& curLeaf =  (this->bspFile->leaves)[i] ;
258      int& cluster =  curLeaf.cluster;
259
260      if(cluster < 0) continue;
261      v = ((viscluster *  ( ((int *)this->bspFile->visData)[1]) ) + (cluster / 8));
262      visSet =((char*) (this->bspFile->visData))[v + 8];
263
264      // gets bit of visSet
265      if( ((visSet) & (1 << (cluster &  7))) != 0 ) {
266
267        // Frustum culling
268
269        Vector dir;
270        dir.x = State::getCameraNode()->getAbsDirX().x;
271        dir.y =  State::getCameraNode()->getAbsDirX().y;
272        dir.z =  State::getCameraNode()->getAbsDirX().z;
273        const float dist =  dir.x*this->cam.x +dir.y*this->cam.y +dir.z*this->cam.z;
274        //if(dist < 0) dist = -dist;
275        const float dMins = dir.x*(float)curLeaf.mins[0] +dir.y*(float)curLeaf.mins[1] +dir.z*(float)curLeaf.mins[2] - dist;
276        const float dMaxs = dir.x*(float)curLeaf.maxs[0] +dir.y*(float)curLeaf.maxs[1] +dir.z*(float)curLeaf.maxs[2] - dist;
277
278        if(dMins < -70.0 && dMaxs < -70.0) {
279          continue;
280        }
281
282
283        // Iterate through all faces
284        for (int j = 0; j < curLeaf.n_leaffaces ; ++j) {
285          const int g = (j +  curLeaf.leafface);
286          const int f = ((int *)this->bspFile->leafFaces)[g];
287
288          if (!this->isAlreadyVisible(f) && f>=0) {
289            this->addFace(f);
290            this->alreadyVisible[f] = true;
291          }
292
293        }
294
295      }// if
296
297    }//for
298
299  }//else
300
301
302  // now sort the transparent faces in the right order
303  if (this->sortTransparency == 1) {
304      int size = this->trasparent.size();
305     
306      // bubble sort
307      bool hasSwapped = true;
308      Vector v1, v2;
309
310      // initialize distance array
311      float * distToPlayer = new float [size];
312      for (int i = 0; i < size; i++)
313      {
314          face& fac1 =  (this->bspFile->faces)[this->trasparent[i]];
315//          face& fac2 =  (this->bspFile->faces)[this->trasparent[i+1]];
316
317          // get center of face 1
318          const BspVertex* curVertex = (BspVertex *) this->bspFile->vertice;
319
320          if (this->sortTransparencyMore == 1)
321          {
322              // assign the values of the vertices
323              float maxDist = 0;
324              float curDist = 0;
325              int maxVert = fac1.vertex;
326              for (int v = 0; v < fac1.n_vertexes; v++)
327              {
328                    v1(curVertex[fac1.vertex + v].position[0], curVertex[fac1.vertex + v].position[1], curVertex[fac1.vertex + v].position[2]);
329                    curDist = (this->cam - v1).len();
330                    if (curDist > maxDist)
331                    {
332                        maxDist = curDist;
333                        maxVert = fac1.vertex + v;
334                    }
335              }
336              v1(curVertex[maxVert].position[0], curVertex[maxVert].position[1], curVertex[maxVert].position[2]);
337          }
338          else
339          {
340              v1(curVertex[fac1.vertex].position[0], curVertex[fac1.vertex].position[1], curVertex[fac1.vertex].position[2]);
341          }
342
343          // relativly to observer
344          v1 = this->cam - v1;
345
346          // save in array
347          distToPlayer[i] = v1.len();
348      }
349
350      while( hasSwapped)
351      {
352        hasSwapped = false;
353
354        for( int i = 0; i < size - 1; i++)
355        {
356/*
357          // sorting test
358          face& fac1 =  (this->bspFile->faces)[this->trasparent[i]];
359          face& fac2 =  (this->bspFile->faces)[this->trasparent[i+1]];
360
361          // get center of face 1
362          const BspVertex* curVertex = (BspVertex *) this->bspFile->vertice;
363         
364          if (this->sortTransparencyMore == 1)
365          {
366              // assign the values of the vertices
367              float maxDist = 0;
368              float curDist = 0;
369              int maxVert = fac1.vertex;
370              for (int v = 0; v < fac1.n_vertexes; v++)
371              {
372                    v1(curVertex[fac1.vertex + v].position[0], curVertex[fac1.vertex + v].position[1], curVertex[fac1.vertex + v].position[2]);
373                    curDist = (this->cam - v1).len();
374                    if (curDist > maxDist)
375                    {
376                        maxDist = curDist;
377                        maxVert = fac1.vertex + v;
378                    }
379              }
380              v1(curVertex[maxVert].position[0], curVertex[maxVert].position[1], curVertex[maxVert].position[2]);
381
382              maxDist = 0;
383              curDist = 0;
384              maxVert = fac1.vertex;
385              for (int v = 0; v < fac2.n_vertexes; v++)
386              {
387                    v2(curVertex[fac2.vertex + v].position[0], curVertex[fac2.vertex + v].position[1], curVertex[fac2.vertex + v].position[2]);
388                    curDist = (this->cam - v2).len();
389                    if (curDist > maxDist)
390                    {
391                        maxDist = curDist;
392                        maxVert = fac2.vertex + v;
393                    }
394              }
395              v2(curVertex[maxVert].position[0], curVertex[maxVert].position[1], curVertex[maxVert].position[2]);
396          }
397          else
398          {
399              v1(curVertex[fac1.vertex].position[0], curVertex[fac1.vertex].position[1], curVertex[fac1.vertex].position[2]);
400              v2(curVertex[fac2.vertex].position[0], curVertex[fac2.vertex].position[1], curVertex[fac2.vertex].position[2]);
401          }
402
403          // relativly to observer
404          v1 = this->cam - v1;
405          v2 = this->cam - v2;
406
407
408*/
409          // swap if necessary
410//          if( v1.len() - v2.len() > 1)
411          if( distToPlayer[i] - distToPlayer[i+1] > 1)
412          {
413            // swap elements
414            float tmp1 = distToPlayer[i+1];
415            distToPlayer[i+1] = distToPlayer[i];
416            distToPlayer[i] = tmp1;
417           
418            int tmp2 = this->trasparent[i+1];
419            this->trasparent[i+1] = this->trasparent[i];
420            this->trasparent[i] = tmp2;
421
422            //printf( "has swapped: %d\n", i );
423
424            //v1.debug();
425            //v2.debug();
426            hasSwapped = true;
427          }
428        }
429      }
430      //printf("hasSwapped == false\n");
431  }
432
433
434  // draw all solid faces
435  while(!this->opal.empty()) {
436    this->draw_face(this->opal.back()); // front()
437    this->opal.pop_back();              // pop_back()
438  }
439
440  // draw all transparent faces
441  while(!this->trasparent.empty()) {
442    this->draw_face(this->trasparent.back());
443    this->trasparent.pop_back();
444  }
445  //glEnable(GL_TEXTURE_2D);
446  glActiveTextureARB(GL_TEXTURE1_ARB);
447  glBindTexture(GL_TEXTURE_2D, this->bspFile->whiteLightMap);
448
449
450
451}//draw
452
453
454
455void BspManager::draw_face(int curface)
456{
457  face& curFace =  (this->bspFile->faces)[curface];
458  const BspVertex* curVertex = (BspVertex *) this->bspFile->vertice;
459  int stride = sizeof(BspVertex);  // sizeof(Vertex)
460  int offset    = curFace.vertex;
461  if (curFace.effect != -1) return;
462  // PRINTF(0)("BSP Manager: ");
463  // PRINTF(0)("BSP Manager: type: %i  \n", curFace.texture);
464
465  //  if(  curFace.texture < 0 ) return;
466  if(curFace.type == 2) {
467    this->draw_patch( &curFace);
468    return;
469  }
470  // if(curFace.type != 1) return;
471  if((char*)(this->bspFile->textures)[curFace.texture*72]== 0) return;
472
473  if(this->lastTex != curFace.texture) {
474    if(this->bspFile->Materials[curFace.texture].animated) {
475      // glBlendFunc(GL_ZERO,GL_ONE);
476
477
478
479      if(this->bspFile->Materials[curFace.texture].aviMat->getStatus() == 2) this->bspFile->Materials[curFace.texture].aviMat->start(0);
480      //this->bspFile->Materials[curFace.texture].aviMat->tick(0.005);
481      int n =  this->bspFile->Materials[curFace.texture].aviMat->getTexture();
482      glActiveTextureARB(GL_TEXTURE0_ARB);
483      glBindTexture(GL_TEXTURE_2D, n );
484      this->lastTex = curFace.texture;
485
486    } else {
487      this->bspFile->Materials[curFace.texture].mat->select();
488      this->lastTex = curFace.texture;
489    }
490  }
491
492  if(curFace.lm_index < 0) {
493    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
494    glActiveTextureARB(GL_TEXTURE1_ARB);
495    glBindTexture(GL_TEXTURE_2D, this->bspFile->whiteLightMap );
496    glEnable(GL_TEXTURE_2D);
497  } else {
498    // glEnable(GL_BLEND);
499    //glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
500    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
501    glActiveTextureARB(GL_TEXTURE1_ARB);
502    glBindTexture(GL_TEXTURE_2D, this->bspFile->glLightMapTextures[curFace.lm_index]);
503    glEnable(GL_TEXTURE_2D);
504    //  glDisable(GL_BLEND);
505  }
506
507  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
508
509  // glColor4f(3.0,3.0,3.0,1.0);
510  glEnableClientState(GL_VERTEX_ARRAY );
511  glEnableClientState(GL_TEXTURE_COORD_ARRAY );
512  glEnableClientState(GL_NORMAL_ARRAY );
513  //  glEnableClientState(GL_COLOR_ARRAY);
514
515
516  glVertexPointer(3, GL_FLOAT, stride, &(curVertex[offset].position[0]));
517
518  glClientActiveTextureARB(GL_TEXTURE0_ARB);
519  glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[0]));
520  //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
521
522  glClientActiveTextureARB(GL_TEXTURE1_ARB);
523  glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[1]));
524  //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
525
526
527  glNormalPointer( GL_FLOAT, stride, &(curVertex[offset].normal[0]));
528  // glColorPointer(4, GL_BYTE, stride, &(curVertex[offset].color[0]));
529  glDrawElements(GL_TRIANGLES, curFace.n_meshverts,
530                 GL_UNSIGNED_INT, &(((meshvert *)this->bspFile->meshverts) [curFace.meshvert]));
531
532  glDisableClientState(GL_TEXTURE0_ARB);
533  glDisableClientState(GL_TEXTURE1_ARB);
534  glDisableClientState(GL_VERTEX_ARRAY );
535  glDisableClientState(GL_TEXTURE_COORD_ARRAY );
536  glDisableClientState(GL_NORMAL_ARRAY );
537  // glDisableClientState(GL_COLOR_ARRAY);
538
539}
540
541
542void BspManager::draw_debug_face(int curface)
543{
544  face& curFace =  (this->bspFile->faces)[curface];
545  const BspVertex* curVertex = (BspVertex *) this->bspFile->vertice;
546  int stride = 44;  // sizeof(Vertex)
547  int offset    = curFace.vertex;
548
549  // PRINTF(0)("BSP Manager: ");
550  // PRINTF(0)("BSP Manager: type: %i  \n", curFace.texture);
551
552  //  if(  curFace.texture < 0 ) return;
553  if(curFace.type == 2) {
554    this->draw_patch( &curFace);
555    return;
556  }
557  if(curFace.type == 3) return;
558  // if(this->bspFile->Materials[curFace.texture] != NULL)
559
560  this->bspFile->Materials[2].mat->select();
561  this->lastTex = 2;
562
563  glEnableClientState(GL_VERTEX_ARRAY );
564  glEnableClientState(GL_TEXTURE_COORD_ARRAY );
565  glEnableClientState(GL_NORMAL_ARRAY );
566  //glEnableClientState(GL_COLOR_ARRAY);
567  // glEnableClientState(GL_VERTEX_ARRAY );
568  glClientActiveTextureARB(GL_TEXTURE0_ARB);
569  glVertexPointer(3, GL_FLOAT, stride, &(curVertex[offset].position[0]));
570  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
571  // glClientActiveTextureARB(GL_TEXTURE0_ARB);
572  glClientActiveTextureARB(GL_TEXTURE1_ARB);
573  glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[0]));
574  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
575  // glClientActiveTextureARB(GL_TEXTURE1_ARB);
576  // glTexCoordPointer(2, GL_FLOAT, stride, &(curVertex[offset].texcoord[1]));
577  //glEnableClientState(GL_NORMAL_ARRAY );
578
579  glNormalPointer( GL_FLOAT, stride, &(curVertex[offset].normal[0]));
580  //  glColorPointer(4, GL_BYTE, stride, &(curVertex[offset].color[0]));
581  glDrawElements(GL_TRIANGLES, curFace.n_meshverts,
582                 GL_UNSIGNED_INT, &(((meshvert *)this->bspFile->meshverts) [curFace.meshvert]));
583
584}
585
586void BspManager::draw_patch(face* Face)
587{
588  if(this->lastTex != Face->texture) {
589    this->bspFile->Materials[Face->texture].mat->select();
590    this->lastTex = Face->texture;
591  }
592  if (Face->effect != -1) return;
593
594
595  if(Face->lm_index < 0) {
596    glActiveTextureARB(GL_TEXTURE1_ARB);
597    glBindTexture(GL_TEXTURE_2D, this->bspFile->whiteLightMap);
598    glEnable(GL_TEXTURE_2D);
599  } else {
600    glActiveTextureARB(GL_TEXTURE1_ARB);
601    glBindTexture(GL_TEXTURE_2D, this->bspFile->glLightMapTextures[Face->lm_index]);
602    glEnable(GL_TEXTURE_2D);
603  }
604  //glColor4f(3.0,3.0,3.0,1.0);
605
606  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
607  glEnable( GL_AUTO_NORMAL);
608  glEnableClientState(GL_VERTEX_ARRAY );
609  glEnableClientState(GL_TEXTURE_COORD_ARRAY );
610  for(int i = Face->n_meshverts -1; i >=0   ; i--) {
611    //glFrontFace(GL_CW);
612    //PRINTF(0)("BSP Manager: Face->size[0]: %i . \n", Face->size[0]);
613
614
615    //glEnableClientState(GL_NORMAL_ARRAY );
616
617    glVertexPointer(3, GL_FLOAT,44, &((((BspVertex*)(this->bspFile->patchVertice))[8*8*(Face->meshvert+i)]).position[0]));
618
619
620    glClientActiveTextureARB(GL_TEXTURE0_ARB);
621    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
622    glTexCoordPointer(2, GL_FLOAT, 44, &((((BspVertex*)(this->bspFile->patchVertice))[8*8*(Face->meshvert+i)]).texcoord[0][0]));
623
624
625
626    glClientActiveTextureARB(GL_TEXTURE1_ARB);
627    glTexCoordPointer(2, GL_FLOAT, 44, &((((BspVertex*)(this->bspFile->patchVertice))[8*8*(Face->meshvert+i)]).texcoord[1][0]));
628    //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
629
630
631    //  glNormalPointer( GL_FLOAT, 44,&((((BspVertex*)(this->bspFile->patchVertice))[8*8*(Face->meshvert+i)]).normal[0]) );
632
633
634
635
636    for(int row=6; row>=0; --row) {
637      glDrawElements(GL_TRIANGLE_STRIP, 2*(8), GL_UNSIGNED_INT,
638                     & (     (((GLuint*)  (this->bspFile->patchIndexes))[7*8*2*(Face->meshvert+i)+ row*2*8]  ))  );
639    }
640
641    //glFrontFace(GL_CCW);
642  }
643  glDisableClientState(GL_TEXTURE0_ARB);
644  glDisableClientState(GL_TEXTURE1_ARB);
645  glDisable(GL_AUTO_NORMAL);
646  glDisableClientState(GL_VERTEX_ARRAY );
647  glDisableClientState(GL_TEXTURE_COORD_ARRAY );
648
649
650}
651
652bool BspManager::isAlreadyVisible(int Face)
653{
654  return this->alreadyVisible[Face];
655}
656
657
658BspTreeNode*  BspManager::getLeaf(BspTreeNode* node, Vector* cam)
659{
660  float dist = 0;
661  while(!(node->isLeaf)) {
662    dist = (node->plane.x * this->cam.x + node->plane.y*this->cam.y + node->plane.z*this->cam.z) - node->d;
663    if(dist >= 0.0f) {
664      node = node->left;
665    } else {
666      node = node->right;
667    }
668  }
669  return  node;
670}
671
672void BspManager::checkBrushRay(brush* curBrush)
673{
674  float EPSILON = 0.000001;
675  float startDistance;
676  float endDistance;
677
678  float startFraction = -1.0f;
679  float endFraction = 1.0f;
680  bool startsOut = false;
681  bool endsOut = false;
682
683  Vector inputStart = State::getCameraTargetNode()->getLastAbsCoor();
684  Vector inputEnd   = State::getCameraTargetNode()->getAbsCoor();
685
686  for (int i = 0; i < curBrush->n_brushsides; i++) {
687    brushside& curBrushSide =   this->bspFile->brushSides[curBrush->brushside + i]   ;
688    plane& curPlane  =   this->bspFile->planes[curBrushSide.plane] ;
689
690    startDistance = inputStart.x * curPlane.x + inputStart.y * curPlane.y+ inputStart.z * curPlane.z - curPlane.d;
691    endDistance = inputEnd.x * curPlane.x +inputEnd.y * curPlane.y +inputEnd.z * curPlane.z -curPlane.d;
692
693    if (startDistance > 0)
694      startsOut = true;
695    if (endDistance > 0)
696      endsOut = true;
697
698    // make sure the trace isn't completely on one side of the brush
699    if (startDistance > 0 && endDistance > 0) {   // both are in front of the plane, its outside of this brush
700      return;
701    }
702    if (startDistance <= 0 && endDistance <= 0) {   // both are behind this plane, it will get clipped by another one
703      continue;
704    }
705
706    // MMM... BEEFY
707    if (startDistance > endDistance) {   // line is entering into the brush
708      float fraction = (startDistance - EPSILON) / (startDistance - endDistance);  // *
709      if (fraction > startFraction)
710        startFraction = fraction;
711      // don't store plane
712      // this->collPlane = &curPlane;
713
714    } else {   // line is leaving the brush
715      float fraction = (startDistance + EPSILON) / (startDistance - endDistance);  // *
716      if (fraction < endFraction)
717        endFraction = fraction;
718      // don't store plane
719      //this->collPlane = & curPlane;
720
721    }
722
723  }
724  if (startsOut == false) {
725    this->outputStartsOut = false;
726    if (endsOut == false)
727      this->outputAllSolid = true;
728    return;
729  }
730
731  if (startFraction < endFraction) {
732    if (startFraction > -1.0f && startFraction < outputFraction) {
733      if (startFraction < 0)
734        startFraction = 0;
735      this->outputFraction = startFraction;
736    }
737  }
738
739}
740
741void BspManager::checkBrushRayN(brush* curBrush)
742{
743  float EPSILON = 0.000001;
744  float startDistance;
745  float endDistance;
746
747  float startFraction = -1.0f;
748  float endFraction = 1.0f;
749  bool  startsOut = false;
750  bool  endsOut = false;
751
752  // Vector inputStart = State::getCameraTargetNode()->getLastAbsCoor();
753  // Vector inputEnd   = State::getCameraTargetNode()->getAbsCoor();
754
755  for (int i = 0; i < curBrush->n_brushsides; i++) {
756    brushside& curBrushSide =   this->bspFile->brushSides[curBrush->brushside + i]   ;
757    plane& curPlane  =   this->bspFile->planes[curBrushSide.plane] ;
758
759    startDistance = inputStart.x * curPlane.x + inputStart.y * curPlane.y+ inputStart.z * curPlane.z - curPlane.d;
760    endDistance = inputEnd.x * curPlane.x +inputEnd.y * curPlane.y +inputEnd.z * curPlane.z -curPlane.d;
761
762    if (startDistance > 0)
763      startsOut = true;
764    if (endDistance > 0)
765      endsOut = true;
766
767    // make sure the trace isn't completely on one side of the brush
768    if (startDistance > 0 && endDistance > 0) {   // both are in front of the plane, its outside of this brush
769      return;
770    }
771    if (startDistance <= 0 && endDistance <= 0) {   // both are behind this plane, it will get clipped by another one
772      continue;
773    }
774
775    // MMM... BEEFY
776    if (startDistance > endDistance) {   // line is entering into the brush
777      float fraction = (startDistance - EPSILON) / (startDistance - endDistance);  // *
778      if (fraction > startFraction)
779        startFraction = fraction;
780      // store plane
781      this->collPlane = &curPlane;
782
783    } else {   // line is leaving the brush
784      float fraction = (startDistance + EPSILON) / (startDistance - endDistance);  // *
785      if (fraction < endFraction)
786        endFraction = fraction;
787      // store plane
788      this->collPlane = & curPlane;
789
790    }
791
792  }
793  if (startsOut == false) {
794    this->outputStartsOut = false;
795    if (endsOut == false)
796      this->outputAllSolid = true;
797    return;
798  }
799
800  if (startFraction < endFraction) {
801    if (startFraction > -1.0f && startFraction < outputFraction) {
802      if (startFraction < 0)
803        startFraction = 0;
804      this->outputFraction = startFraction;
805    }
806  }
807
808}
809
810void BspManager::checkBrushRayN(brush* curBrush, Vector& inputStart, Vector& inputEnd)
811{
812  float EPSILON = 0.000001;
813  float startDistance;
814  float endDistance;
815
816  float startFraction = -1.0f;
817  float endFraction = 1.0f;
818  bool  startsOut = false;
819  bool  endsOut = false;
820
821  //Vector inputStart = State::getCameraTargetNode()->getLastAbsCoor();
822  //Vector inputEnd   = State::getCameraTargetNode()->getAbsCoor();
823
824  for (int i = 0; i < curBrush->n_brushsides; i++) {
825    brushside& curBrushSide =   this->bspFile->brushSides[curBrush->brushside + i]   ;
826    plane& curPlane  =   this->bspFile->planes[curBrushSide.plane] ;
827
828    startDistance = inputStart.x * curPlane.x + inputStart.y * curPlane.y+ inputStart.z * curPlane.z - curPlane.d;
829    endDistance = inputEnd.x * curPlane.x +inputEnd.y * curPlane.y +inputEnd.z * curPlane.z -curPlane.d;
830
831    if (startDistance > 0)
832      startsOut = true;
833    if (endDistance > 0)
834      endsOut = true;
835
836    // make sure the trace isn't completely on one side of the brush
837    if (startDistance > 0 && endDistance > 0) {   // both are in front of the plane, its outside of this brush
838      return;
839    }
840    if (startDistance <= 0 && endDistance <= 0) {   // both are behind this plane, it will get clipped by another one
841      continue;
842    }
843
844    // MMM... BEEFY
845    if (startDistance > endDistance) {   // line is entering into the brush
846      float fraction = (startDistance - EPSILON) / (startDistance - endDistance);  // *
847      if (fraction > startFraction)
848        startFraction = fraction;
849      // store plane
850      this->collPlane = &curPlane;
851
852    } else {   // line is leaving the brush
853      float fraction = (startDistance + EPSILON) / (startDistance - endDistance);  // *
854      if (fraction < endFraction)
855        endFraction = fraction;
856      // store plane
857      this->collPlane = & curPlane;
858
859    }
860
861  }
862  if (startsOut == false) {
863    this->outputStartsOut = false;
864    if (endsOut == false)
865      this->outputAllSolid = true;
866    return;
867  }
868
869  if (startFraction < endFraction) {
870    if (startFraction > -1.0f && startFraction < outputFraction) {
871      if (startFraction < 0)
872        startFraction = 0;
873      this->outputFraction = startFraction;
874    }
875  }
876
877}
878
879
880void BspManager::checkCollisionRay(BspTreeNode* node, float startFraction, float endFraction, Vector* start, Vector* end)
881{
882
883
884  float EPSILON = 0.000001;
885  float  endDistance = (end)->x * (node->plane.x) +(end)->y * (node->plane.y) +(end)->z * (node->plane.z)  - node->d;
886  float  startDistance = (start)->x * (node->plane.x)+ (start)->y * (node->plane.y)+ (start)->z * (node->plane.z)- node->d;
887
888
889  if(node->isLeaf) {
890    leaf& curLeaf = this->bspFile->leaves[node->leafIndex];
891    for (int i = 0; i <  curLeaf.n_leafbrushes ; i++) {
892      brush& curBrush = this->bspFile->brushes[((int*)(this->bspFile->leafBrushes))[curLeaf.leafbrush_first+i]];
893      //object *brush = &BSP.brushes[BSP.leafBrushes[leaf->firstLeafBrush + i]];
894      if (curBrush.n_brushsides > 0   &&
895          ((((BspTexture*)(this->bspFile->textures))[curBrush.texture]).contents & 1))
896        // CheckBrush( brush );
897        this->checkBrushRay(&curBrush);
898      if(curBrush.n_brushsides <=0) this->outputAllSolid = true;
899    }
900    return;
901  }
902
903
904  if (startDistance >= 0 && endDistance >= 0)     // A
905  {   // both points are in front of the plane
906    // so check the front child
907    this->checkCollisionRay(node->left,0,0,start,end);
908  } else if (startDistance < 0 && endDistance < 0)  // B
909  {   // both points are behind the plane
910    // so check the back child
911    this->checkCollisionRay(node->right,0,0,start,end);
912  } else                                            // C
913  {   // the line spans the splitting plane
914    int side;
915    float fraction1, fraction2, middleFraction;
916    Vector middle;
917
918    // STEP 1: split the segment into two
919    if (startDistance < endDistance) {
920      side = 1; // back
921      float inverseDistance = 1.0f / (startDistance - endDistance);
922      fraction1 = (startDistance + EPSILON) * inverseDistance;
923      fraction2 = (startDistance + EPSILON) * inverseDistance;
924    } else if (endDistance < startDistance) {
925      side = 0; // front(start)->x * (node->plane.x)+
926      float inverseDistance = 1.0f / (startDistance - endDistance);
927      fraction1 = (startDistance + EPSILON) * inverseDistance;
928      fraction2 = (startDistance - EPSILON) * inverseDistance;
929    } else {
930      side = 0; // front
931      fraction1 = 1.0f;
932      fraction2 = 0.0f;
933    }
934
935    // STEP 2: make sure the numbers are valid
936    if (fraction1 < 0.0f) fraction1 = 0.0f;
937    else if (fraction1 > 1.0f) fraction1 = 1.0f;
938    if (fraction2 < 0.0f) fraction2 = 0.0f;
939    else if (fraction2 > 1.0f) fraction2 = 1.0f;
940
941    // STEP 3: calculate the middle point for the first side
942    middleFraction = startFraction +
943                     (endFraction - startFraction) * fraction1;
944
945    middle.x = start->x + fraction1 * (end->x - start->x);
946    middle.y = start->y + fraction1 * (end->y - start->y);
947    middle.z = start->z + fraction1 * (end->z - start->z);
948
949    // STEP 4: check the first side
950    //CheckNode( node->children[side], startFraction, middleFraction, start, middle );
951    if(side == 0) this->checkCollisionRay(node->left,startFraction, middleFraction, start, &middle );
952
953    else this->checkCollisionRay(node->right,startFraction, middleFraction,
954                                   start, &middle );
955
956    // STEP 5: calculate the middle point for the second side
957    middleFraction = startFraction +
958                     (endFraction - startFraction) * fraction2;
959
960    middle.x = start->x + fraction2 * (end->x - start->x);
961    middle.y = start->y + fraction2 * (end->y - start->y);
962    middle.z = start->z + fraction2 * (end->z - start->z);
963
964    // STEP 6: check the second side
965    if(side == 1)this->checkCollisionRay(node->left,middleFraction, endFraction, &middle, end);
966
967    else this->checkCollisionRay(node->right,middleFraction, endFraction,&middle, end );
968
969
970  }
971
972}
973
974
975
976void BspManager::checkCollisionRayN(BspTreeNode* node, float startFraction, float endFraction, Vector* start, Vector* end)
977{
978
979
980  float EPSILON = 0.000001;
981
982  float endDistance = end->dot(node->plane) - node->d;
983  float startDistance = start->dot(node->plane) - node->d;
984
985
986  if( node->isLeaf) {
987    leaf& curLeaf = this->bspFile->leaves[node->leafIndex];
988    for (int i = 0; i <  curLeaf.n_leafbrushes ; i++) {
989      brush& curBrush = this->bspFile->brushes[((int*)(this->bspFile->leafBrushes))[curLeaf.leafbrush_first+i]];
990      //object *brush = &BSP.brushes[BSP.leafBrushes[leaf->firstLeafBrush + i]];
991      if (curBrush.n_brushsides > 0   &&
992          ((((BspTexture*)(this->bspFile->textures))[curBrush.texture]).contents & 1))
993        // CheckBrush( brush );
994        this->checkBrushRayN(&curBrush);
995      if(curBrush.n_brushsides <=0) this->outputAllSolid = true;
996    }
997
998    return;
999  }
1000
1001
1002  if (startDistance >= 0 && endDistance >= 0)     // A
1003  {   // both points are in front of the plane
1004    // so check the front child
1005    this->checkCollisionRayN(node->left,0,0,start,end);
1006  } else if (startDistance < 0 && endDistance < 0)  // B
1007  {   // both points are behind the plane
1008    // so check the back child
1009    this->checkCollisionRayN(node->right,0,0,start,end);
1010  } else                                            // C
1011  {   // the line spans the splitting plane
1012    int side;
1013    float fraction1, fraction2, middleFraction;
1014    Vector middle;
1015
1016    // STEP 1: split the segment into two
1017    if (startDistance < endDistance) {
1018      side = 1; // back
1019      float inverseDistance = 1.0f / (startDistance - endDistance);
1020      fraction1 = (startDistance + EPSILON) * inverseDistance;
1021      fraction2 = (startDistance + EPSILON) * inverseDistance;
1022    } else if (endDistance < startDistance) {
1023      side = 0; // front(start)->x * (node->plane.x)+
1024      float inverseDistance = 1.0f / (startDistance - endDistance);
1025      fraction1 = (startDistance + EPSILON) * inverseDistance;
1026      fraction2 = (startDistance - EPSILON) * inverseDistance;
1027    } else {
1028      side = 0; // front
1029      fraction1 = 1.0f;
1030      fraction2 = 0.0f;
1031    }
1032
1033    // STEP 2: make sure the numbers are valid
1034    if (fraction1 < 0.0f) fraction1 = 0.0f;
1035    else if (fraction1 > 1.0f) fraction1 = 1.0f;
1036    if (fraction2 < 0.0f) fraction2 = 0.0f;
1037    else if (fraction2 > 1.0f) fraction2 = 1.0f;
1038
1039    // STEP 3: calculate the middle point for the first side
1040    middleFraction = startFraction + (endFraction - startFraction) * fraction1;
1041    middle = (*start) + ((*end) - (*start)) * fraction1;
1042
1043
1044    // STEP 4: check the first side
1045    //CheckNode( node->children[side], startFraction, middleFraction, start, middle );
1046    if(side == 0) this->checkCollisionRayN(node->left,startFraction, middleFraction, start, &middle );
1047
1048    else this->checkCollisionRayN(node->right,startFraction, middleFraction,
1049                                    start, &middle );
1050
1051    // STEP 5: calculate the middle point for the second side
1052    middleFraction = startFraction + (endFraction - startFraction) * fraction2;
1053    middle = (*start) + ((*end) - (*start)) * fraction2;
1054
1055    // STEP 6: check the second side
1056    if(side == 1)this->checkCollisionRayN(node->left,middleFraction, endFraction, &middle, end);
1057
1058    else this->checkCollisionRayN(node->right,middleFraction, endFraction,&middle, end );
1059
1060
1061  }
1062
1063}
1064
1065float BspManager::checkPatchAltitude(BspTreeNode* node)
1066{
1067  leaf& curLeaf = this->bspFile->leaves[node->leafIndex];
1068  for(int i = 0; i < curLeaf.n_leaffaces ; i++) {}
1069  return 10.0f;
1070}
1071
1072void BspManager::checkCollisionBox(void)
1073{}
1074
1075
1076void BspManager::TraceBox( Vector& inputStart, Vector& inputEnd,
1077                           Vector& inputMins, Vector& inputMaxs )
1078{
1079  if (inputMins.x == 0 && inputMins.y == 0 && inputMins.z == 0 &&
1080      inputMaxs.x == 0 && inputMaxs.y == 0 && inputMaxs.z == 0) {   // the user called TraceBox, but this is actually a ray
1081    //!> FIXME TraceRay( inputStart, inputEnd );
1082  } else {   // setup for a box
1083    //traceType = TT_BOX;
1084    this->traceMins = inputMins;
1085    this->traceMaxs = inputMaxs;
1086    this->traceExtents.x = -traceMins.x > traceMaxs.x ?
1087                           -traceMins.x : traceMaxs.x;
1088    this->traceExtents.y = -traceMins.y > traceMaxs.y ?
1089                           -traceMins.y : traceMaxs.y;
1090    this->traceExtents.z = -traceMins.z > traceMaxs.z ?
1091                           -traceMins.z : traceMaxs.z;
1092    //!> FIXME Trace( inputStart, inputEnd );
1093  }
1094}
1095
1096void BspManager::checkCollision(WorldEntity* worldEntity)
1097{
1098
1099  // Init  Collision Detection
1100  this->outputStartsOut = true;
1101  this->outputAllSolid = false;
1102  this->outputFraction = 1.0f;
1103
1104
1105  this->checkCollisionX(worldEntity);
1106  this->checkCollisionY(worldEntity);
1107  this->checkCollisionZ(worldEntity);
1108
1109
1110#if 0
1111  // Retrieve Bounding box
1112  AABB* box = worldEntity->getModelAABB();
1113
1114
1115  Vector forwardDir = Vector(0.0,0.0,1.0);
1116  Vector upDir = Vector(0.0,1.0,0.0);
1117  Vector position = worldEntity->getAbsCoor();
1118
1119  bool SolidFlag = false;
1120  bool collision = false;
1121  Vector position1 = position;
1122  Vector position2 = position + Vector(0.0,1.0,0.0);
1123  Vector position3 = position;
1124  Vector position4 = position + Vector(0.0,1.0,0.0);
1125  Vector dest = worldEntity->getAbsCoor() - upDir*40.0f; //
1126  Vector dest1 = position + forwardDir*4.0f;
1127  Vector dest2 = position2 + forwardDir*4.0;
1128  Vector dest3 = position + forwardDir*4.0f;
1129  Vector dest4 = position2 + forwardDir*4.0;
1130  dest = position - Vector(0.0, 40.0,0.0);
1131  Vector out = dest;
1132  Vector out1;
1133  Vector out2;
1134
1135
1136  plane* testPlane;
1137
1138  bool xCollision = false;
1139  bool zCollision = false;
1140
1141
1142  float height = 40;
1143
1144
1145  if( box != NULL) {
1146    position = worldEntity->getAbsCoor() +  box->center; // + Vector(0.0, 1.0, 0.0) * box->halfLength[1] * 1.0f;
1147    dest     = worldEntity->getAbsCoor() +  box->center - Vector(0.0, 1.0, 0.0) * (box->halfLength[1] + BSP_Y_OFFSET) *   100;
1148
1149    Vector dirX =  worldEntity->getAbsDirX(); dirX.y = 0.0f; dirX.normalize();
1150
1151    //position1 = worldEntity->getAbsCoor() +  box->center - dirX * (box->halfLength[0]  + BSP_X_OFFSET);
1152    dest1     = worldEntity->getAbsCoor() +  box->center + dirX * (box->halfLength[0]  + BSP_X_OFFSET);
1153    dest2     = worldEntity->getAbsCoor() -  box->center + dirX * (box->halfLength[0]  + BSP_X_OFFSET);
1154
1155    Vector dirZ =  worldEntity->getAbsDirZ(); dirX.y = 0.0f; dirZ.normalize();
1156    //position2 = worldEntity->getAbsCoor() +  box->center - dirZ * (box->halfLength[2]  + BSP_Z_OFFSET);
1157    dest3     = worldEntity->getAbsCoor() +  box->center + dirZ * (box->halfLength[2]  + BSP_Z_OFFSET);
1158    dest4     = worldEntity->getAbsCoor() -  box->center + dirZ * (box->halfLength[2]  + BSP_Z_OFFSET);
1159  } else {
1160    // Init positions and destinations to anything useful!
1161
1162  }
1163
1164
1165
1166  // 1st Ray: Y RAY
1167  this->inputStart =  position;
1168  this->inputEnd =   dest;
1169  this->checkCollisionRayN(this->root,0.0f,1.0f, &position, &dest );
1170
1171
1172  //
1173  if(!this->outputStartsOut ) {
1174    this->collPlane = new plane;
1175    this->collPlane->x = 0.0f;
1176    this->collPlane->y = 0.0f;
1177    this->collPlane->z = 0.0f;
1178    collision = true;
1179  } else {
1180
1181    if( this->outputFraction == 1.0f) {
1182      if(this->outputAllSolid ) {
1183        this->collPlane = new plane;
1184        this->collPlane->x = 0.0f;
1185        this->collPlane->y = 0.0f;
1186        this->collPlane->z = 0.0f;
1187        collision = true;
1188        SolidFlag = true;
1189      } else
1190        collision = false;
1191
1192
1193      out = dest;
1194
1195    } else {
1196      collision = true;
1197      out.x = position.x + (dest.x -position.x) * this->outputFraction;
1198      out.y = position.y + (dest.y -position.y) * this->outputFraction;
1199      out.z = position.z + (dest.z -position.z) * this->outputFraction;
1200
1201      Vector out3 = out + Vector(height*this->collPlane->x,height*this->collPlane->y,height*this->collPlane->z);
1202      this->out = out;
1203    }
1204  }
1205    testPlane = this->collPlane;
1206
1207
1208  bool xCollisionNeg = false;
1209  bool zCollisionNeg = false;
1210
1211
1212
1213    // 2nd Collision Detection X-RAY
1214    this->outputStartsOut = true;
1215    this->outputAllSolid = false;
1216    this->outputFraction = 1.0f;
1217    this->inputStart =  position1;
1218    this->inputEnd =   dest1;
1219    this->checkCollisionRayN(this->root,0.0f,1.0f, &position1, &dest1 );
1220
1221    if(this->outputFraction < 1.0f) {
1222      out.x = dest1.x + (dest1.x -position1.x) * this->outputFraction;
1223      dest1 = position1 + (dest1 -position1) * this->outputFraction;
1224      xCollision = true;
1225      testPlane = this->collPlane;
1226    }
1227    if(this->outputAllSolid ) {
1228
1229      this->collPlane = new plane;
1230      this->collPlane->x = 0.0f;
1231      this->collPlane->y = 0.0f;
1232      this->collPlane->z = 0.0f;
1233      testPlane = this->collPlane;
1234      SolidFlag = true;
1235      xCollision = true;
1236    }
1237    //out.z = this->outputFraction;
1238
1239
1240
1241      // 3rd Collision Detection Z-RAY
1242      this->outputStartsOut = true;
1243      this->outputAllSolid = false;
1244      this->outputFraction = 1.0f;
1245      this->inputStart =  position2;
1246      this->inputEnd =   dest2;
1247
1248      this->checkCollisionRayN(this->root,0.0f,1.0f, &position2, &dest2 );
1249      //out.x = this->outputFraction;
1250
1251      if(this->outputFraction < 1.0f ) {
1252        out.z = out.z = dest2.z + (dest2.z -position2.z) * this->outputFraction;
1253        dest2 = position2 + (dest2 -position2) * this->outputFraction;
1254        zCollision = true;
1255        testPlane = this->collPlane;
1256
1257      }
1258      if(this->outputAllSolid ) {
1259        this->collPlane = new plane;
1260        this->collPlane->x = 0.0f;
1261        this->collPlane->y = 0.0f;
1262        this->collPlane->z = 0.0f;
1263        testPlane = this->collPlane;
1264
1265        SolidFlag = true;
1266        zCollision = true;
1267      }
1268
1269
1270  // Return the normal here: Normal's stored in this->collPlane;
1271  if( collision) {
1272    worldEntity->registerCollision(COLLISION_TYPE_AXIS_Y , this->parent, worldEntity, Vector(testPlane->x, testPlane->y, testPlane->z), out, SolidFlag);
1273}
1274  if(xCollision) {
1275    worldEntity->registerCollision(COLLISION_TYPE_AXIS_X , this->parent, worldEntity, Vector(testPlane->x, testPlane->y, testPlane->z),dest1 , SolidFlag);
1276  }
1277
1278  if(zCollision) {
1279    worldEntity->registerCollision(COLLISION_TYPE_AXIS_Z , this->parent, worldEntity, Vector(testPlane->x, testPlane->y, testPlane->z), dest2 , SolidFlag);
1280  }
1281#endif
1282
1283}
1284
1285
1286
1287/**
1288 * check the collision in the x direction (forward, backward)
1289 */
1290void BspManager::checkCollisionX(WorldEntity* entity)
1291{
1292  // Retrieve Bounding box
1293  AABB* box = entity->getModelAABB();
1294
1295
1296  plane*            testPlane          = NULL;  //!< the collision test plane
1297
1298  Vector            forward;                    //!< left collision ray
1299  Vector            backward;                   //!< right collision ray
1300  Vector            collPos;                    //!< the collision position
1301
1302  bool              xCollisionForward  = false; //!< flag true if right collision
1303  bool              xCollisionBackward = false; //!< flag true if left collision
1304  bool              SolidFlag          = false; //!< flag set true if solid
1305
1306  Vector            position;                   //!< current position of the entity
1307  Vector            dirX;                       //!< direction x
1308
1309  position = entity->getAbsCoor();
1310  dirX =  entity->getAbsDirX(); dirX.y = 0.0f; dirX.normalize();
1311
1312  // calculate the rays
1313  if( box != NULL)
1314  {
1315    forward  = entity->getAbsCoor() +  box->center + dirX * (box->halfLength[0]  + BSP_X_OFFSET);
1316    backward = entity->getAbsCoor() +  box->center - dirX * (box->halfLength[0]  + BSP_X_OFFSET);
1317  }
1318  else
1319  {
1320    forward  = position + dirX * 4.0f;
1321    backward = position + Vector(0.0, 1.0, 0.0) + dirX * 4.0;
1322  }
1323
1324
1325  /*   X Ray forward  */
1326  // init some member variables before collision check
1327  this->outputStartsOut = true;
1328  this->outputAllSolid = false;
1329  this->outputFraction = 1.0f;
1330  this->inputStart =  position;
1331  this->inputEnd =   forward;
1332  this->checkCollisionRayN(this->root, 0.0f, 1.0f, &position, &forward );
1333
1334  // collision occured
1335  if( this->outputFraction < 1.0f)
1336  {
1337    collPos = position + (forward - position) * this->outputFraction;
1338    xCollisionForward = true;
1339    testPlane = this->collPlane;
1340  }
1341  if(this->outputAllSolid )
1342  {
1343    this->collPlane = new plane;
1344    this->collPlane->x = 0.0f;
1345    this->collPlane->y = 0.0f;
1346    this->collPlane->z = 0.0f;
1347    testPlane = this->collPlane;
1348    SolidFlag = true;
1349    xCollisionForward = true;
1350  }
1351
1352  // collision registration
1353  if( xCollisionForward)
1354  {
1355    CoRe::CollisionTube::getInstance()->registerCollisionEvent( CoRe::CREngine::CR_COLLISION_TYPE_AXIS_X ,
1356                              entity, this->parent,
1357                              Vector(testPlane->x, testPlane->y, testPlane->z),
1358                              collPos,
1359                              SolidFlag);
1360  }
1361
1362
1363
1364  /*   X Ray backward  */
1365  // init some member variables before collision check
1366  this->outputStartsOut = true;
1367  this->outputAllSolid = false;
1368  this->outputFraction = 1.0f;
1369  this->inputStart =  position;
1370  this->inputEnd =   backward;
1371  this->checkCollisionRayN(this->root, 0.0f, 1.0f, &position, &backward );
1372
1373  // collision occured
1374  if( this->outputFraction < 1.0f)
1375  {
1376    collPos = position + (backward - position) * this->outputFraction;
1377    xCollisionBackward = true;
1378    testPlane = this->collPlane;
1379  }
1380  if( this->outputAllSolid)
1381  {
1382    this->collPlane = new plane;
1383    this->collPlane->x = 0.0f;
1384    this->collPlane->y = 0.0f;
1385    this->collPlane->z = 0.0f;
1386    testPlane = this->collPlane;
1387    SolidFlag = true;
1388    xCollisionBackward = true;
1389  }
1390
1391  // collision registration
1392  if( xCollisionBackward)
1393  {
1394    CoRe::CollisionTube::getInstance()->registerCollisionEvent( CoRe::CREngine::CR_COLLISION_TYPE_AXIS_X_NEG,
1395                              entity, this->parent,
1396                              Vector(testPlane->x, testPlane->y, testPlane->z),
1397                              collPos,
1398                              SolidFlag);
1399  }
1400}
1401
1402
1403/**
1404 * check the collision in the z direction (up, down)
1405 */
1406void BspManager::checkCollisionY(WorldEntity* entity)
1407{
1408
1409  // Retrieve Bounding box
1410  AABB* box = entity->getModelAABB();
1411
1412
1413  plane*            testPlane          = NULL;  //!< the collision test plane
1414
1415  Vector            up;                         //!< up collision ray
1416  Vector            down;                       //!< down collision ray
1417  Vector            collPos;                    //!< the collision position
1418
1419  bool              yCollisionUp       = false; //!< flag true if right collision
1420  bool              yCollisionDown     = false; //!< flag true if left collision
1421  bool              SolidFlag          = false; //!< flag set true if solid
1422
1423  Vector            position;                   //!< current position of the entity
1424  Vector            dirY;                       //!< direction x
1425
1426  position = entity->getAbsCoor();
1427  collPos = position;
1428  dirY =  Vector(0.0, 1.0, 0.0);
1429
1430  // calculate the rays
1431  if( box != NULL)
1432  {
1433    up   = position +  box->center + dirY * (box->halfLength[1]/*  + BSP_Y_OFFSET*/);
1434    down = position +  box->center - dirY * (box->halfLength[1]  + BSP_Y_OFFSET);
1435  }
1436  else
1437  {
1438    up   = position + dirY * 4.0f;
1439    down = position + Vector(0.0, 1.0, 0.0) + dirY * 4.0;
1440  }
1441
1442
1443
1444
1445  /*   Y Ray up */
1446  // init some member variables before collision check
1447  this->inputStart = position;
1448  this->inputEnd   = up;
1449  this->checkCollisionRayN(this->root,0.0f,1.0f, &position, &up );
1450
1451  if( !this->outputStartsOut )
1452  {
1453    this->collPlane = new plane;
1454    this->collPlane->x = 0.0f;
1455    this->collPlane->y = 0.0f;
1456    this->collPlane->z = 0.0f;
1457    yCollisionUp = true;
1458  }
1459  else
1460  {
1461    if( this->outputFraction == 1.0f)
1462    {
1463      if( this->outputAllSolid )
1464      {
1465        this->collPlane = new plane;
1466        this->collPlane->x = 0.0f;
1467        this->collPlane->y = 0.0f;
1468        this->collPlane->z = 0.0f;
1469        yCollisionUp = true;
1470        SolidFlag = true;
1471      }
1472      else
1473      {
1474        yCollisionUp = false;
1475        collPos = up;
1476      }
1477    }
1478    else
1479    {
1480      yCollisionUp = true;
1481      collPos = position + (up - position) * this->outputFraction;
1482      this->out = collPos;        // why this????
1483    }
1484  }
1485  testPlane = this->collPlane;
1486
1487  // collision registration
1488  if( yCollisionUp)
1489  {
1490    CoRe::CollisionTube::getInstance()->registerCollisionEvent( CoRe::CREngine::CR_COLLISION_TYPE_AXIS_Y,
1491                              entity, this->parent,
1492                              Vector(testPlane->x, testPlane->y, testPlane->z),
1493                              collPos, SolidFlag);
1494  }
1495
1496
1497
1498
1499  /*   Y Ray down */
1500  // init some member variables before collision check
1501  this->inputStart = position;
1502  this->inputEnd   = down;
1503  this->checkCollisionRayN(this->root,0.0f,1.0f, &position, &down );
1504
1505  if( !this->outputStartsOut )
1506  {
1507    this->collPlane = new plane;
1508    this->collPlane->x = 0.0f;
1509    this->collPlane->y = 0.0f;
1510    this->collPlane->z = 0.0f;
1511    yCollisionDown = true;
1512  }
1513  else
1514  {
1515    if( this->outputFraction == 1.0f) // No collision Detected
1516    {
1517      if( this->outputAllSolid )
1518      {
1519        this->collPlane = new plane;
1520        this->collPlane->x = 0.0f;
1521        this->collPlane->y = 0.0f;
1522        this->collPlane->z = 0.0f;
1523        yCollisionDown = true;
1524        SolidFlag = true;
1525      }
1526      else      // No collision happened
1527      {
1528        yCollisionDown = false;
1529        collPos = down;
1530      }
1531    }
1532    else           // A collision has happended
1533    {
1534      yCollisionDown = true;
1535      collPos = position + (down - position) * this->outputFraction;
1536    }
1537  }
1538  testPlane = this->collPlane;
1539
1540  // collision registration
1541  if( yCollisionDown)
1542  {
1543    CoRe::CollisionTube::getInstance()->registerCollisionEvent( CoRe::CREngine::CR_COLLISION_TYPE_AXIS_Y_NEG ,
1544                              entity, this->parent,
1545                              Vector(testPlane->x, testPlane->y, testPlane->z),
1546                              collPos, SolidFlag);
1547  }
1548}
1549
1550
1551
1552
1553/**
1554 * check the collision in the z direction (left, right)
1555 */
1556void BspManager::checkCollisionZ(WorldEntity* entity)
1557{
1558  // Retrieve Bounding box
1559  AABB* box = entity->getModelAABB();
1560
1561
1562  plane*            testPlane          = NULL;  //!< the collision test plane
1563
1564  Vector            right;                      //!< right collision ray
1565  Vector            left;                       //!< left collision ray
1566  Vector            collPos;                    //!< the collision position
1567
1568  bool              zCollisionRight    = false; //!< flag true if right collision
1569  bool              zCollisionLeft     = false; //!< flag true if left collision
1570  bool              SolidFlag          = false; //!< flag set true if solid
1571
1572  Vector            position;                   //!< current position of the entity
1573  Vector            dirZ;                       //!< direction x
1574
1575  position = entity->getAbsCoor();
1576  dirZ =  entity->getAbsDirZ(); dirZ.y = 0.0f; dirZ.normalize();
1577
1578  // calculate the rays
1579  if( box != NULL)
1580  {
1581    right = entity->getAbsCoor() +  box->center + dirZ * (box->halfLength[2]  + BSP_Z_OFFSET);
1582    left  = entity->getAbsCoor() +  box->center - dirZ * (box->halfLength[2]  + BSP_Z_OFFSET);
1583  }
1584  else
1585  {
1586    right = position + dirZ * 4.0f;
1587    left  = position + Vector(0.0, 1.0, 0.0) + dirZ * 4.0;
1588  }
1589
1590
1591  /*   Z Ray right */
1592  // init some member variables before collision check
1593  this->outputStartsOut = true;
1594  this->outputAllSolid = false;
1595  this->outputFraction = 1.0f;
1596  this->inputStart =  position;
1597  this->inputEnd =   right;
1598  this->checkCollisionRayN(this->root, 0.0f, 1.0f, &position, &right );
1599
1600
1601  // collision occured
1602  if( this->outputFraction < 1.0f )
1603  {
1604    collPos = position + (right - position) * this->outputFraction;
1605    zCollisionRight = true;
1606    testPlane = this->collPlane;
1607  }
1608  if(this->outputAllSolid )
1609  {
1610    this->collPlane = new plane;
1611    this->collPlane->x = 0.0f;
1612    this->collPlane->y = 0.0f;
1613    this->collPlane->z = 0.0f;
1614    testPlane = this->collPlane;
1615
1616    SolidFlag = true;
1617    zCollisionRight = true;
1618  }
1619
1620
1621  if( zCollisionRight) {
1622    CoRe::CollisionTube::getInstance()->registerCollisionEvent( CoRe::CREngine::CR_COLLISION_TYPE_AXIS_Z ,
1623                              entity, this->parent,
1624                              Vector(testPlane->x, testPlane->y, testPlane->z),
1625                              collPos , SolidFlag);
1626  }
1627
1628
1629
1630  /*   Z Ray left */
1631  // init some member variables before collision check
1632  this->outputStartsOut = true;
1633  this->outputAllSolid = false;
1634  this->outputFraction = 1.0f;
1635  this->inputStart =  position;
1636  this->inputEnd =    left;
1637  this->checkCollisionRayN(this->root, 0.0f, 1.0f, &position, &left);
1638
1639
1640  // collision occured
1641  if( this->outputFraction < 1.0f )
1642  {
1643    collPos = position + (left - position) * this->outputFraction;
1644    zCollisionLeft = true;
1645    testPlane = this->collPlane;
1646  }
1647  if(this->outputAllSolid )
1648  {
1649    this->collPlane = new plane;
1650    this->collPlane->x = 0.0f;
1651    this->collPlane->y = 0.0f;
1652    this->collPlane->z = 0.0f;
1653    testPlane = this->collPlane;
1654
1655    SolidFlag = true;
1656    zCollisionLeft = true;
1657  }
1658
1659
1660  if( zCollisionLeft) {
1661    CoRe::CollisionTube::getInstance()->registerCollisionEvent( CoRe::CREngine::CR_COLLISION_TYPE_AXIS_Z_NEG ,
1662                               entity, this->parent,
1663                               Vector(testPlane->x, testPlane->y, testPlane->z),
1664                               collPos , SolidFlag);
1665  }
1666
1667}
1668
1669
1670
1671
1672void  BspManager::checkCollision(BspTreeNode* node, Vector* cam)
1673{
1674  Vector next = this->cam;
1675  next.x =   (State::getCameraTargetNode()->getLastAbsCoor()).x ;
1676  next.y =   (State::getCameraTargetNode()->getLastAbsCoor()).y ;
1677  next.z =   (State::getCameraTargetNode()->getLastAbsCoor()).z ;
1678
1679  float dist = 0;
1680  if(!(node->isLeaf)) {
1681    dist = (node->plane.x * this->cam.x + node->plane.y*this->cam.y + node->plane.z*this->cam.z) - node->d;
1682    if(dist > 4.0f) {
1683      checkCollision(node->left,cam);
1684      return;
1685    }
1686    if(dist < -4.0f) {
1687      checkCollision(node->right,cam);
1688      return;
1689    }
1690    if(dist<=4.0f && dist >= -4.0f) {
1691      checkCollision(node->left,cam);
1692      checkCollision(node->right,cam);
1693      return;
1694    }
1695    return;
1696  } else {
1697
1698    leaf& camLeaf =  ((leaf *)(this->bspFile->leaves))[(node->leafIndex ) ];
1699
1700    if (camLeaf.cluster < 0) {
1701      this->drawDebugCube(&this->cam);
1702      this->drawDebugCube(&next);
1703      // State::getPlayer()->getPlayable()->setRelCoor(-100,-100,-100);
1704      //State::getPlayer()->getPlayable()->collidesWith(NULL, State::getCameraTargetNode()->getLastAbsCoor());
1705    }
1706
1707
1708    /*
1709        for(int i = 0; i < camLeaf.n_leafbrushes && i < 10; i++ )
1710        {
1711                brush& curBrush = ((brush*)(this->bspFile->brushes))[(camLeaf.leafbrush_first +i)%this->bspFile->numLeafBrushes];
1712                if(curBrush.n_brushsides < 0) return;
1713                for(int j = 0; j < curBrush.n_brushsides; j++)
1714                {
1715                float dist = -0.1;
1716                brushside& curBrushSide = ((brushside*)(this->bspFile->brushSides))[(curBrush.brushside +j)%this->bspFile->numBrushSides];
1717                plane&      testPlane = ((plane*)(this->bspFile->planes))[curBrushSide.plane % this->bspFile->numPlanes];
1718                dist = testPlane.x * this->cam.x +  testPlane.y * this->cam.y  +  testPlane.z * this->cam.z   -testPlane.d ;
1719
1720                if(dist < -0.01f) dist = -1.0f *dist;
1721                if(dist < 1.0f){
1722                                this->drawDebugCube(&this->cam);
1723                                return;
1724                              }
1725                }
1726
1727        } */
1728
1729  }
1730  return;
1731}
1732
1733void BspManager::drawDebugCube(Vector* cam)
1734{
1735  glBegin(GL_QUADS);
1736
1737  // Bottom Face.  Red, 75% opaque, magnified texture
1738
1739  glNormal3f( 0.0f, -1.0f, 0.0f); // Needed for lighting
1740  glColor4f(0.9,0.2,0.2,.75); // Basic polygon color
1741
1742  glTexCoord2f(0.800f, 0.800f); glVertex3f(cam->x-1.0f, cam->y-1.0f,cam->z -1.0f);
1743  glTexCoord2f(0.200f, 0.800f); glVertex3f(cam->x+1.0f, cam->y-1.0f,cam->z -1.0f);
1744  glTexCoord2f(0.200f, 0.200f); glVertex3f(cam->x+ 1.0f,cam->y -1.0f,cam->z +  1.0f);
1745  glTexCoord2f(0.800f, 0.200f); glVertex3f(cam->x-1.0f, cam->y-1.0f, cam->z + 1.0f);
1746
1747
1748  // Top face; offset.  White, 50% opaque.
1749
1750  glNormal3f( 0.0f, 1.0f, 0.0f);  glColor4f(0.5,0.5,0.5,.5);
1751
1752  glTexCoord2f(0.005f, 1.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z -1.0f);
1753  glTexCoord2f(0.005f, 0.005f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f,  cam->z +1.0f);
1754  glTexCoord2f(1.995f, 0.005f); glVertex3f(cam->x+ 1.0f,  cam->y+1.0f,  cam->z +1.0f);
1755  glTexCoord2f(1.995f, 1.995f); glVertex3f(cam->x+ 1.0f, cam->y+ 1.0f, cam->z -1.0f);
1756
1757
1758  // Far face.  Green, 50% opaque, non-uniform texture cooridinates.
1759
1760  glNormal3f( 0.0f, 0.0f,-1.0f);  glColor4f(0.2,0.9,0.2,.5);
1761
1762  glTexCoord2f(0.995f, 0.005f); glVertex3f(cam->x-1.0f, cam->y-1.0f, cam->z -1.3f);
1763  glTexCoord2f(2.995f, 2.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z -1.3f);
1764  glTexCoord2f(0.005f, 0.995f); glVertex3f(cam->x+ 1.0f,cam->y+  1.0f, cam->z -1.3f);
1765  glTexCoord2f(0.005f, 0.005f); glVertex3f( cam->x+1.0f,cam->y -1.0f, cam->z -1.3f);
1766
1767
1768  // Right face.  Blue; 25% opaque
1769
1770  glNormal3f( 1.0f, 0.0f, 0.0f);  glColor4f(0.2,0.2,0.9,.25);
1771
1772  glTexCoord2f(0.995f, 0.005f); glVertex3f(cam->x+ 1.0f, cam->y -1.0f, cam->z -1.0f);
1773  glTexCoord2f(0.995f, 0.995f); glVertex3f(cam->x+ 1.0f, cam->y+ 1.0f, cam->z -1.0f);
1774  glTexCoord2f(0.005f, 0.995f); glVertex3f(cam->x+ 1.0f, cam->y+ 1.0f, cam->z + 1.0f);
1775  glTexCoord2f(0.005f, 0.005f); glVertex3f(cam->x+ 1.0f, cam->y-1.0f,  cam->z +1.0f);
1776
1777
1778  // Front face; offset.  Multi-colored, 50% opaque.
1779
1780  glNormal3f( 0.0f, 0.0f, 1.0f);
1781
1782  glColor4f( 0.9f, 0.2f, 0.2f, 0.5f);
1783  glTexCoord2f( 0.005f, 0.005f); glVertex3f(cam->x-1.0f, cam->y-1.0f,  cam->z +1.0f);
1784  glColor4f( 0.2f, 0.9f, 0.2f, 0.5f);
1785  glTexCoord2f( 0.995f, 0.005f); glVertex3f(cam->x+ 1.0f, cam->y-1.0f,  cam->z +1.0f);
1786  glColor4f( 0.2f, 0.2f, 0.9f, 0.5f);
1787  glTexCoord2f( 0.995f, 0.995f); glVertex3f( cam->x+1.0f,  cam->y+1.0f,  cam->z +1.0f);
1788  glColor4f( 0.1f, 0.1f, 0.1f, 0.5f);
1789  glTexCoord2f( 0.005f, 0.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f,  cam->z +1.0f);
1790
1791
1792  // Left Face; offset.  Yellow, varying levels of opaque.
1793
1794  glNormal3f(-1.0f, 0.0f, 0.0f);
1795
1796  glColor4f(0.9,0.9,0.2,0.0);
1797  glTexCoord2f(0.005f, 0.005f); glVertex3f(cam->x-1.0f, cam->y-1.0f, cam->z -1.0f);
1798  glColor4f(0.9,0.9,0.2,0.66);
1799  glTexCoord2f(0.995f, 0.005f); glVertex3f(cam->x-1.0f,cam->y -1.0f,  cam->z +1.0f);
1800  glColor4f(0.9,0.9,0.2,1.0);
1801  glTexCoord2f(0.995f, 0.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f,  cam->z +1.0f);
1802  glColor4f(0.9,0.9,0.2,0.33);
1803  glTexCoord2f(0.005f, 0.995f); glVertex3f(cam->x-1.0f, cam->y+ 1.0f, cam->z -1.0f);
1804
1805  glEnd();
1806}
1807
1808void BspManager::addFace(int f)
1809{
1810  face& curFace =  ((face *)(this->bspFile->faces))[f];
1811  if(this->bspFile->Materials[curFace.texture].alpha) this->trasparent.push_back(f);
1812  else this->opal.push_back(f);
1813}
Note: See TracBrowser for help on using the repository browser.