Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10209 was 10076, checked in by patrick, 18 years ago

bsp texture patch from claudio. claudio: thx very much you did a fantastic job in such short time :D

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  this->lastTex = -1;
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.