Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/ODE/src/lib/graphics/importer/bsp_manager.cc @ 9919

Last change on this file since 9919 was 9919, checked in by bottac, 17 years ago

CrPhysicsFullWalk on Static Models and BSP Patches almost working. libODE≥0.7 required.
Screenshot: http://people.ee.ethz.ch/~bottac/Collision_ODE/

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