Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10033 was 10033, checked in by patrick, 17 years ago

moved some of the importer sources, probably will need to rebuild the project

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