00001 #include "objects.h"
00002
00003 OBJECTS::OBJECTS()
00004 {
00005 error_log.open((settings.GetSettingsDir() + "/logs/objects.log").c_str());
00006
00007
00008 sphere_reflection_loaded = false;
00009
00010 object_list = NULL;
00011 model_list = NULL;
00012 }
00013
00014 OBJECTS::~OBJECTS()
00015 {
00016 error_log.close();
00017
00018
00019 DeleteAll();
00020 }
00021
00022 void OBJECTS::DeleteAll()
00023 {
00024 for (map <string, TEXTURE_HANDLE>::iterator i = texture_db.begin(); i != texture_db.end(); i++)
00025 {
00026
00027 i->second.Unload();
00028 }
00029
00030 if (sphere_reflection_loaded)
00031 {
00032
00033 sphere_reflection.Unload();
00034 }
00035
00036 texture_db.clear();
00037
00038 while (object_list != NULL)
00039 delobject();
00040
00041 while (model_list != NULL)
00042 delmodel();
00043 }
00044
00045 void OBJECTS::delobject()
00046 {
00047 if (object_list == NULL)
00048 return;
00049
00050
00051 OBJECTNODE * old = object_list;
00052 object_list = object_list->next;
00053 delete old;
00054 }
00055
00056 void OBJECTS::delmodel()
00057 {
00058 if (model_list == NULL)
00059 return;
00060
00061
00062 OBJECTMODEL * old = model_list;
00063 model_list = model_list->next;
00064 delete old;
00065 }
00066
00067 void OBJECTS::UpdateSettings()
00068 {
00069 settings.Get( "display.view_distance", lod_far );
00070 settings.Get( "display.width", display_x );
00071 settings.Get( "display.height", display_y );
00072 }
00073
00074 void OBJECTS::DrawObject(OBJECTNODE * object)
00075 {
00076
00077
00078
00079 float dx, dy, dz, rc;
00080
00081
00082 VERTEX objcenter = object->model->jmodel.GetBBOX().GetCenter();
00083 float temp = objcenter.x;
00084 objcenter.x = objcenter.y;
00085 objcenter.y = objcenter.z;
00086 objcenter.z = temp;
00087 VERTEX objpos = object->pos + objcenter;
00088 dx=objpos.x+cam.position.x; dy=objpos.y+cam.position.y; dz=objpos.z+cam.position.z;
00089 rc=dx*dx+dy*dy+dz*dz;
00090
00091 bool zerotransform = false;
00092 if (object->pos.x == 0 && object->pos.y == 0 && object->pos.z == 0)
00093 zerotransform = true;
00094
00095 if (!object->model->skybox)
00096 {
00097 lod_far += object->model->jmodel.GetRadius();
00098 if (rc > lod_far*lod_far) return;
00099
00100
00101
00102 float bound, rd;
00103
00104 {
00105
00106 bound = object->model->jmodel.GetRadius();
00107 int i;
00108 for (i=0;i<6;i++)
00109 {
00110 rd=cam.frustum[i][0]*objpos.x+
00111 cam.frustum[i][1]*objpos.y+
00112 cam.frustum[i][2]*objpos.z+
00113 cam.frustum[i][3];
00114 if (rd<=-bound)
00115 {
00116 return;
00117 }
00118 }
00119 }
00120
00121
00122 }
00123
00124
00125
00126
00127
00128 if (object->model->skybox)
00129 {
00130 glPushMatrix();
00131 glMatrixMode( GL_PROJECTION );
00132 glPushMatrix();
00133 glLoadIdentity( );
00134 gluPerspective( 45.0f, (float)display_x / (float)display_y, 0.1f, 10000.0 );
00135 glMatrixMode( GL_MODELVIEW );
00136 GLdouble temp_matrix[16];
00137 cam.PutTransformInto(temp_matrix);
00138 glLoadMatrixd(temp_matrix);
00139 glDepthMask(0);
00140 glRotated(-90, 1,0,0);
00141 glDisable(GL_FOG);
00142 }
00143 else if (!zerotransform)
00144 {
00145 glPushMatrix();
00146 GLfloat transform_matrix[16];
00147 object->dir.GetMat(transform_matrix);
00148
00149 glTranslatef(object->pos.x, object->pos.y, object->pos.z);
00150 glMultMatrixf(transform_matrix);
00151 }
00152
00153 if (object->model != NULL)
00154 {
00155 if (object->model->fullbright)
00156 glDisable(GL_LIGHTING);
00157 else
00158 glEnable(GL_LIGHTING);
00159
00160 if (object->model->blend)
00161 {
00162 glDisable(GL_ALPHA_TEST);
00163 glDepthMask(0);
00164 }
00165
00166
00167
00168 object->model->jmodel.DrawStatic();
00169
00170 if (object->model->blend)
00171 {
00172 glEnable(GL_ALPHA_TEST);
00173 glDepthMask(1);
00174 }
00175
00176 }
00177 else
00178 cout << "NULL model" << endl;
00179
00180 if (object->model->skybox)
00181 {
00182 glDepthMask(1);
00183 glMatrixMode( GL_PROJECTION );
00184 glPopMatrix();
00185 glMatrixMode( GL_MODELVIEW );
00186 glPopMatrix();
00187 glEnable(GL_FOG);
00188 }
00189 else if (!zerotransform)
00190 glPopMatrix();
00191 }
00192
00193 void OBJECTS::Draw(bool cull)
00194 {
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 glPushAttrib(GL_ALL_ATTRIB_BITS);
00207 glPushMatrix();
00208
00209
00210
00211 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
00212
00213 glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00214 glEnable (GL_COLOR_MATERIAL);
00215 glColor3f (1.0, 1.0, 1.0);
00216 GLfloat specular [] = { 0.0, 0.0, 0.0, 0.0 };
00217 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
00218 GLfloat shininess [] = { 0.0 };
00219 glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, shininess);
00220
00221
00222 glEnable(GL_BLEND);
00223
00224 glAlphaFunc(GL_GREATER, 0.9f);
00225 glEnable(GL_ALPHA_TEST);
00226 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00227 glCullFace(GL_BACK);
00228 if (cull)
00229 glEnable(GL_CULL_FACE);
00230 else
00231 glDisable(GL_CULL_FACE);
00232
00233 glColor4f(1,1,1,1);
00234
00235 glRotated(-90, 1,0,0);
00236
00237
00238 OBJECTNODE * curpos = object_list;
00239 while (curpos != NULL)
00240 {
00241 if (curpos->model->skybox)
00242 DrawObject(curpos);
00243 curpos = curpos -> next;
00244 }
00245
00246
00247 curpos = object_list;
00248 while (curpos != NULL)
00249 {
00250 if (!curpos->model->skybox && !curpos->model->blend)
00251 DrawObject(curpos);
00252 curpos = curpos -> next;
00253 }
00254
00255
00256 curpos = object_list;
00257 while (curpos != NULL)
00258 {
00259 if (curpos->model->blend)
00260 DrawObject(curpos);
00261 curpos = curpos -> next;
00262 }
00263
00264 glPopMatrix();
00265 glPopAttrib();
00266
00267
00268
00269
00270
00271
00272
00273
00274 }
00275
00276 OBJECTNODE * OBJECTS::Add(VERTEX pos, float rotation, string modelname, string texname, bool mip, bool fullbright, bool skybox, bool drv, bool col, bool blend, JOEPACK * pack, float f1, float f2, float bl, float bm, float rr, float rd)
00277 {
00278 OBJECTNODE * oldfirst = object_list;
00279 object_list = new OBJECTNODE;
00280 object_list->next = oldfirst;
00281
00282 object_list->pos.x = pos.x;
00283
00284 object_list->pos.z = pos.z;
00285
00286 object_list->driveable = drv;
00287 object_list->cancollide = col;
00288
00289 object_list->friction1 = f1;
00290 object_list->friction2 = f2;
00291
00292 object_list->bumplength = bl;
00293 object_list->bumpmag = bm;
00294
00295 object_list->rolling_resistance_factor = rr;
00296 object_list->rolling_drag = rd;
00297
00298
00299 {
00300
00301 }
00302
00303
00304
00305
00306 OBJECTMODEL * mplist = model_list;
00307
00308 bool found = false;
00309 int count = 0;
00310 while (mplist != NULL && !found)
00311 {
00312
00313 if (mplist->name == modelname)
00314 {
00315 found = true;
00316 object_list->model = mplist;
00317 }
00318 mplist = mplist -> next;
00319 count++;
00320 }
00321
00322 if (!found)
00323 {
00324 object_list->model = AddModel(modelname, texname, mip, fullbright, skybox, blend, pack);
00325 object_list->texture = texname;
00326 }
00327
00328 return object_list;
00329 }
00330
00331 OBJECTNODE::OBJECTNODE()
00332 {
00333 dir.LoadMultIdent();
00334 }
00335
00336 OBJECTMODEL * OBJECTS::AddModel(string modelname, string texname, bool mip, bool fullbright, bool skybox, bool blend, JOEPACK * pack)
00337 {
00338 OBJECTMODEL * oldfirst = model_list;
00339 model_list = new OBJECTMODEL;
00340 model_list->next = oldfirst;
00341
00342 model_list->name = modelname;
00343 model_list->jmodel.Load(path + "/" + modelname, false, pack);
00344
00345 model_list->fullbright = fullbright;
00346 model_list->blend = blend;
00347 model_list->skybox = skybox;
00348
00349
00350 map <string, TEXTURE_HANDLE>::iterator tslot = texture_db.find(texname);
00351 if (tslot == texture_db.end())
00352 {
00353 TEXTURE_HANDLE newtexid;
00354 newtexid.Load(path + "/" + texname, mip);
00355 texture_db[texname] = newtexid;
00356
00357 model_list->jmodel.TextureID(&newtexid, 0);
00358 }
00359 else
00360 {
00361 model_list->jmodel.TextureID(&(tslot->second), 0);
00362 }
00363
00364
00365
00366
00367 return model_list;
00368 }
00369
00370 extern void LoadingScreen(string loadtext);
00371
00372 void OBJECTS::LoadObjectsFromFolder(string objectpath)
00373 {
00374 DeleteAll();
00375 collision.Clear();
00376
00377
00378
00379
00380 JOEPACK pack;
00381 JOEPACK * packptr = NULL;
00382
00383 if (pack.LoadPack(objectpath+"/objects.jpk"))
00384 {
00385 packptr = &pack;
00386
00387 }
00388
00389 OBJECTNODE * added = NULL;
00390
00391 ifstream o;
00392
00393 o.open((objectpath+"/list.txt").c_str());
00394
00395 path = objectpath;
00396
00397 if (o)
00398 {
00399 string m;
00400 string t;
00401 string extra;
00402 bool mip;
00403 bool fb, sb;
00404 bool blend;
00405 VERTEX p;
00406 float r;
00407 bool c, d;
00408 float f1, f2;
00409 float bl, bm;
00410 float rr, rd;
00411
00412 int count = 0;
00413
00414 const int expectedparams = 14;
00415 int numparams = expectedparams;
00416 numparams = utility.iGetParam(o);
00417
00418 if (numparams != expectedparams)
00419 {
00420 cerr << "Parameters per entry number incorrect, error in object list: " << objectpath+"/list.txt" << endl;
00421 cerr << "Expected " << expectedparams << " parameters, got " << numparams << endl;
00422 cerr << "Check the format.txt file in the VDrift-trackeditor/listedit/format.txt folder." << endl;
00423 return;
00424 }
00425
00426 while (!o.eof())
00427 {
00428 if (count % 100 == 0)
00429 {
00430
00431
00432
00433 string msg = "Loading...\nLoading scenery objects";
00434 for (int sn = 0; sn < count/100; sn++)
00435 msg = msg + ".";
00436 LoadingScreen(msg);
00437 }
00438
00439 m = utility.sGetParam(o);
00440 t = utility.sGetParam(o);
00441 mip = utility.bGetParam(o);
00442 fb = utility.bGetParam(o);
00443 sb = utility.bGetParam(o);
00444
00445 blend = utility.bGetParam(o);
00446
00447
00448 bl = utility.fGetParam(o);
00449 bm = utility.fGetParam(o);
00450
00451 p.zero();
00452 r = 0;
00453 d = utility.bGetParam(o);
00454 c = utility.bGetParam(o);
00455 f1 = utility.fGetParam(o);
00456 f2 = utility.fGetParam(o);
00457 rr = utility.fGetParam(o);
00458 rd = utility.fGetParam(o);
00459
00460 for (int i = 0; i < numparams - expectedparams; i++)
00461 {
00462 extra = utility.sGetParam(o);
00463 }
00464
00465 added = NULL;
00466
00467 if (m != "" && m != utility.GetEOFString())
00468 {
00469 added = Add(p, r, m, t, mip, fb, sb, d, c, blend, packptr, f1, f2, bl, bm, rr, rd);
00470 count++;
00471
00472 unsigned int i;
00473 for (i = 0; i < added->model->jmodel.GetFaces(); i++)
00474 {
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 collision.AddColNode(added, added->model->jmodel.GetFace(i));
00497 }
00498
00499 }
00500 }
00501
00502 o.close();
00503
00504 collision.GenerateCollisionTree();
00505
00506 GroupObjectListByTexture();
00507 }
00508 else
00509 {
00510 error_log << "Couldn't open Object List: " << objectpath << "/list.txt" << endl;
00511 }
00512
00513 if (packptr != NULL)
00514 packptr->ClosePack();
00515 }
00516
00517 bool OBJECTS::Collide(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, VERTEX & normal, float seglen, OBJECTNODE * &colnode)
00518 {
00519 return collision.CollideAABB(origin, direction, outtri, closest, normal, seglen, colnode);
00520 }
00521
00522 bool OBJECTS::CollideD(VERTEXD origin, VERTEXD direction, VERTEXD &outtri, bool closest, VERTEXD & normal, double seglen)
00523 {
00524 return collision.CollideAABB_double(origin, direction, outtri, closest, normal, seglen);
00525 }
00526
00527 bool OBJECTS::CollideDriveable(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, VERTEX & normal)
00528 {
00529 return collision.CollideDriveable(origin, direction, outtri, closest, normal);
00530 }
00531
00532 bool OBJECTS::CollideModel(VERTEX * modelverts, int numfaces, AABB bbox, VERTEX & outtri, bool closest, VERTEX & normal, float & depth)
00533 {
00534 return collision.CollideModelAABB(modelverts, numfaces, bbox, outtri, closest, normal, depth);
00535 }
00536
00537 OBJCOLNODE::OBJCOLNODE()
00538 {
00539 object = NULL;
00540 int i;
00541 for (i = 0; i < 3; i++)
00542 vertexIndex[i] = 0;
00543 }
00544
00545 bool OBJCOLNODE::operator==(const OBJCOLNODE & other)
00546 {
00547 return (object == other.object && vertexIndex[0] == other.vertexIndex[0] &&
00548 vertexIndex[1] == other.vertexIndex[1] &&
00549 vertexIndex[2] == other.vertexIndex[2]);
00550 }
00551
00552 bool OBJCOLNODE::EqualGeom(const OBJCOLNODE & other)
00553 {
00554 return (vertexIndex[0] == other.vertexIndex[0] &&
00555 vertexIndex[1] == other.vertexIndex[1] &&
00556 vertexIndex[2] == other.vertexIndex[2]);
00557 }
00558
00559 bool OBJCOLNODE::operator<(const OBJCOLNODE & other)
00560 {
00561 bool output = false;
00562
00563 int cmpresult = strcmp(object->model->name.c_str(),other.object->model->name.c_str());
00564
00565 if (cmpresult < 0)
00566 output = true;
00567 else if (cmpresult == 0)
00568 {
00569 if (vertexIndex[0] < other.vertexIndex[0])
00570 output = true;
00571 else if (vertexIndex[0] == other.vertexIndex[0])
00572 {
00573 if (vertexIndex[1] < other.vertexIndex[1])
00574 output = true;
00575 else if (vertexIndex[1] == other.vertexIndex[1])
00576 {
00577 if (vertexIndex[2] < other.vertexIndex[2])
00578 output = true;
00579 }
00580 }
00581 }
00582
00583 return output;
00584 }
00585
00586 OBJCOLNODE::OBJCOLNODE(const OBJCOLNODE & other)
00587 {
00588 object = other.object;
00589 vertexIndex[0] = other.vertexIndex[0];
00590 vertexIndex[1] = other.vertexIndex[1];
00591 vertexIndex[2] = other.vertexIndex[2];
00592 }
00593
00594 OBJCOLNODE& OBJCOLNODE::operator= (const OBJCOLNODE &other)
00595 {
00596 object = other.object;
00597 vertexIndex[0] = other.vertexIndex[0];
00598 vertexIndex[1] = other.vertexIndex[1];
00599 vertexIndex[2] = other.vertexIndex[2];
00600
00601 return *this;
00602 }
00603
00604 void OBJCOLNODE::SortVerts()
00605 {
00606 short omin, omax, omid;
00607 omin = omax = omid = 0;
00608 bool havemin = false;
00609 bool havemax = false;
00610 for (int i = 0; i < 3; i++)
00611 {
00612 if (!havemin)
00613 {
00614 omin = vertexIndex[i];
00615 havemin = true;
00616 }
00617
00618 if (!havemax)
00619 {
00620 omax = vertexIndex[i];
00621 havemax = true;
00622 }
00623
00624 if (vertexIndex[i] < omin)
00625 omin = vertexIndex[i];
00626 if (vertexIndex[i] > omax)
00627 omax = vertexIndex[i];
00628 }
00629
00630 for (int i = 0; i < 3; i++)
00631 {
00632 if (vertexIndex[i] > omin && vertexIndex[i] < omax)
00633 omid = vertexIndex[i];
00634 }
00635
00636 vertexIndex[0] = omin;
00637 vertexIndex[1] = omid;
00638 vertexIndex[2] = omax;
00639 }
00640
00641 void OBJECTCOLLISION::AddColNode(OBJECTNODE * newobject, short * newvi)
00642 {
00643 OBJCOLNODE temp;
00644 temp.object = newobject;
00645 int i;
00646 for (i = 0; i < 3; i++)
00647 temp.vertexIndex[i] = newvi[i];
00648
00649
00650
00651 if (COLLIDE_AND_DRIVE_TOGETHER)
00652 {
00653 if (newobject->cancollide || newobject->driveable)
00654 {
00655 colnodes.push_back(temp);
00656 drvnodes.push_back(temp);
00657 }
00658 }
00659 else
00660 {
00661 if (newobject->cancollide)
00662 {
00663 colnodes.push_back(temp);
00664 }
00665
00666 if (newobject->driveable)
00667 {
00668 drvnodes.push_back(temp);
00669 }
00670 }
00671 }
00672
00673 bool OBJECTCOLLISION::CollideDriveable(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, VERTEX & normal)
00674 {
00675 list <OBJCOLNODE>::iterator i1 = drvnodes.begin();
00676
00677 bool hadcollision = false;
00678 VERTEX curtri[3], tvert;
00679 int retval;
00680 float t,u,v;
00681
00682 origin.z = -origin.z;
00683
00684 int count = 0;
00685
00686 while (i1 != drvnodes.end())
00687 {
00688
00689 count++;
00690
00691 curtri[0].Set(i1->object->model->jmodel.GetVert(i1->vertexIndex[0]));
00692 curtri[1].Set(i1->object->model->jmodel.GetVert(i1->vertexIndex[1]));
00693 curtri[2].Set(i1->object->model->jmodel.GetVert(i1->vertexIndex[2]));
00694
00695
00696 int n;
00697 for (n = 0; n < 3; n++)
00698 curtri[n] = curtri[n] + i1->object->pos;
00699
00700 retval = INTERSECT_FUNCTION(origin.v3(), direction.v3(),
00701 curtri[0].v3(), curtri[1].v3(), curtri[2].v3(),
00702 &t, &u, &v);
00703
00704 if (retval)
00705 {
00706 if (t < 0)
00707 {
00708
00709 retval = 0;
00710 }
00711 else
00712 {
00713
00714 tvert = curtri[0].ScaleR(1-u-v) + curtri[1].ScaleR(u) + curtri[2].ScaleR(v);
00715
00716
00717 curtri[0].z = -curtri[0].z;
00718 curtri[1].z = -curtri[1].z;
00719 curtri[2].z = -curtri[2].z;
00720 normal = (curtri[2] - curtri[0]).cross(curtri[1] - curtri[0]);
00721 normal = normal.normalize();
00722
00723 if (normal.dot(direction) > 0)
00724 normal.Scale(-1);
00725
00726 if (!closest)
00727 {
00728 outtri = tvert;
00729
00730
00731 OBJCOLNODE temp;
00732 temp = *i1;
00733
00734
00735
00736
00737 drvnodes.erase(i1);
00738 drvnodes.insert(drvnodes.begin(), temp);
00739
00740 return true;
00741 }
00742 }
00743 }
00744
00745
00746
00747 if (retval && closest)
00748 {
00749 if ((hadcollision && (origin - tvert).len() < (origin - outtri).len()) || !hadcollision)
00750 {
00751
00752 outtri = tvert;
00753 }
00754
00755 hadcollision = true;
00756 }
00757
00758 i1++;
00759 }
00760
00761 if (closest && hadcollision)
00762 {
00763 return true;
00764 }
00765
00766
00767
00768 return false;
00769 }
00770
00771 OBJCOLBRANCH::OBJCOLBRANCH()
00772 {
00773 left = NULL;
00774 right = NULL;
00775 leaves.clear();
00776 }
00777
00778 void OBJCOLBRANCH::DeleteChildren()
00779 {
00780 leaves.clear();
00781
00782 if (left != NULL)
00783 {
00784 left->DeleteChildren();
00785 delete left;
00786 left = NULL;
00787 }
00788
00789 if (right != NULL)
00790 {
00791 right->DeleteChildren();
00792 delete right;
00793 right = NULL;
00794 }
00795 }
00796
00797 void OBJECTCOLLISION::GenerateCollisionTree()
00798 {
00799 bool verbose = false;
00800
00801 if (verbose)
00802 cout << "Generating collision tree..." << endl;
00803
00804 coltree.DeleteChildren();
00805
00806 if (verbose)
00807 cout << "deleted old tree" << endl;
00808
00809 if (verbose)
00810 cout << "Sorting collision nodes...";
00811
00812 if (verbose)
00813 cout << "done" << endl;
00814
00815 coltree.left = NULL;
00816 coltree.right = NULL;
00817
00818 coltree.leaves.clear();
00819
00820
00821 int count = 0;
00822
00823 for (list <OBJCOLNODE>::iterator i = colnodes.begin(); i != colnodes.end(); i++)
00824 {
00825 bool dup = false;
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 if (!dup)
00836 {
00837 coltree.leaves.push_back(&(*i));
00838 count++;
00839 }
00840 }
00841
00842 if (verbose)
00843 cout << "copied leaves: " << count << "/" << colnodes.size() << endl;
00844
00845 GenerateBranches(&coltree);
00846
00847 if (verbose)
00848 cout << "done" << endl;
00849 }
00850
00851 void OBJECTCOLLISION::GenerateBranches(OBJCOLBRANCH * branch)
00852 {
00853 bool verbose = false;
00854
00855 list <OBJCOLNODE *>::iterator i1 = branch->leaves.begin();
00856
00857
00858 VERTEX avgcenter;
00859 float maxv[3];
00860 float minv[3];
00861 bool havevals[6];
00862 int n = 0;
00863 for (n = 0; n < 6; n++)
00864 havevals[n] = false;
00865
00866
00867
00868 int numleaves = 0;
00869
00870 for (i1 = branch->leaves.begin(); i1 != branch->leaves.end(); i1++)
00871 numleaves++;
00872
00873 i1 = branch->leaves.begin();
00874 while (i1 != branch->leaves.end())
00875 {
00876 VERTEX p[3];
00877 p[0].Set((*i1)->object->model->jmodel.GetVert((*i1)->vertexIndex[0]));
00878 p[1].Set((*i1)->object->model->jmodel.GetVert((*i1)->vertexIndex[1]));
00879 p[2].Set((*i1)->object->model->jmodel.GetVert((*i1)->vertexIndex[2]));
00880
00881 int i, c;
00882 for (c = 0; c < 3; c++)
00883 {
00884 float * v = p[c].v3();
00885 for (i = 0; i < 3; i++)
00886 {
00887 if (v[i] > maxv[i] || !havevals[i])
00888 {
00889 maxv[i] = v[i];
00890 havevals[i] = true;
00891 }
00892 if (v[i] < minv[i] || !havevals[i+3])
00893 {
00894 minv[i] = v[i];
00895 havevals[i+3] = true;
00896 }
00897 }
00898 }
00899
00900 VERTEX pcenter = p[0] + p[1] + p[2];
00901 pcenter.Scale(0.333333);
00902 avgcenter = avgcenter + pcenter.ScaleR(1.0/numleaves);
00903
00904 i1++;
00905 }
00906
00907 VERTEX minvals, maxvals;
00908 minvals.Set(minv);
00909 maxvals.Set(maxv);
00910 branch->bbox.SetFromCorners(minvals, maxvals);
00911 if (verbose)
00912 {
00913 cout << "Bounding box:" << endl;
00914 branch->bbox.GetPos().DebugPrint();
00915 branch->bbox.GetSize().DebugPrint();
00916 branch->bbox.GetCenter().DebugPrint();
00917 }
00918
00919
00920 VERTEX axismask;
00921 axismask.Set(1,0,0);
00922 if (maxvals.x - minvals.x > maxvals.y - minvals.y && maxvals.x - minvals.x > maxvals.z - minvals.z)
00923 {
00924 axismask.Set(1,0,0);
00925 }
00926 else if (maxvals.y - minvals.y > maxvals.x - minvals.x && maxvals.y - minvals.y > maxvals.z - minvals.z)
00927 {
00928 axismask.Set(0,1,0);
00929 }
00930 else if (maxvals.z - minvals.z > maxvals.y - minvals.y && maxvals.z - minvals.z > maxvals.x - minvals.x)
00931 {
00932 axismask.Set(0,0,1);
00933 }
00934
00935 int ll = 0;
00936 int lr = 0;
00937
00938
00939 if (numleaves > TRIANGLES_PER_BBOX)
00940 {
00941
00942 branch->left = new OBJCOLBRANCH;
00943 branch->right = new OBJCOLBRANCH;
00944
00945 int distributor = 0;
00946
00947
00948 for (i1 = branch->leaves.begin(); i1 != branch->leaves.end(); i1++)
00949 {
00950 VERTEX p[3];
00951 p[0].Set((*i1)->object->model->jmodel.GetVert((*i1)->vertexIndex[0]));
00952 p[1].Set((*i1)->object->model->jmodel.GetVert((*i1)->vertexIndex[1]));
00953 p[2].Set((*i1)->object->model->jmodel.GetVert((*i1)->vertexIndex[2]));
00954
00955 VERTEX pcenter = p[0] + p[1] + p[2];
00956 pcenter.Scale(0.333333);
00957
00958 if (pcenter.dot(axismask) - avgcenter.dot(axismask) > 0.0)
00959 {
00960 branch->right->leaves.push_back(*i1);
00961 distributor = 1;
00962 }
00963 else if (pcenter.dot(axismask) - avgcenter.dot(axismask) < 0.0)
00964 {
00965 branch->left->leaves.push_back(*i1);
00966 distributor = 0;
00967 }
00968 else
00969 {
00970
00971 if (distributor % 2 == 0)
00972 branch->right->leaves.push_back(*i1);
00973 else
00974 branch->left->leaves.push_back(*i1);
00975
00976 distributor++;
00977 }
00978 }
00979
00980
00981 branch->leaves.clear();
00982
00983
00984 for (i1 = branch->left->leaves.begin(); i1 != branch->left->leaves.end(); i1++)
00985 ll++;
00986 for (i1 = branch->right->leaves.begin(); i1 != branch->right->leaves.end(); i1++)
00987 lr++;
00988
00989 if (verbose) cout << "Parent Leaves: " << numleaves << " L: " << ll << " R: " << lr << endl;
00990
00991 if (ll == 0 || lr == 0)
00992 {
00993 if (lr != 0)
00994 {
00995 for (i1 = branch->right->leaves.begin(); i1 != branch->right->leaves.end(); i1++)
00996 branch->leaves.push_back(*i1);
00997 branch->right->leaves.clear();
00998 }
00999
01000 if (ll != 0)
01001 {
01002 for (i1 = branch->left->leaves.begin(); i1 != branch->left->leaves.end(); i1++)
01003 branch->leaves.push_back(*i1);
01004 branch->left->leaves.clear();
01005 }
01006
01007 delete branch->left;
01008 branch->left = NULL;
01009
01010 delete branch->right;
01011 branch->right = NULL;
01012 }
01013 else
01014 {
01015 GenerateBranches(branch->left);
01016 GenerateBranches(branch->right);
01017 }
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032 }
01033 else
01034 {
01035 branch->right = NULL;
01036 branch->left = NULL;
01037
01038 if (verbose) cout << "(Leaf)" << endl;
01039 }
01040 }
01041
01042 void OBJECTCOLLISION::Clear()
01043 {
01044 coltree.DeleteChildren();
01045 colnodes.clear();
01046 drvnodes.clear();
01047 }
01048
01049 OBJECTCOLLISION::~OBJECTCOLLISION()
01050 {
01051 Clear();
01052 }
01053
01054 bool OBJECTCOLLISION::CollideModelAABB(VERTEX * modelverts, int numfaces, AABB modelbbox, VERTEX & outtri, bool closest, VERTEX & normal, float & depth)
01055 {
01056 normal.zero();
01057
01058 int testcount = 0;
01059
01060 bool col = CollideBranchModel(modelverts, numfaces, modelbbox, outtri, closest, &coltree, normal, depth, testcount);
01061
01062
01063
01064 normal = normal.normalize();
01065
01066 return col;
01067 }
01068
01069 bool OBJECTCOLLISION::CollideAABB(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, VERTEX & normal, float seglen, OBJECTNODE * &colnode)
01070 {
01071 bool col = false;
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 origin.z = -origin.z;
01085 int count = 0;
01086 col = CollideBranch(origin, direction, outtri, closest, &coltree, normal, seglen, count, colnode);
01087
01088
01089
01090
01091 return col;
01092 }
01093
01094 bool OBJECTCOLLISION::CollideAABB_double(VERTEXD origin, VERTEXD direction, VERTEXD &outtri, bool closest, VERTEXD & normal, double seglen)
01095 {
01096 bool col = false;
01097
01098 origin.z = -origin.z;
01099 direction.z = -direction.z;
01100
01101 col = CollideBranch_double(origin, direction, outtri, closest, &coltree, normal, seglen);
01102
01103 return col;
01104 }
01105
01106 bool OBJECTCOLLISION::CollideBranch(VERTEX origin, VERTEX direction, VERTEX &outtri, bool closest, OBJCOLBRANCH * branch, VERTEX & normal, float seglen, int & testcount, OBJECTNODE * &colnode)
01107 {
01108 if (branch == NULL)
01109 return false;
01110
01111 bool verbose = false;
01112 bool collideverbose = false;
01113
01114 if (verbose)
01115 {
01116 if (branch->left != NULL && branch->right != NULL)
01117 {
01118 cout << "Parent" << endl;
01119 }
01120 else
01121 cout << "Leaf" << endl;
01122 }
01123
01124
01125 if (branch->left == NULL && branch->right == NULL)
01126 {
01127 testcount++;
01128
01129 bool hadcollision = false;
01130 VERTEX curtri[3], tvert;
01131 VERTEX tnorm;
01132 float t,u,v;
01133
01134 int retval = 0;
01135
01136 list <OBJCOLNODE *>::iterator i1 = branch->leaves.begin();
01137
01138 <