Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/blink/src/lib/graphics/importer/bsp/bsp_manager.cc

Last change on this file was 10337, checked in by patrick, 18 years ago

fixed a floating point problem

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