Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9110 was 9110, checked in by bensch, 18 years ago

orxonox/trunk: merged the Presentation back

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