Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/presentation/src/lib/graphics/importer/bsp_manager.cc @ 9197

Last change on this file since 9197 was 9197, checked in by bottac, 18 years ago

Better empiric constants.

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