Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10321 was 10314, checked in by patrick, 19 years ago

merged branche mount_point to trunk. this will add mount point abilities, bsp transparency fix and some other smaller stuff to this trunk

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