00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #define GL_GLEXT_PROTOTYPES
00027
00028 #include "utility.h"
00029 #include "textures.h"
00030 #include <fstream>
00031
00032 #ifdef _WIN32
00033
00034 #include <GL/glext.h>
00035 #include <GL/glut.h>
00036
00037
00038 #include <windows.h>
00039 #endif
00040
00041 #ifdef _WIN32
00042 PFNGLMULTITEXCOORD2FARBPROC pglMultiTexCoord2f = NULL;
00043 PFNGLMULTITEXCOORD4FARBPROC pglMultiTexCoord4f = NULL;
00044 PFNGLCLIENTACTIVETEXTUREARBPROC pglActiveTexture = NULL;
00045 PFNGLACTIVETEXTUREARBPROC pglClientActiveTexture = NULL;
00046 #endif
00047
00048
00049 #ifndef _WIN32
00050 #include <sys/types.h>
00051 #include <dirent.h>
00052 #endif
00053
00054 const float DEG2RAD = 3.14159 / 180.0;
00055
00056 void UTILITY::SelectTU(int TU)
00057 {
00058 if (!initdone)
00059 {
00060 initerror();
00061 return;
00062 }
00063
00064 GLenum tuenum;
00065
00066 if (TU == 0)
00067 tuenum = GL_TEXTURE0_ARB;
00068 else if (TU == 1)
00069 tuenum = GL_TEXTURE1_ARB;
00070 else if (TU == 2)
00071 tuenum = GL_TEXTURE2_ARB;
00072 else if (TU == 3)
00073 tuenum = GL_TEXTURE3_ARB;
00074 else
00075 tuenum = GL_TEXTURE0_ARB;
00076
00077 #ifdef _WIN32
00078 pglActiveTexture(tuenum);
00079 #else
00080 glActiveTextureARB(tuenum);
00081 #endif
00082 }
00083
00084 void UTILITY::TexCoord2d2f(int TU, float u, float v)
00085 {
00086 if (!initdone)
00087 {
00088 initerror();
00089 return;
00090 }
00091
00092 GLenum tuenum;
00093
00094 if (TU+1 > nb_multitexture)
00095 return;
00096
00097 if (TU == 0)
00098 tuenum = GL_TEXTURE0_ARB;
00099 else if (TU == 1)
00100 tuenum = GL_TEXTURE1_ARB;
00101 else if (TU == 2)
00102 tuenum = GL_TEXTURE2_ARB;
00103 else if (TU == 3)
00104 tuenum = GL_TEXTURE3_ARB;
00105 else
00106 tuenum = GL_TEXTURE0_ARB;
00107
00108 #ifdef _WIN32
00109 pglMultiTexCoord2f(tuenum, u, v);
00110 #else
00111 glMultiTexCoord2fARB(tuenum, u, v);
00112 #endif
00113 }
00114
00115 GLuint UTILITY::TexLoad(string filename, int format, bool mipmap, int &w, int &h, const bool supressederror, bool &err)
00116 {
00117 return TexLoad(filename, format, mipmap, w, h, supressederror, err, 0);
00118 }
00119
00120 GLuint UTILITY::TexLoad(string filename, int format, bool mipmap, int &w, int &h, const bool supressederror, bool &err, int attempt)
00121 {
00122 string filepath;
00123 string texture_size;
00124 char buffer[1024];
00125
00126 settings.Get( "display.texture_size", texture_size );
00127
00128 switch (attempt)
00129 {
00130 case 0:
00131 filepath = filename;
00132 break;
00133
00134 case 1:
00135 filepath = settings.GetFullDataPath(filename);
00136 break;
00137
00138 case 2:
00139 filepath = settings.GetFullDataPath("textures/" + texture_size + "/" + filename);
00140 break;
00141
00142 default:
00143 filepath = filename;
00144 break;
00145 }
00146
00147
00148
00149 strcpy(buffer, filepath.c_str());
00150
00151 GLuint new_handle = 0;
00152
00153
00154 SDL_Surface *TextureImage[1];
00155
00156
00157 if ((TextureImage[0]=IMG_Load(buffer)))
00158 {
00159
00160
00161 w = TextureImage[0]->w;
00162 h = TextureImage[0]->h;
00163
00164 switch (TextureImage[0]->format->BytesPerPixel)
00165 {
00166 case 1:
00167 format = GL_LUMINANCE;
00168 break;
00169 case 2:
00170 format = GL_LUMINANCE_ALPHA;
00171 break;
00172 case 3:
00173 format = GL_RGB;
00174 break;
00175 case 4:
00176 format = GL_RGBA;
00177 break;
00178 default:
00179 break;
00180 }
00181
00182 glGenTextures(1, &new_handle);
00183
00184
00185 glBindTexture(GL_TEXTURE_2D, new_handle);
00186 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00187 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00188 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00189
00190 if (mipmap)
00191 {
00192 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
00193 gluBuild2DMipmaps( GL_TEXTURE_2D, format, TextureImage[0]->w, TextureImage[0]->h, format, GL_UNSIGNED_BYTE, TextureImage[0]->pixels );
00194 }
00195 else
00196 {
00197 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00198 glTexImage2D( GL_TEXTURE_2D, 0, format, TextureImage[0]->w, TextureImage[0]->h, 0, format, GL_UNSIGNED_BYTE, TextureImage[0]->pixels );
00199 }
00200
00201
00202 int anisotropy = 0;
00203 settings.Get( "display.anisotropic", anisotropy );
00204 if (gfxcard.GetCapability(CARDINFOTYPE::ANISOTROPY) && anisotropy > 0)
00205 {
00206
00207 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)anisotropy);
00208 }
00209
00210 err = false;
00211 }
00212 else
00213 {
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 attempt++;
00236
00237 if (attempt > 2)
00238 {
00239 err = true;
00240 if (!supressederror) error_log << "Could not find texture: " << filename << "\n";
00241 return 0;
00242 }
00243 else
00244 {
00245 return TexLoad(filename, format, mipmap, w, h, supressederror, err, attempt);
00246 }
00247 }
00248
00249 if (TextureImage[0])
00250 {
00251
00252 SDL_FreeSurface( TextureImage[0] );
00253 }
00254
00255 return new_handle;
00256 }
00257
00258 GLuint UTILITY::TexLoad(string texfile, bool mipmap)
00259 {
00260 return TexLoad(texfile, GL_RGBA, mipmap);
00261 }
00262
00263 GLuint UTILITY::TexLoad(string filename, int format, bool mipmap)
00264 {
00265 int dw, dh, new_handle;
00266 bool err = false;
00267
00268 new_handle = TexLoad(filename, format, mipmap, dw, dh, false, err);
00269
00270 return new_handle;
00271 }
00272
00273 UTILITY::UTILITY()
00274 {
00275 error_log.open((settings.GetSettingsDir() + "/logs/utility.log").c_str());
00276 initdone = false;
00277 }
00278
00279 extern bool verbose_output;
00280 UTILITY::~UTILITY()
00281 {
00282 if (verbose_output)
00283 cout << "utility deinit" << endl;
00284
00285 error_log.close();
00286 }
00287
00288 void UTILITY::Init()
00289 {
00290
00291
00292 #ifdef _WIN32
00293 pglMultiTexCoord4f = (PFNGLMULTITEXCOORD4FARBPROC) wglGetProcAddress("glMultiTexCoord4fARB");
00294 pglMultiTexCoord2f = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");
00295 pglActiveTexture = (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB");
00296 pglClientActiveTexture = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB");
00297
00298 if (pglMultiTexCoord4f == NULL)
00299 error_log << "main, WIN32: wglGetProcAddress(\"glMultiTexCoord4fARB\") failed." << endl;
00300 if (pglMultiTexCoord2f == NULL)
00301 error_log << "main, WIN32: wglGetProcAddress(\"glMultiTexCoord2fARB\") failed." << endl;
00302 if (pglActiveTexture == NULL)
00303 error_log << "main, WIN32: wglGetProcAddress(\"glActiveTextureARB\") failed." << endl;
00304 if (pglClientActiveTexture == NULL)
00305 error_log << "main, WIN32: wglGetProcAddress(\"glClientActiveTextureARB\") failed." << endl;
00306
00307
00308 #endif
00309
00310
00311 glGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB,&nb_multitexture );
00312
00313
00314
00315 cout << "Multitexture units (4 are required for all effects): " << nb_multitexture << endl;
00316 if (nb_multitexture < 2)
00317 cout << "You have less than the recommended number of texture units." << endl << "Some effects will not be rendered." << endl << "Upgrade your graphics card!" << endl;
00318 else if (nb_multitexture <= 3)
00319 cout << "You have less than the recommended number of texture units." << endl << "Some textures will lack detail." << endl << "Upgrade your graphics card!" << endl;
00320 else
00321 cout << "Your GPU meets the texture unit requirements." << endl;
00322
00323 cout << endl << "Note to user: All error messages will be put in " + settings.GetSettingsDir() + "/logs/." << endl;
00324
00325 initdone = true;
00326 }
00327
00328 string UTILITY::sGetLine(ifstream &ffrom)
00329 {
00330 string trashstr;
00331 char trashchar[1024];
00332
00333
00334 ffrom.getline(trashchar,1024,'\n');
00335
00336 while ((trashchar[0] == '#' || strlen(trashchar) <= 1 ) && !ffrom.eof())
00337 {
00338 ffrom.getline(trashchar, 1024, '\n');
00339
00340
00341 }
00342 trashstr = trashchar;
00343
00344 if (ffrom.eof() && trashstr.length() == 0)
00345 return ENDOFFILESTRING;
00346 else
00347 return trashstr;
00348 }
00349
00350 string UTILITY::sGetParam(ifstream &ffrom)
00351 {
00352 string trashstr;
00353 char trashchar[1024];
00354
00355 ffrom >> trashstr;
00356
00357 while (trashstr.c_str()[0] == '#' && !ffrom.eof() && trashstr != "")
00358 {
00359 ffrom.getline(trashchar, 1024, '\n');
00360 ffrom >> trashstr;
00361 }
00362
00363 if (ffrom.eof() && trashstr.c_str()[0] == '#')
00364 return ENDOFFILESTRING;
00365 else
00366 return trashstr;
00367 }
00368
00369 int UTILITY::iGetParam(ifstream &ffrom)
00370 {
00371 string trashstr;
00372 char trashchar[1024];
00373
00374 ffrom >> trashstr;
00375
00376 while (trashstr.c_str()[0] == '#' && !ffrom.eof())
00377 {
00378 ffrom.getline(trashchar, 1024, '\n');
00379 ffrom >> trashstr;
00380 }
00381
00382 return atoi(trashstr.c_str());
00383 }
00384
00385 float UTILITY::fGetParam(ifstream &ffrom)
00386 {
00387 string trashstr;
00388 char trashchar[1024];
00389
00390 ffrom >> trashstr;
00391
00392 while (trashstr.c_str()[0] == '#' && !ffrom.eof())
00393 {
00394 ffrom.getline(trashchar, 1024, '\n');
00395 ffrom >> trashstr;
00396 }
00397
00398 return atof(trashstr.c_str());
00399 }
00400
00401 void UTILITY::initerror()
00402 {
00403
00404 }
00405
00406 void UTILITY::Tex2D(int TU, bool enable)
00407 {
00408 if (!initdone)
00409 {
00410 initerror();
00411 return;
00412 }
00413
00414 SelectTU(TU);
00415 if (enable)
00416 glEnable(GL_TEXTURE_2D);
00417 else
00418 glDisable(GL_TEXTURE_2D);
00419 }
00420
00421 bool UTILITY::bGetParam(ifstream &ffrom)
00422 {
00423 string trashstr;
00424 char trashchar[1024];
00425
00426 ffrom >> trashstr;
00427
00428 while (trashstr.c_str()[0] == '#' && !ffrom.eof())
00429 {
00430 ffrom.getline(trashchar, 1024, '\n');
00431 ffrom >> trashstr;
00432 }
00433
00434 if (trashstr == "true" || trashstr == "1" || trashstr == "on")
00435 return true;
00436 else
00437 return false;
00438 }
00439
00440 int UTILITY::numTUs()
00441 {
00442 if (!initdone)
00443 {
00444 initerror();
00445 return 0;
00446 }
00447
00448 return nb_multitexture;
00449 }
00450
00451 void UTILITY::Draw2D(float x1, float y1, float x2, float y2, TEXTURE_HANDLE * texid)
00452 {
00453 Draw2D(x1, y1, x2, y2, texid, 0.0);
00454 }
00455
00456 void UTILITY::Draw2D(float x1, float y1, float x2, float y2, TEXTURE_HANDLE * texid, float rotation)
00457 {
00458 Draw2D(x1, y1, x2, y2, texid, rotation, 0);
00459 }
00460
00461 void UTILITY::Draw2D(float x1, float y1, float x2, float y2, TEXTURE_HANDLE * texid, float rotation, int texsize)
00462 {
00463 Draw2D(x1, y1, x2, y2, texid, rotation, texsize, 1.0);
00464 }
00465
00466 void UTILITY::Draw2D(float x1, float y1, float x2, float y2, TEXTURE_HANDLE * texid, float rotation, int texsize, float opacity)
00467 {
00468 int sx, sy;
00469
00470 QUATERNION rot;
00471 rot.Rotate(rotation, 0,0,1);
00472
00473 glPushAttrib(GL_ALL_ATTRIB_BITS);
00474 Tex2D(0, true);
00475
00476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00477 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00478
00479 sx = 1600;
00480 sy = 1200;
00481
00482 int x = (int) (x1*(float)sx);
00483 int y = (int) ((1.0-y1)*(float)sy);
00484
00485 int w = (int) ((x2-x1)*(float)sx);
00486 int h = (int) ((y2-y1)*(float)sy);
00487
00488
00489
00490 texid->Activate();
00491
00492
00493 glDisable( GL_DEPTH_TEST );
00494
00495 glDisable( GL_LIGHTING);
00496 glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
00497 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00498 glEnable( GL_BLEND );
00499
00500
00501 glMatrixMode( GL_PROJECTION );
00502
00503 glPushMatrix( );
00504
00505
00506 glLoadIdentity( );
00507
00508 glOrtho( 0, sx, 0, sy, -1, 1 );
00509
00510
00511 glMatrixMode( GL_MODELVIEW );
00512
00513 glPushMatrix( );
00514
00515 glLoadIdentity( );
00516
00517
00518 glTranslated( x, y, 0 );
00519
00520
00521
00522
00523
00524
00525
00526
00527 glColor4f(1,1,1,opacity);
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 VERTEX v[4];
00549 v[0].Set(0,0,0);
00550 v[1].Set(w,0,0);
00551 v[2].Set(w,-h,0);
00552 v[3].Set(0,-h,0);
00553
00554 int i;
00555
00556 for (i = 0; i < 4; i++)
00557 {
00558 v[i].x -= w/2.0;
00559 v[i].y += h/2.0;
00560 }
00561
00562 for (i = 0; i < 4; i++)
00563 v[i] = rot.RotateVec(v[i]);
00564
00565 for (i = 0; i < 4; i++)
00566 {
00567 v[i].x += w/2.0;
00568 v[i].y -= h/2.0;
00569 }
00570
00571 float tmin, tmax;
00572 tmin = 0;
00573 tmax = 1;
00574 if (texsize > 0)
00575 {
00576 tmin = 1.0/(float)texsize;
00577 tmax = ((float)texsize-1.0)/(float)texsize;
00578 }
00579
00580
00581 glBegin( GL_QUADS );
00582
00583 glTexCoord2f( tmin, tmin);
00584
00585 glVertex2f( v[0].x, v[0].y );
00586
00587
00588 glTexCoord2f( tmax, tmin);
00589
00590 glVertex2f( v[1].x, v[1].y );
00591
00592
00593 glTexCoord2f( tmax, tmax);
00594
00595 glVertex2f( v[2].x, v[2].y );
00596
00597
00598 glTexCoord2f( tmin, tmax);
00599
00600 glVertex2f( v[3].x, v[3].y );
00601 glEnd( );
00602
00603
00604 glMatrixMode( GL_PROJECTION );
00605
00606 glPopMatrix( );
00607
00608
00609 glMatrixMode( GL_MODELVIEW );
00610
00611 glPopMatrix( );
00612
00613
00614 glEnable( GL_DEPTH_TEST );
00615
00616 glEnable( GL_LIGHTING);
00617 glDisable(GL_BLEND);
00618
00619 glPopAttrib();
00620 }
00621
00622 void UTILITY::DrawEllipse( float center_x, float center_y, float radius_x, float radius_y, float color_r, float color_g, float color_b, float opacity )
00623 {
00624 int sx = 1600;
00625 int sy = 1200;
00626 int x = (int)( center_x * (float)sx );
00627 int y = (int)( ( 1.0 - center_y ) * (float)sy );
00628
00629 glLoadIdentity();
00630 glTranslated( x, y, 0 );
00631 glColor4f( color_r, color_g, color_b, opacity );
00632
00633 glBegin( GL_LINE_LOOP );
00634
00635 for( int i = 0; i < 360; i++ )
00636 {
00637
00638 float rad = i * DEG2RAD;
00639 glVertex2f( cos( rad ) * radius_x, sin( rad ) * radius_y );
00640 }
00641
00642 glEnd();
00643 }
00644
00645 float UTILITY::GetValue(SDL_Surface * surf, int channel, float x, float y, bool interpolate)
00646 {
00647 return GetValue(surf, channel, x, y, interpolate, false);
00648 }
00649
00650 float UTILITY::GetValue(SDL_Surface * surf, int channel, float x, float y, bool interpolate, bool wrap)
00651 {
00652
00653 if (!(x < 0 || x >= 0) || !(y < 0 || y >= 0))
00654 return 0;
00655
00656 if (channel >= surf->format->BytesPerPixel || channel < 0)
00657 {
00658 error_log << "Asked for channel " << channel << ", image only has " << surf->format->BytesPerPixel << endl;
00659 channel = surf->format->BytesPerPixel - 1;
00660 }
00661
00662 {
00663 if (x < 0)
00664 x = 0;
00665 if (x > 1)
00666 x = 1;
00667 if (y < 0)
00668 y = 0;
00669 if (y > 1)
00670 y = 1;
00671 int ix, iy;
00672 ix = (int)(x * surf->w);
00673 iy = (int)(y * surf->h);
00674 float dx, dy;
00675 dx = x - ix;
00676 dy = y - iy;
00677
00678 unsigned char * pix;
00679 pix = (unsigned char *) surf->pixels;
00680
00681 if (ix >= surf->w)
00682 {
00683 if (wrap)
00684 ix = ix % surf->w;
00685 else
00686 ix = surf->w - 1;
00687 }
00688 if (iy >= surf->h)
00689 {
00690 if (wrap)
00691 iy = iy % surf->h;
00692 else
00693 iy = surf->h - 1;
00694 }
00695
00696 if (!interpolate)
00697 {
00698 return pix[(ix+surf->pitch*iy)*surf->format->BytesPerPixel+channel] / 255.0f;
00699 }
00700 else
00701 {
00702 float ul, ur, ll, lr;
00703
00704 int rx, ry;
00705
00706 rx = ix + 1;
00707 if (rx >= surf->w)
00708 {
00709 if (wrap)
00710 rx = rx % surf->w;
00711 else
00712 rx = ix;
00713 }
00714
00715 ry = iy + 1;
00716 if (ry >= surf->h)
00717 {
00718 if (wrap)
00719 ry = ry % surf->h;
00720 else
00721 ry = iy;
00722 }
00723
00724 rx = ix;
00725 ry = iy;
00726
00727 ul = pix[(ix+surf->pitch*iy)*surf->format->BytesPerPixel+channel] / 255.0f;
00728 ur = pix[(rx+surf->pitch*iy)*surf->format->BytesPerPixel+channel] / 255.0f;
00729 ll = pix[(ix+surf->pitch*ry)*surf->format->BytesPerPixel+channel] / 255.0f;
00730 lr = pix[(rx+surf->pitch*ry)*surf->format->BytesPerPixel+channel] / 255.0f;
00731
00732 float u, l;
00733
00734 u = ul*(1.0-dx)+ur*dx;
00735 l = ll*(1.0-dx)+lr*dx;
00736
00737 return u*(1.0-dy)+l*dy;
00738 }
00739 }
00740 }
00741
00742 bool UTILITY::FileExists(string filename)
00743 {
00744 ifstream test;
00745 test.open(filename.c_str());
00746 if (test)
00747 {
00748 test.close();
00749 return true;
00750 }
00751 else
00752 return false;
00753 }
00754
00755 int UTILITY::IntersectTriangleD(double orig[3], double dir[3],
00756 double vert0[3], double vert1[3], double vert2[3],
00757 double *t, double *u, double *v)
00758 {
00759 double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
00760 double det,inv_det;
00761
00762
00763 SUB(edge1, vert1, vert0);
00764 SUB(edge2, vert2, vert0);
00765
00766
00767 CROSS(pvec, dir, edge2);
00768
00769
00770 det = DOT(edge1, pvec);
00771
00772 #ifdef TEST_CULL
00773 if (det < EPSILON)
00774 return 0;
00775
00776
00777 SUB(tvec, orig, vert0);
00778
00779
00780 *u = DOT(tvec, pvec);
00781 if (*u < 0.0 || *u > det)
00782 return 0;
00783
00784
00785 CROSS(qvec, tvec, edge1);
00786
00787
00788 *v = DOT(dir, qvec);
00789 if (*v < 0.0 || *u + *v > det)
00790 return 0;
00791
00792
00793 *t = DOT(edge2, qvec);
00794 inv_det = 1.0 / det;
00795 *t *= inv_det;
00796 *u *= inv_det;
00797 *v *= inv_det;
00798 #else
00799 if (det > -EPSILON && det < EPSILON)
00800 return 0;
00801 inv_det = 1.0 / det;
00802
00803
00804 SUB(tvec, orig, vert0);
00805
00806
00807 *u = DOT(tvec, pvec) * inv_det;
00808 if (*u < 0.0 || *u > 1.0)
00809 return 0;
00810
00811
00812 CROSS(qvec, tvec, edge1);
00813
00814
00815 *v = DOT(dir, qvec) * inv_det;
00816 if (*v < 0.0 || *u + *v > 1.0)
00817 return 0;
00818
00819
00820 *t = DOT(edge2, qvec) * inv_det;
00821 #endif
00822 return 1;
00823 }
00824
00825 int UTILITY::IntersectTriangleF(float orig[3], float dir[3],
00826 float vert0[3], float vert1[3], float vert2[3],
00827 float *t, float *u, float *v)
00828 {
00829 float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
00830 float det,inv_det;
00831
00832
00833 SUB(edge1, vert1, vert0);
00834 SUB(edge2, vert2, vert0);
00835
00836
00837 CROSS(pvec, dir, edge2);
00838
00839
00840 det = DOT(edge1, pvec);
00841
00842 #ifdef TEST_CULL
00843 if (det < EPSILON)
00844 return 0;
00845
00846
00847 SUB(tvec, orig, vert0);
00848
00849
00850 *u = DOT(tvec, pvec);
00851 if (*u < 0.0 || *u > det)
00852 return 0;
00853
00854
00855 CROSS(qvec, tvec, edge1);
00856
00857
00858 *v = DOT(dir, qvec);
00859 if (*v < 0.0 || *u + *v > det)
00860 return 0;
00861
00862
00863 *t = DOT(edge2, qvec);
00864 inv_det = 1.0 / det;
00865 *t *= inv_det;
00866 *u *= inv_det;
00867 *v *= inv_det;
00868 #else
00869 if (det > -EPSILON && det < EPSILON)
00870 return 0;
00871 inv_det = 1.0 / det;
00872
00873
00874 SUB(tvec, orig, vert0);
00875
00876
00877 *u = DOT(tvec, pvec) * inv_det;
00878 if (*u < 0.0 || *u > 1.0)
00879 return 0;
00880
00881
00882 CROSS(qvec, tvec, edge1);
00883
00884
00885 *v = DOT(dir, qvec) * inv_det;
00886 if (*v < 0.0 || *u + *v > 1.0)
00887 return 0;
00888
00889
00890 *t = DOT(edge2, qvec) * inv_det;
00891 #endif
00892 if (isNaN(*u) || isNaN(*v) || isNaN(*t))
00893 return 0;
00894 return 1;
00895 }
00896
00897 void UTILITY::DrawButton(float x1, float y1, float x2, float y2, float sidewidth, TEXTURE_HANDLE * texid, float opacity)
00898 {
00899 int sx, sy;
00900
00901
00902
00903
00904 glPushAttrib(GL_ALL_ATTRIB_BITS);
00905
00906 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00907 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00908
00909 sx = 1600;
00910 sy = 1200;
00911
00912 int x = (int) (x1*(float)sx);
00913 int y = (int) ((1.0-y1)*(float)sy);
00914
00915 int w = (int) ((x2-x1)*(float)sx);
00916 int h = (int) ((y2-y1)*(float)sy);
00917
00918 int sw = (int) (sidewidth * (float) sx);
00919
00920
00921
00922 texid->Activate();
00923
00924
00925 glDisable( GL_DEPTH_TEST );
00926
00927 glDisable( GL_LIGHTING);
00928 glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
00929 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00930 glEnable( GL_BLEND );
00931
00932
00933 glMatrixMode( GL_PROJECTION );
00934
00935 glPushMatrix( );
00936
00937
00938 glLoadIdentity( );
00939
00940 glOrtho( 0, sx, 0, sy, -1, 1 );
00941
00942
00943 glMatrixMode( GL_MODELVIEW );
00944 glPushMatrix( );
00945 glLoadIdentity( );
00946 glTranslated( x, y, 0 );
00947 glColor4f(1,1,1,opacity);
00948
00949 VERTEX v[4];
00950 v[0].Set(0,0,0);
00951 v[1].Set(sw,0,0);
00952 v[2].Set(sw,-h,0);
00953 v[3].Set(0,-h,0);
00954
00955 glTranslated(-sw, 0, 0);
00956
00957
00958 glBegin( GL_QUADS );
00959
00960 glTexCoord2f( 0, 0);
00961
00962 glVertex2f( v[0].x, v[0].y );
00963
00964
00965 glTexCoord2f( 0.5, 0);
00966
00967 glVertex2f( v[1].x, v[1].y );
00968
00969
00970 glTexCoord2f( 0.5, 1);
00971
00972 glVertex2f( v[2].x, v[2].y );
00973
00974
00975 glTexCoord2f( 0, 1);
00976
00977 glVertex2f( v[3].x, v[3].y );
00978 glEnd( );
00979
00980 glTranslated(sw, 0, 0);
00981
00982 v[0].Set(0,0,0);
00983 v[1].Set(w,0,0);
00984 v[2].Set(w,-h,0);
00985 v[3].Set(0,-h,0);
00986
00987
00988 glBegin( GL_QUADS );
00989
00990 glTexCoord2f( 0.5, 0);
00991
00992 glVertex2f( v[0].x, v[0].y );
00993
00994
00995 glTexCoord2f( 0.5, 0);
00996
00997 glVertex2f( v[1].x, v[1].y );
00998
00999
01000 glTexCoord2f( 0.5, 1);
01001
01002 glVertex2f( v[2].x, v[2].y );
01003
01004
01005 glTexCoord2f( 0.5, 1);
01006
01007 glVertex2f( v[3].x, v[3].y );
01008 glEnd( );
01009
01010
01011 v[0].Set(0,0,0);
01012 v[1].Set(sw,0,0);
01013 v[2].Set(sw,-h,0);
01014 v[3].Set(0,-h,0);
01015
01016 glTranslated(w, 0, 0);
01017
01018
01019 glBegin( GL_QUADS );
01020
01021 glTexCoord2f( 0.5, 0);
01022
01023 glVertex2f( v[0].x, v[0].y );
01024
01025
01026 glTexCoord2f( 1, 0);
01027
01028 glVertex2f( v[1].x, v[1].y );
01029
01030
01031 glTexCoord2f( 1, 1);
01032
01033 glVertex2f( v[2].x, v[2].y );
01034
01035
01036 glTexCoord2f( 0.5, 1);
01037
01038 glVertex2f( v[3].x, v[3].y );
01039 glEnd( );
01040
01041
01042 glMatrixMode( GL_MODELVIEW );
01043
01044 glPopMatrix( );
01045
01046
01047 glMatrixMode( GL_PROJECTION );
01048
01049 glPopMatrix( );
01050
01051
01052 glEnable( GL_DEPTH_TEST );
01053
01054 glEnable( GL_LIGHTING);
01055 glDisable(GL_BLEND);
01056
01057 glPopAttrib();
01058 }
01059
01060 bool UTILITY::IntersectQuadrilateralF(VERTEX orig, VERTEX dir,
01061 VERTEX v_00, VERTEX v_10, VERTEX v_11, VERTEX v_01,
01062 float &t, float &u, float &v)
01063 {
01064
01065
01066 VERTEX E_01 = v_10 - v_00;
01067 VERTEX E_03 = v_01 - v_00;
01068 VERTEX P = dir.cross(E_03);
01069 float det = E_01.dot(P);
01070
01071 if (std::abs(det) < EPSILON) return false;
01072
01073 VERTEX T = orig - v_00;
01074 float alpha = T.dot(P) / det;
01075
01076 if (alpha < 0.0) return false;
01077
01078 VERTEX Q = T.cross(E_01);
01079 float beta = dir.dot(Q) / det;
01080
01081 if (beta < 0.0) return false;
01082
01083 if (alpha + beta > 1.0)
01084 {
01085
01086
01087 VERTEX E_23 = v_01 - v_11;
01088 VERTEX E_21 = v_10 - v_11;
01089 VERTEX P_prime = dir.cross(E_21);
01090 float det_prime = E_23.dot(P_prime);
01091
01092 if (std::abs(det_prime) < EPSILON) return false;
01093
01094 VERTEX T_prime = orig - v_11;
01095 float alpha_prime = T_prime.dot(P_prime) / det_prime;
01096
01097 if (alpha_prime < 0.0) return false;
01098
01099 VERTEX Q_prime = T_prime.cross(E_23);
01100 float beta_prime = dir.dot(Q_prime) / det_prime;
01101
01102 if (beta_prime < 0.0) return false;
01103 }
01104
01105
01106
01107 t = E_03.dot(Q) / det;
01108
01109 if (t < 0.0) return false;
01110
01111
01112
01113
01114 float alpha_11, beta_11;
01115 VERTEX E_02 = v_11 - v_00;
01116 VERTEX n = E_01.cross(E_03);
01117
01118 if ((std::abs(n.x) >= std::abs(n.y))
01119 && (std::abs(n.x) >= std::abs(n.z)))
01120 {
01121 alpha_11 = ((E_02.y * E_03.z) - (E_02.z * E_03.y)) / n.x;
01122 beta_11 = ((E_01.y * E_02.z) - (E_01.z * E_02.y)) / n.x;
01123 }
01124 else if ((std::abs(n.y) >= std::abs(n.x))
01125 && (std::abs(n.y) >= std::abs(n.z)))
01126 {
01127 alpha_11 = ((E_02.z * E_03.x) - (E_02.x * E_03.z)) / n.y;
01128 beta_11 = ((E_01.z * E_02.x) - (E_01.x * E_02.z)) / n.y;
01129 }
01130 else
01131 {
01132 alpha_11 = ((E_02.x * E_03.y) - (E_02.y * E_03.x)) / n.z;
01133 beta_11 = ((E_01.x * E_02.y) - (E_01.y * E_02.x)) / n.z;
01134 }
01135
01136
01137 if (std::abs(alpha_11 - (1.0)) < EPSILON)
01138 {
01139
01140 u = alpha;
01141 if (std::abs(beta_11 - (1.0)) < EPSILON) v = beta;
01142 else v = beta / ((u * (beta_11 - (1.0))) + (1.0));
01143 }
01144 else if (std::abs(beta_11 - (1.0)) < EPSILON)
01145 {
01146
01147 v = beta;
01148 u = alpha / ((v * (alpha_11 - (1.0))) + (1.0));
01149 }
01150 else
01151 {
01152 float A = (1.0) - beta_11;
01153 float B = (alpha * (beta_11 - (1.0)))
01154 - (beta * (alpha_11 - (1.0))) - (1.0);
01155 float C = alpha;
01156 float D = (B * B) - ((4.0) * A * C);
01157 if (D < 0) return false;
01158 float Q = (-0.5) * (B + ((B < (0.0) ? (-1.0) : (1.0))
01159 * std::sqrt(D)));
01160 u = Q / A;
01161 if ((u < (0.0)) || (u > (1.0))) u = C / Q;
01162 v = beta / ((u * (beta_11 - (1.0))) + (1.0));
01163 }
01164
01165 return true;
01166 }
01167
01168 bool UTILITY::IntersectQuadrilateralD(VERTEXD orig, VERTEXD dir,
01169 VERTEXD v_00, VERTEXD v_10, VERTEXD v_11, VERTEXD v_01,
01170 double &t, double &u, double &v)
01171 {
01172
01173
01174 VERTEXD E_01 = v_10 - v_00;
01175 VERTEXD E_03 = v_01 - v_00;
01176 VERTEXD P = dir.cross(E_03);
01177 double det = E_01.dot(P);
01178
01179 if (std::abs(det) < EPSILON) return false;
01180
01181 VERTEXD T = orig - v_00;
01182 double alpha = T.dot(P) / det;
01183
01184 if (alpha < 0.0) return false;
01185
01186 VERTEXD Q = T.cross(E_01);
01187 double beta = dir.dot(Q) / det;
01188
01189 if (beta < 0.0) return false;
01190
01191 if (alpha + beta > 1.0)
01192 {
01193
01194
01195 VERTEXD E_23 = v_01 - v_11;
01196 VERTEXD E_21 = v_10 - v_11;
01197 VERTEXD P_prime = dir.cross(E_21);
01198 double det_prime = E_23.dot(P_prime);
01199
01200 if (std::abs(det_prime) < EPSILON) return false;
01201
01202 VERTEXD T_prime = orig - v_11;
01203 double alpha_prime = T_prime.dot(P_prime) / det_prime;
01204
01205 if (alpha_prime < 0.0) return false;
01206
01207 VERTEXD Q_prime = T_prime.cross(E_23);
01208 double beta_prime = dir.dot(Q_prime) / det_prime;
01209
01210 if (beta_prime < 0.0) return false;
01211 }
01212
01213
01214
01215 t = E_03.dot(Q) / det;
01216
01217 if (t < 0.0) return false;
01218
01219
01220
01221
01222 double alpha_11, beta_11;
01223 VERTEXD E_02 = v_11 - v_00;
01224 VERTEXD n = E_01.cross(E_03);
01225
01226 if ((std::abs(n.x) >= std::abs(n.y))
01227 && (std::abs(n.x) >= std::abs(n.z)))
01228 {
01229 alpha_11 = ((E_02.y * E_03.z) - (E_02.z * E_03.y)) / n.x;
01230 beta_11 = ((E_01.y * E_02.z) - (E_01.z * E_02.y)) / n.x;
01231 }
01232 else if ((std::abs(n.y) >= std::abs(n.x))
01233 && (std::abs(n.y) >= std::abs(n.z)))
01234 {
01235 alpha_11 = ((E_02.z * E_03.x) - (E_02.x * E_03.z)) / n.y;
01236 beta_11 = ((E_01.z * E_02.x) - (E_01.x * E_02.z)) / n.y;
01237 }
01238 else
01239 {
01240 alpha_11 = ((E_02.x * E_03.y) - (E_02.y * E_03.x)) / n.z;
01241 beta_11 = ((E_01.x * E_02.y) - (E_01.y * E_02.x)) / n.z;
01242 }
01243
01244
01245 if (std::abs(alpha_11 - (1.0)) < EPSILON)
01246 {
01247
01248 u = alpha;
01249 if (std::abs(beta_11 - (1.0)) < EPSILON) v = beta;
01250 else v = beta / ((u * (beta_11 - (1.0))) + (1.0));
01251 }
01252 else if (std::abs(beta_11 - (1.0)) < EPSILON)
01253 {
01254
01255 v = beta;
01256 u = alpha / ((v * (alpha_11 - (1.0))) + (1.0));
01257 }
01258 else
01259 {
01260 double A = (1.0) - beta_11;
01261 double B = (alpha * (beta_11 - (1.0)))
01262 - (beta * (alpha_11 - (1.0))) - (1.0);
01263 double C = alpha;
01264 double D = (B * B) - ((4.0) * A * C);
01265 if (D < 0) return false;
01266 double Q = (-0.5) * (B + ((B < (0.0) ? (-1.0) : (1.0))
01267 * std::sqrt(D)));
01268 u = Q / A;
01269 if ((u < (0.0)) || (u > (1.0))) u = C / Q;
01270 v = beta / ((u * (beta_11 - (1.0))) + (1.0));
01271 }
01272
01273 return true;
01274 }
01275
01276
01277 #define CROSS(dest,v1,v2) \
01278 dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
01279 dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
01280 dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
01281
01282 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
01283
01284 #define SUB(dest,v1,v2) dest[0]=v1[0]-v2[0]; dest[1]=v1[1]-v2[1]; dest[2]=v1[2]-v2[2];
01285
01286 #define ADD(dest,v1,v2) dest[0]=v1[0]+v2[0]; dest[1]=v1[1]+v2[1]; dest[2]=v1[2]+v2[2];
01287
01288 #define MULT(dest,v,factor) dest[0]=factor*v[0]; dest[1]=factor*v[1]; dest[2]=factor*v[2];
01289
01290 #define SET(dest,src) dest[0]=src[0]; dest[1]=src[1]; dest[2]=src[2];
01291
01292
01293 #define SORT(a,b) \
01294 if(a>b) \
01295 { \
01296 float c; \
01297 c=a; \
01298 a=b; \
01299 b=c; \
01300 }
01301
01302
01303 #define SORT2(a,b,smallest) \
01304 if(a>b) \
01305 { \
01306 float c; \
01307 c=a; \
01308 a=b; \
01309 b=c; \
01310 smallest=1; \
01311 } \
01312 else smallest=0;
01313
01314 #define ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1) \
01315 isect0=VV0+(VV1-VV0)*D0/(D0-D1); \
01316 isect1=VV0+(VV2-VV0)*D0/(D0-D2);
01317
01318
01319 #define COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1) \
01320 if(D0D1>0.0f) \
01321