Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/terrain.older/src/lib/graphics/importer/bsp_manager.cc @ 10764

Last change on this file since 10764 was 9324, checked in by ponder, 18 years ago

Added byte_order.h to
Added binary_file.h binary_file.cc
Changed the bsp code to work on big endian machines.

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