Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged the presentation back

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