drawstuff.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639
  1. /*************************************************************************
  2. * *
  3. * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
  4. * All rights reserved. Email: [email protected] Web: www.q12.org *
  5. * *
  6. * This library is free software; you can redistribute it and/or *
  7. * modify it under the terms of EITHER: *
  8. * (1) The GNU Lesser General Public License as published by the Free *
  9. * Software Foundation; either version 2.1 of the License, or (at *
  10. * your option) any later version. The text of the GNU Lesser *
  11. * General Public License is included with this library in the *
  12. * file LICENSE.TXT. *
  13. * (2) The BSD-style license that is included with this library in *
  14. * the file LICENSE-BSD.TXT. *
  15. * *
  16. * This library is distributed in the hope that it will be useful, *
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
  19. * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
  20. * *
  21. *************************************************************************/
  22. /*
  23. simple graphics.
  24. the following command line flags can be used (typically under unix)
  25. -notex Do not use any textures
  26. -noshadow[s] Do not draw any shadows
  27. -pause Start the simulation paused
  28. -texturepath <path> Inform an alternative textures path
  29. TODO
  30. ----
  31. manage openGL state changes better
  32. */
  33. #ifdef WIN32
  34. #include <windows.h>
  35. #endif
  36. #include <ode/ode.h>
  37. #include "config.h"
  38. #ifdef HAVE_APPLE_OPENGL_FRAMEWORK
  39. #include <OpenGL/gl.h>
  40. #include <OpenGL/glu.h>
  41. #else
  42. #include <GL/gl.h>
  43. #include <GL/glu.h>
  44. #endif
  45. #include "drawstuff/drawstuff.h"
  46. #include "internal.h"
  47. //***************************************************************************
  48. // misc
  49. #ifndef DEFAULT_PATH_TO_TEXTURES
  50. #if 0
  51. #define DEFAULT_PATH_TO_TEXTURES "..\\textures\\"
  52. #else
  53. #define DEFAULT_PATH_TO_TEXTURES "../textures/"
  54. #endif
  55. #endif
  56. #ifndef M_PI
  57. #define M_PI (3.14159265358979323846)
  58. #endif
  59. // constants to convert degrees to radians and the reverse
  60. #define RAD_TO_DEG (180.0/M_PI)
  61. #define DEG_TO_RAD (M_PI/180.0)
  62. // light vector. LIGHTZ is implicitly 1
  63. #define LIGHTX (1.0f)
  64. #define LIGHTY (0.4f)
  65. // ground and sky
  66. #define SHADOW_INTENSITY (0.65f)
  67. #define GROUND_R (0.5f) // ground color for when there's no texture
  68. #define GROUND_G (0.5f)
  69. #define GROUND_B (0.3f)
  70. const float ground_scale = 1.0f/1.0f; // ground texture scale (1/size)
  71. const float ground_ofsx = 0.5; // offset of ground texture
  72. const float ground_ofsy = 0.5;
  73. const float sky_scale = 1.0f/4.0f; // sky texture scale (1/size)
  74. const float sky_height = 1.0f; // sky height above viewpoint
  75. //***************************************************************************
  76. // misc mathematics stuff
  77. static void normalizeVector3 (float v[3])
  78. {
  79. float len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  80. if (len <= 0.0f) {
  81. v[0] = 1;
  82. v[1] = 0;
  83. v[2] = 0;
  84. }
  85. else {
  86. len = 1.0f / (float)sqrt(len);
  87. v[0] *= len;
  88. v[1] *= len;
  89. v[2] *= len;
  90. }
  91. }
  92. static void crossProduct3(float res[3], const float a[3], const float b[3])
  93. {
  94. float res_0 = a[1]*b[2] - a[2]*b[1];
  95. float res_1 = a[2]*b[0] - a[0]*b[2];
  96. float res_2 = a[0]*b[1] - a[1]*b[0];
  97. // Only assign after all the calculations are over to avoid incurring memory aliasing
  98. res[0] = res_0;
  99. res[1] = res_1;
  100. res[2] = res_2;
  101. }
  102. //***************************************************************************
  103. // PPM image object
  104. typedef unsigned char byte;
  105. class Image {
  106. int image_width,image_height;
  107. byte *image_data;
  108. public:
  109. Image (char *filename);
  110. // load from PPM file
  111. ~Image();
  112. int width() { return image_width; }
  113. int height() { return image_height; }
  114. byte *data() { return image_data; }
  115. };
  116. // skip over whitespace and comments in a stream.
  117. static void skipWhiteSpace (char *filename, FILE *f)
  118. {
  119. int c,d;
  120. for(;;) {
  121. c = fgetc(f);
  122. if (c==EOF) dsError ("unexpected end of file in \"%s\"",filename);
  123. // skip comments
  124. if (c == '#') {
  125. do {
  126. d = fgetc(f);
  127. if (d==EOF) dsError ("unexpected end of file in \"%s\"",filename);
  128. } while (d != '\n');
  129. continue;
  130. }
  131. if (c > ' ') {
  132. ungetc (c,f);
  133. return;
  134. }
  135. }
  136. }
  137. // read a number from a stream, this return 0 if there is none (that's okay
  138. // because 0 is a bad value for all PPM numbers anyway).
  139. static int readNumber (char *filename, FILE *f)
  140. {
  141. int c,n=0;
  142. for(;;) {
  143. c = fgetc(f);
  144. if (c==EOF) dsError ("unexpected end of file in \"%s\"",filename);
  145. if (c >= '0' && c <= '9') n = n*10 + (c - '0');
  146. else {
  147. ungetc (c,f);
  148. return n;
  149. }
  150. }
  151. }
  152. Image::Image (char *filename)
  153. {
  154. FILE *f = fopen (filename,"rb");
  155. if (!f) dsError ("Can't open image file `%s'",filename);
  156. // read in header
  157. if (fgetc(f) != 'P' || fgetc(f) != '6')
  158. dsError ("image file \"%s\" is not a binary PPM (no P6 header)",filename);
  159. skipWhiteSpace (filename,f);
  160. // read in image parameters
  161. image_width = readNumber (filename,f);
  162. skipWhiteSpace (filename,f);
  163. image_height = readNumber (filename,f);
  164. skipWhiteSpace (filename,f);
  165. int max_value = readNumber (filename,f);
  166. // check values
  167. if (image_width < 1 || image_height < 1)
  168. dsError ("bad image file \"%s\"",filename);
  169. if (max_value != 255)
  170. dsError ("image file \"%s\" must have color range of 255",filename);
  171. // read either nothing, LF (10), or CR,LF (13,10)
  172. int c = fgetc(f);
  173. if (c == 10) {
  174. // LF
  175. }
  176. else if (c == 13) {
  177. // CR
  178. c = fgetc(f);
  179. if (c != 10) ungetc (c,f);
  180. }
  181. else ungetc (c,f);
  182. // read in rest of data
  183. image_data = new byte [image_width*image_height*3];
  184. if (fread (image_data,image_width*image_height*3,1,f) != 1)
  185. dsError ("Can not read data from image file `%s'",filename);
  186. fclose (f);
  187. }
  188. Image::~Image()
  189. {
  190. delete[] image_data;
  191. }
  192. //***************************************************************************
  193. // Texture object.
  194. class Texture {
  195. Image *image;
  196. GLuint name;
  197. public:
  198. Texture (char *filename);
  199. ~Texture();
  200. void bind (int modulate);
  201. };
  202. Texture::Texture (char *filename)
  203. {
  204. image = new Image (filename);
  205. glGenTextures (1,&name);
  206. glBindTexture (GL_TEXTURE_2D,name);
  207. // set pixel unpacking mode
  208. glPixelStorei (GL_UNPACK_SWAP_BYTES, 0);
  209. glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
  210. glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  211. glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
  212. glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
  213. // glTexImage2D (GL_TEXTURE_2D, 0, 3, image->width(), image->height(), 0,
  214. // GL_RGB, GL_UNSIGNED_BYTE, image->data());
  215. gluBuild2DMipmaps (GL_TEXTURE_2D, 3, image->width(), image->height(),
  216. GL_RGB, GL_UNSIGNED_BYTE, image->data());
  217. // set texture parameters - will these also be bound to the texture???
  218. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  219. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  220. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  221. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  222. GL_LINEAR_MIPMAP_LINEAR);
  223. glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  224. }
  225. Texture::~Texture()
  226. {
  227. delete image;
  228. glDeleteTextures (1,&name);
  229. }
  230. void Texture::bind (int modulate)
  231. {
  232. glBindTexture (GL_TEXTURE_2D,name);
  233. glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
  234. modulate ? GL_MODULATE : GL_DECAL);
  235. }
  236. //***************************************************************************
  237. // the current drawing state (for when the user's step function is drawing)
  238. static float color[4] = {0,0,0,0}; // current r,g,b,alpha color
  239. static int tnum = 0; // current texture number
  240. //***************************************************************************
  241. // OpenGL utility stuff
  242. static void setCamera (float x, float y, float z, float h, float p, float r)
  243. {
  244. glMatrixMode (GL_MODELVIEW);
  245. glLoadIdentity();
  246. glRotatef (90, 0,0,1);
  247. glRotatef (90, 0,1,0);
  248. glRotatef (r, 1,0,0);
  249. glRotatef (p, 0,1,0);
  250. glRotatef (-h, 0,0,1);
  251. glTranslatef (-x,-y,-z);
  252. }
  253. // sets the material color, not the light color
  254. static void setColor (float r, float g, float b, float alpha)
  255. {
  256. GLfloat light_ambient[4],light_diffuse[4],light_specular[4];
  257. light_ambient[0] = r*0.3f;
  258. light_ambient[1] = g*0.3f;
  259. light_ambient[2] = b*0.3f;
  260. light_ambient[3] = alpha;
  261. light_diffuse[0] = r*0.7f;
  262. light_diffuse[1] = g*0.7f;
  263. light_diffuse[2] = b*0.7f;
  264. light_diffuse[3] = alpha;
  265. light_specular[0] = r*0.2f;
  266. light_specular[1] = g*0.2f;
  267. light_specular[2] = b*0.2f;
  268. light_specular[3] = alpha;
  269. glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, light_ambient);
  270. glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, light_diffuse);
  271. glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, light_specular);
  272. glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 5.0f);
  273. }
  274. static void setTransform (const float pos[3], const float R[12])
  275. {
  276. GLfloat matrix[16];
  277. matrix[0]=R[0];
  278. matrix[1]=R[4];
  279. matrix[2]=R[8];
  280. matrix[3]=0;
  281. matrix[4]=R[1];
  282. matrix[5]=R[5];
  283. matrix[6]=R[9];
  284. matrix[7]=0;
  285. matrix[8]=R[2];
  286. matrix[9]=R[6];
  287. matrix[10]=R[10];
  288. matrix[11]=0;
  289. matrix[12]=pos[0];
  290. matrix[13]=pos[1];
  291. matrix[14]=pos[2];
  292. matrix[15]=1;
  293. glPushMatrix();
  294. glMultMatrixf (matrix);
  295. }
  296. static void setTransformD (const double pos[3], const double R[12])
  297. {
  298. GLdouble matrix[16];
  299. matrix[0]=R[0];
  300. matrix[1]=R[4];
  301. matrix[2]=R[8];
  302. matrix[3]=0;
  303. matrix[4]=R[1];
  304. matrix[5]=R[5];
  305. matrix[6]=R[9];
  306. matrix[7]=0;
  307. matrix[8]=R[2];
  308. matrix[9]=R[6];
  309. matrix[10]=R[10];
  310. matrix[11]=0;
  311. matrix[12]=pos[0];
  312. matrix[13]=pos[1];
  313. matrix[14]=pos[2];
  314. matrix[15]=1;
  315. glPushMatrix();
  316. glMultMatrixd (matrix);
  317. }
  318. // set shadow projection transform
  319. static void setShadowTransform()
  320. {
  321. GLfloat matrix[16];
  322. for (int i=0; i<16; i++) matrix[i] = 0;
  323. matrix[0]=1;
  324. matrix[5]=1;
  325. matrix[8]=-LIGHTX;
  326. matrix[9]=-LIGHTY;
  327. matrix[15]=1;
  328. glPushMatrix();
  329. glMultMatrixf (matrix);
  330. }
  331. static void drawConvex (const float *_planes, unsigned int _planecount,
  332. const float *_points, unsigned int /*_pointcount*/,
  333. const unsigned int *_polygons)
  334. {
  335. unsigned int polyindex=0;
  336. for(unsigned int i=0;i<_planecount;++i)
  337. {
  338. unsigned int pointcount=_polygons[polyindex];
  339. polyindex++;
  340. glBegin (GL_POLYGON);
  341. glNormal3f(_planes[(i*4)+0],
  342. _planes[(i*4)+1],
  343. _planes[(i*4)+2]);
  344. for(unsigned int j=0;j<pointcount;++j)
  345. {
  346. glVertex3f(_points[_polygons[polyindex]*3],
  347. _points[(_polygons[polyindex]*3)+1],
  348. _points[(_polygons[polyindex]*3)+2]);
  349. polyindex++;
  350. }
  351. glEnd();
  352. }
  353. }
  354. static void drawConvexD (const double *_planes, unsigned int _planecount,
  355. const double *_points, unsigned int /*_pointcount*/,
  356. const unsigned int *_polygons)
  357. {
  358. unsigned int polyindex=0;
  359. for(unsigned int i=0;i<_planecount;++i)
  360. {
  361. unsigned int pointcount=_polygons[polyindex];
  362. polyindex++;
  363. glBegin (GL_POLYGON);
  364. glNormal3d(_planes[(i*4)+0],
  365. _planes[(i*4)+1],
  366. _planes[(i*4)+2]);
  367. for(unsigned int j=0;j<pointcount;++j)
  368. {
  369. glVertex3d(_points[_polygons[polyindex]*3],
  370. _points[(_polygons[polyindex]*3)+1],
  371. _points[(_polygons[polyindex]*3)+2]);
  372. polyindex++;
  373. }
  374. glEnd();
  375. }
  376. }
  377. static void drawBox (const float sides[3])
  378. {
  379. float lx = sides[0]*0.5f;
  380. float ly = sides[1]*0.5f;
  381. float lz = sides[2]*0.5f;
  382. // sides
  383. glBegin (GL_TRIANGLE_STRIP);
  384. glNormal3f (-1,0,0);
  385. glVertex3f (-lx,-ly,-lz);
  386. glVertex3f (-lx,-ly,lz);
  387. glVertex3f (-lx,ly,-lz);
  388. glVertex3f (-lx,ly,lz);
  389. glNormal3f (0,1,0);
  390. glVertex3f (lx,ly,-lz);
  391. glVertex3f (lx,ly,lz);
  392. glNormal3f (1,0,0);
  393. glVertex3f (lx,-ly,-lz);
  394. glVertex3f (lx,-ly,lz);
  395. glNormal3f (0,-1,0);
  396. glVertex3f (-lx,-ly,-lz);
  397. glVertex3f (-lx,-ly,lz);
  398. glEnd();
  399. // top face
  400. glBegin (GL_TRIANGLE_FAN);
  401. glNormal3f (0,0,1);
  402. glVertex3f (-lx,-ly,lz);
  403. glVertex3f (lx,-ly,lz);
  404. glVertex3f (lx,ly,lz);
  405. glVertex3f (-lx,ly,lz);
  406. glEnd();
  407. // bottom face
  408. glBegin (GL_TRIANGLE_FAN);
  409. glNormal3f (0,0,-1);
  410. glVertex3f (-lx,-ly,-lz);
  411. glVertex3f (-lx,ly,-lz);
  412. glVertex3f (lx,ly,-lz);
  413. glVertex3f (lx,-ly,-lz);
  414. glEnd();
  415. }
  416. // This is recursively subdivides a triangular area (vertices p1,p2,p3) into
  417. // smaller triangles, and then draws the triangles. All triangle vertices are
  418. // normalized to a distance of 1.0 from the origin (p1,p2,p3 are assumed
  419. // to be already normalized). Note this is not super-fast because it draws
  420. // triangles rather than triangle strips.
  421. static void drawPatch (float p1[3], float p2[3], float p3[3], int level)
  422. {
  423. int i;
  424. if (level > 0) {
  425. float q1[3],q2[3],q3[3]; // sub-vertices
  426. for (i=0; i<3; i++) {
  427. q1[i] = 0.5f*(p1[i]+p2[i]);
  428. q2[i] = 0.5f*(p2[i]+p3[i]);
  429. q3[i] = 0.5f*(p3[i]+p1[i]);
  430. }
  431. float length1 = (float)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2]));
  432. float length2 = (float)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2]));
  433. float length3 = (float)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2]));
  434. for (i=0; i<3; i++) {
  435. q1[i] *= length1;
  436. q2[i] *= length2;
  437. q3[i] *= length3;
  438. }
  439. drawPatch (p1,q1,q3,level-1);
  440. drawPatch (q1,p2,q2,level-1);
  441. drawPatch (q1,q2,q3,level-1);
  442. drawPatch (q3,q2,p3,level-1);
  443. }
  444. else {
  445. glNormal3f (p1[0],p1[1],p1[2]);
  446. glVertex3f (p1[0],p1[1],p1[2]);
  447. glNormal3f (p2[0],p2[1],p2[2]);
  448. glVertex3f (p2[0],p2[1],p2[2]);
  449. glNormal3f (p3[0],p3[1],p3[2]);
  450. glVertex3f (p3[0],p3[1],p3[2]);
  451. }
  452. }
  453. // draw a sphere of radius 1
  454. static int sphere_quality = 1;
  455. static void drawSphere()
  456. {
  457. // icosahedron data for an icosahedron of radius 1.0
  458. # define ICX 0.525731112119133606f
  459. # define ICZ 0.850650808352039932f
  460. static GLfloat idata[12][3] = {
  461. {-ICX, 0, ICZ},
  462. {ICX, 0, ICZ},
  463. {-ICX, 0, -ICZ},
  464. {ICX, 0, -ICZ},
  465. {0, ICZ, ICX},
  466. {0, ICZ, -ICX},
  467. {0, -ICZ, ICX},
  468. {0, -ICZ, -ICX},
  469. {ICZ, ICX, 0},
  470. {-ICZ, ICX, 0},
  471. {ICZ, -ICX, 0},
  472. {-ICZ, -ICX, 0}
  473. };
  474. static int index[20][3] = {
  475. {0, 4, 1}, {0, 9, 4},
  476. {9, 5, 4}, {4, 5, 8},
  477. {4, 8, 1}, {8, 10, 1},
  478. {8, 3, 10}, {5, 3, 8},
  479. {5, 2, 3}, {2, 7, 3},
  480. {7, 10, 3}, {7, 6, 10},
  481. {7, 11, 6}, {11, 0, 6},
  482. {0, 1, 6}, {6, 1, 10},
  483. {9, 0, 11}, {9, 11, 2},
  484. {9, 2, 5}, {7, 2, 11},
  485. };
  486. static GLuint listnum = 0;
  487. if (listnum==0) {
  488. listnum = glGenLists (1);
  489. glNewList (listnum,GL_COMPILE);
  490. glBegin (GL_TRIANGLES);
  491. for (int i=0; i<20; i++) {
  492. drawPatch (&idata[index[i][2]][0],&idata[index[i][1]][0],
  493. &idata[index[i][0]][0],sphere_quality);
  494. }
  495. glEnd();
  496. glEndList();
  497. }
  498. glCallList (listnum);
  499. }
  500. static void drawSphereShadow (float px, float py, float pz, float radius)
  501. {
  502. // calculate shadow constants based on light vector
  503. static int init=0;
  504. static float len2,len1,scale;
  505. if (!init) {
  506. len2 = LIGHTX*LIGHTX + LIGHTY*LIGHTY;
  507. len1 = 1.0f/(float)sqrt(len2);
  508. scale = (float) sqrt(len2 + 1);
  509. init = 1;
  510. }
  511. // map sphere center to ground plane based on light vector
  512. px -= LIGHTX*pz;
  513. py -= LIGHTY*pz;
  514. const float kx = 0.96592582628907f;
  515. const float ky = 0.25881904510252f;
  516. float x=radius, y=0;
  517. glBegin (GL_TRIANGLE_FAN);
  518. for (int i=0; i<24; i++) {
  519. // for all points on circle, scale to elongated rotated shadow and draw
  520. float x2 = (LIGHTX*x*scale - LIGHTY*y)*len1 + px;
  521. float y2 = (LIGHTY*x*scale + LIGHTX*y)*len1 + py;
  522. glTexCoord2f (x2*ground_scale+ground_ofsx,y2*ground_scale+ground_ofsy);
  523. glVertex3f (x2,y2,0);
  524. // rotate [x,y] vector
  525. float xtmp = kx*x - ky*y;
  526. y = ky*x + kx*y;
  527. x = xtmp;
  528. }
  529. glEnd();
  530. }
  531. static void drawTriangle (const float *v0, const float *v1, const float *v2, int solid)
  532. {
  533. float u[3],v[3],normal[3];
  534. u[0] = v1[0] - v0[0];
  535. u[1] = v1[1] - v0[1];
  536. u[2] = v1[2] - v0[2];
  537. v[0] = v2[0] - v0[0];
  538. v[1] = v2[1] - v0[1];
  539. v[2] = v2[2] - v0[2];
  540. crossProduct3(normal,u,v);
  541. normalizeVector3 (normal);
  542. glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
  543. glNormal3fv (normal);
  544. glVertex3fv (v0);
  545. glVertex3fv (v1);
  546. glVertex3fv (v2);
  547. glEnd();
  548. }
  549. static void drawTriangleD (const double *v0, const double *v1, const double *v2, int solid)
  550. {
  551. float u[3],v[3],normal[3];
  552. u[0] = float( v1[0] - v0[0] );
  553. u[1] = float( v1[1] - v0[1] );
  554. u[2] = float( v1[2] - v0[2] );
  555. v[0] = float( v2[0] - v0[0] );
  556. v[1] = float( v2[1] - v0[1] );
  557. v[2] = float( v2[2] - v0[2] );
  558. crossProduct3(normal,u,v);
  559. normalizeVector3 (normal);
  560. glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
  561. glNormal3fv (normal);
  562. glVertex3dv (v0);
  563. glVertex3dv (v1);
  564. glVertex3dv (v2);
  565. glEnd();
  566. }
  567. // draw a capped cylinder of length l and radius r, aligned along the x axis
  568. static int capped_cylinder_quality = 3;
  569. static void drawCapsule (float l, float r)
  570. {
  571. int i,j;
  572. float tmp,nx,ny,nz,start_nx,start_ny,a,ca,sa;
  573. // number of sides to the cylinder (divisible by 4):
  574. const int n = capped_cylinder_quality*4;
  575. l *= 0.5;
  576. a = float(M_PI*2.0)/float(n);
  577. sa = (float) sin(a);
  578. ca = (float) cos(a);
  579. // draw cylinder body
  580. ny=1; nz=0; // normal vector = (0,ny,nz)
  581. glBegin (GL_TRIANGLE_STRIP);
  582. for (i=0; i<=n; i++) {
  583. glNormal3d (ny,nz,0);
  584. glVertex3d (ny*r,nz*r,l);
  585. glNormal3d (ny,nz,0);
  586. glVertex3d (ny*r,nz*r,-l);
  587. // rotate ny,nz
  588. tmp = ca*ny - sa*nz;
  589. nz = sa*ny + ca*nz;
  590. ny = tmp;
  591. }
  592. glEnd();
  593. // draw first cylinder cap
  594. start_nx = 0;
  595. start_ny = 1;
  596. for (j=0; j<(n/4); j++) {
  597. // get start_n2 = rotated start_n
  598. float start_nx2 = ca*start_nx + sa*start_ny;
  599. float start_ny2 = -sa*start_nx + ca*start_ny;
  600. // get n=start_n and n2=start_n2
  601. nx = start_nx; ny = start_ny; nz = 0;
  602. float nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
  603. glBegin (GL_TRIANGLE_STRIP);
  604. for (i=0; i<=n; i++) {
  605. glNormal3d (ny2,nz2,nx2);
  606. glVertex3d (ny2*r,nz2*r,l+nx2*r);
  607. glNormal3d (ny,nz,nx);
  608. glVertex3d (ny*r,nz*r,l+nx*r);
  609. // rotate n,n2
  610. tmp = ca*ny - sa*nz;
  611. nz = sa*ny + ca*nz;
  612. ny = tmp;
  613. tmp = ca*ny2- sa*nz2;
  614. nz2 = sa*ny2 + ca*nz2;
  615. ny2 = tmp;
  616. }
  617. glEnd();
  618. start_nx = start_nx2;
  619. start_ny = start_ny2;
  620. }
  621. // draw second cylinder cap
  622. start_nx = 0;
  623. start_ny = 1;
  624. for (j=0; j<(n/4); j++) {
  625. // get start_n2 = rotated start_n
  626. float start_nx2 = ca*start_nx - sa*start_ny;
  627. float start_ny2 = sa*start_nx + ca*start_ny;
  628. // get n=start_n and n2=start_n2
  629. nx = start_nx; ny = start_ny; nz = 0;
  630. float nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
  631. glBegin (GL_TRIANGLE_STRIP);
  632. for (i=0; i<=n; i++) {
  633. glNormal3d (ny,nz,nx);
  634. glVertex3d (ny*r,nz*r,-l+nx*r);
  635. glNormal3d (ny2,nz2,nx2);
  636. glVertex3d (ny2*r,nz2*r,-l+nx2*r);
  637. // rotate n,n2
  638. tmp = ca*ny - sa*nz;
  639. nz = sa*ny + ca*nz;
  640. ny = tmp;
  641. tmp = ca*ny2- sa*nz2;
  642. nz2 = sa*ny2 + ca*nz2;
  643. ny2 = tmp;
  644. }
  645. glEnd();
  646. start_nx = start_nx2;
  647. start_ny = start_ny2;
  648. }
  649. }
  650. // draw a cylinder of length l and radius r, aligned along the z axis
  651. static void drawCylinder (float l, float r, float zoffset)
  652. {
  653. int i;
  654. float tmp,ny,nz,a,ca,sa;
  655. const int n = 24; // number of sides to the cylinder (divisible by 4)
  656. l *= 0.5;
  657. a = float(M_PI*2.0)/float(n);
  658. sa = (float) sin(a);
  659. ca = (float) cos(a);
  660. // draw cylinder body
  661. ny=1; nz=0; // normal vector = (0,ny,nz)
  662. glBegin (GL_TRIANGLE_STRIP);
  663. for (i=0; i<=n; i++) {
  664. glNormal3d (ny,nz,0);
  665. glVertex3d (ny*r,nz*r,l+zoffset);
  666. glNormal3d (ny,nz,0);
  667. glVertex3d (ny*r,nz*r,-l+zoffset);
  668. // rotate ny,nz
  669. tmp = ca*ny - sa*nz;
  670. nz = sa*ny + ca*nz;
  671. ny = tmp;
  672. }
  673. glEnd();
  674. // draw top cap
  675. glShadeModel (GL_FLAT);
  676. ny=1; nz=0; // normal vector = (0,ny,nz)
  677. glBegin (GL_TRIANGLE_FAN);
  678. glNormal3d (0,0,1);
  679. glVertex3d (0,0,l+zoffset);
  680. for (i=0; i<=n; i++) {
  681. if (i==1 || i==n/2+1)
  682. setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
  683. glNormal3d (0,0,1);
  684. glVertex3d (ny*r,nz*r,l+zoffset);
  685. if (i==1 || i==n/2+1)
  686. setColor (color[0],color[1],color[2],color[3]);
  687. // rotate ny,nz
  688. tmp = ca*ny - sa*nz;
  689. nz = sa*ny + ca*nz;
  690. ny = tmp;
  691. }
  692. glEnd();
  693. // draw bottom cap
  694. ny=1; nz=0; // normal vector = (0,ny,nz)
  695. glBegin (GL_TRIANGLE_FAN);
  696. glNormal3d (0,0,-1);
  697. glVertex3d (0,0,-l+zoffset);
  698. for (i=0; i<=n; i++) {
  699. if (i==1 || i==n/2+1)
  700. setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
  701. glNormal3d (0,0,-1);
  702. glVertex3d (ny*r,nz*r,-l+zoffset);
  703. if (i==1 || i==n/2+1)
  704. setColor (color[0],color[1],color[2],color[3]);
  705. // rotate ny,nz
  706. tmp = ca*ny + sa*nz;
  707. nz = -sa*ny + ca*nz;
  708. ny = tmp;
  709. }
  710. glEnd();
  711. }
  712. //***************************************************************************
  713. // motion model
  714. // current camera position and orientation
  715. static float view_xyz[3]; // position x,y,z
  716. static float view_hpr[3]; // heading, pitch, roll (degrees)
  717. // initialize the above variables
  718. static void initMotionModel()
  719. {
  720. view_xyz[0] = 2;
  721. view_xyz[1] = 0;
  722. view_xyz[2] = 1;
  723. view_hpr[0] = 180;
  724. view_hpr[1] = 0;
  725. view_hpr[2] = 0;
  726. }
  727. static void wrapCameraAngles()
  728. {
  729. for (int i=0; i<3; i++) {
  730. while (view_hpr[i] > 180) view_hpr[i] -= 360;
  731. while (view_hpr[i] < -180) view_hpr[i] += 360;
  732. }
  733. }
  734. // call this to update the current camera position. the bits in `mode' say
  735. // if the left (1), middle (2) or right (4) mouse button is pressed, and
  736. // (deltax,deltay) is the amount by which the mouse pointer has moved.
  737. void dsMotion (int mode, int deltax, int deltay)
  738. {
  739. float side = 0.01f * float(deltax);
  740. float fwd = (mode==4) ? (0.01f * float(deltay)) : 0.0f;
  741. float s = (float) sin (view_hpr[0]*DEG_TO_RAD);
  742. float c = (float) cos (view_hpr[0]*DEG_TO_RAD);
  743. if (mode==1) {
  744. view_hpr[0] += float (deltax) * 0.5f;
  745. view_hpr[1] += float (deltay) * 0.5f;
  746. }
  747. else {
  748. view_xyz[0] += -s*side + c*fwd;
  749. view_xyz[1] += c*side + s*fwd;
  750. if (mode==2 || mode==5) view_xyz[2] += 0.01f * float(deltay);
  751. }
  752. wrapCameraAngles();
  753. }
  754. //***************************************************************************
  755. // drawing loop stuff
  756. // the current state:
  757. // 0 = uninitialized
  758. // 1 = dsSimulationLoop() called
  759. // 2 = dsDrawFrame() called
  760. static int current_state = 0;
  761. // textures and shadows
  762. static int use_textures=1; // 1 if textures to be drawn
  763. static int use_shadows=1; // 1 if shadows to be drawn
  764. static Texture *sky_texture = 0;
  765. static Texture *ground_texture = 0;
  766. static Texture *wood_texture = 0;
  767. static Texture *checkered_texture = 0;
  768. static Texture *texture[4+1]; // +1 since index 0 is not used
  769. #if !defined(macintosh) || defined(ODE_PLATFORM_OSX)
  770. void dsStartGraphics (int /*width*/, int /*height*/, dsFunctions *fn)
  771. {
  772. const char *prefix = DEFAULT_PATH_TO_TEXTURES;
  773. if (fn->version >= 2 && fn->path_to_textures) prefix = fn->path_to_textures;
  774. char *s = (char*) alloca (strlen(prefix) + 20);
  775. strcpy (s,prefix);
  776. strcat (s,"/sky.ppm");
  777. texture[DS_SKY] = sky_texture = new Texture (s);
  778. strcpy (s,prefix);
  779. strcat (s,"/ground.ppm");
  780. texture[DS_GROUND] = ground_texture = new Texture (s);
  781. strcpy (s,prefix);
  782. strcat (s,"/wood.ppm");
  783. texture[DS_WOOD] = wood_texture = new Texture (s);
  784. strcpy (s,prefix);
  785. strcat (s,"/checkered.ppm");
  786. texture[DS_CHECKERED] = checkered_texture = new Texture (s);
  787. }
  788. #else // macintosh
  789. void dsStartGraphics (int width, int height, dsFunctions *fn)
  790. {
  791. // All examples build into the same dir
  792. char *prefix = "::::drawstuff:textures";
  793. char *s = (char*) alloca (strlen(prefix) + 20);
  794. strcpy (s,prefix);
  795. strcat (s,":sky.ppm");
  796. sky_texture = new Texture (s);
  797. strcpy (s,prefix);
  798. strcat (s,":ground.ppm");
  799. ground_texture = new Texture (s);
  800. strcpy (s,prefix);
  801. strcat (s,":wood.ppm");
  802. wood_texture = new Texture (s);
  803. }
  804. #endif
  805. void dsStopGraphics()
  806. {
  807. delete sky_texture;
  808. delete ground_texture;
  809. delete wood_texture;
  810. sky_texture = 0;
  811. ground_texture = 0;
  812. wood_texture = 0;
  813. }
  814. static void drawSky (float view_xyz[3])
  815. {
  816. glDisable (GL_LIGHTING);
  817. if (use_textures) {
  818. glEnable (GL_TEXTURE_2D);
  819. sky_texture->bind (0);
  820. }
  821. else {
  822. glDisable (GL_TEXTURE_2D);
  823. glColor3f (0,0.5,1.0);
  824. }
  825. // make sure sky depth is as far back as possible
  826. glShadeModel (GL_FLAT);
  827. glEnable (GL_DEPTH_TEST);
  828. glDepthFunc (GL_LEQUAL);
  829. glDepthRange (1,1);
  830. const float ssize = 1000.0f;
  831. static float offset = 0.0f;
  832. float x = ssize*sky_scale;
  833. float z = view_xyz[2] + sky_height;
  834. glBegin (GL_QUADS);
  835. glNormal3f (0,0,-1);
  836. glTexCoord2f (-x+offset,-x+offset);
  837. glVertex3f (-ssize+view_xyz[0],-ssize+view_xyz[1],z);
  838. glTexCoord2f (-x+offset,x+offset);
  839. glVertex3f (-ssize+view_xyz[0],ssize+view_xyz[1],z);
  840. glTexCoord2f (x+offset,x+offset);
  841. glVertex3f (ssize+view_xyz[0],ssize+view_xyz[1],z);
  842. glTexCoord2f (x+offset,-x+offset);
  843. glVertex3f (ssize+view_xyz[0],-ssize+view_xyz[1],z);
  844. glEnd();
  845. offset = offset + 0.002f;
  846. if (offset > 1) offset -= 1;
  847. glDepthFunc (GL_LESS);
  848. glDepthRange (0,1);
  849. }
  850. static void drawGround()
  851. {
  852. glDisable (GL_LIGHTING);
  853. glShadeModel (GL_FLAT);
  854. glEnable (GL_DEPTH_TEST);
  855. glDepthFunc (GL_LESS);
  856. // glDepthRange (1,1);
  857. if (use_textures) {
  858. glEnable (GL_TEXTURE_2D);
  859. ground_texture->bind (0);
  860. }
  861. else {
  862. glDisable (GL_TEXTURE_2D);
  863. glColor3f (GROUND_R,GROUND_G,GROUND_B);
  864. }
  865. // ground fog seems to cause problems with TNT2 under windows
  866. /*
  867. GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1};
  868. glEnable (GL_FOG);
  869. glFogi (GL_FOG_MODE, GL_EXP2);
  870. glFogfv (GL_FOG_COLOR, fogColor);
  871. glFogf (GL_FOG_DENSITY, 0.05f);
  872. glHint (GL_FOG_HINT, GL_NICEST); // GL_DONT_CARE);
  873. glFogf (GL_FOG_START, 1.0);
  874. glFogf (GL_FOG_END, 5.0);
  875. */
  876. const float gsize = 100.0f;
  877. const float offset = 0; // -0.001f; ... polygon offsetting doesn't work well
  878. glBegin (GL_QUADS);
  879. glNormal3f (0,0,1);
  880. glTexCoord2f (-gsize*ground_scale + ground_ofsx,
  881. -gsize*ground_scale + ground_ofsy);
  882. glVertex3f (-gsize,-gsize,offset);
  883. glTexCoord2f (gsize*ground_scale + ground_ofsx,
  884. -gsize*ground_scale + ground_ofsy);
  885. glVertex3f (gsize,-gsize,offset);
  886. glTexCoord2f (gsize*ground_scale + ground_ofsx,
  887. gsize*ground_scale + ground_ofsy);
  888. glVertex3f (gsize,gsize,offset);
  889. glTexCoord2f (-gsize*ground_scale + ground_ofsx,
  890. gsize*ground_scale + ground_ofsy);
  891. glVertex3f (-gsize,gsize,offset);
  892. glEnd();
  893. glDisable (GL_FOG);
  894. }
  895. static void drawPyramidGrid()
  896. {
  897. // setup stuff
  898. glEnable (GL_LIGHTING);
  899. glDisable (GL_TEXTURE_2D);
  900. glShadeModel (GL_FLAT);
  901. glEnable (GL_DEPTH_TEST);
  902. glDepthFunc (GL_LESS);
  903. // draw the pyramid grid
  904. for (int i=-1; i<=1; i++) {
  905. for (int j=-1; j<=1; j++) {
  906. glPushMatrix();
  907. glTranslatef ((float)i,(float)j,(float)0);
  908. if (i==1 && j==0) setColor (1,0,0,1);
  909. else if (i==0 && j==1) setColor (0,0,1,1);
  910. else setColor (1,1,0,1);
  911. const float k = 0.03f;
  912. glBegin (GL_TRIANGLE_FAN);
  913. glNormal3f (0,-1,1);
  914. glVertex3f (0,0,k);
  915. glVertex3f (-k,-k,0);
  916. glVertex3f ( k,-k,0);
  917. glNormal3f (1,0,1);
  918. glVertex3f ( k, k,0);
  919. glNormal3f (0,1,1);
  920. glVertex3f (-k, k,0);
  921. glNormal3f (-1,0,1);
  922. glVertex3f (-k,-k,0);
  923. glEnd();
  924. glPopMatrix();
  925. }
  926. }
  927. }
  928. void dsDrawFrame (int width, int height, dsFunctions *fn, int pause)
  929. {
  930. if (current_state < 1) dsDebug ("internal error");
  931. current_state = 2;
  932. // setup stuff
  933. glEnable (GL_LIGHTING);
  934. glEnable (GL_LIGHT0);
  935. glDisable (GL_TEXTURE_2D);
  936. glDisable (GL_TEXTURE_GEN_S);
  937. glDisable (GL_TEXTURE_GEN_T);
  938. glShadeModel (GL_FLAT);
  939. glEnable (GL_DEPTH_TEST);
  940. glDepthFunc (GL_LESS);
  941. glEnable (GL_CULL_FACE);
  942. glCullFace (GL_BACK);
  943. glFrontFace (GL_CCW);
  944. // setup viewport
  945. glViewport (0,0,width,height);
  946. glMatrixMode (GL_PROJECTION);
  947. glLoadIdentity();
  948. const float vnear = 0.1f;
  949. const float vfar = 100.0f;
  950. const float k = 0.8f; // view scale, 1 = +/- 45 degrees
  951. if (width >= height) {
  952. float k2 = float(height)/float(width);
  953. glFrustum (-vnear*k,vnear*k,-vnear*k*k2,vnear*k*k2,vnear,vfar);
  954. }
  955. else {
  956. float k2 = float(width)/float(height);
  957. glFrustum (-vnear*k*k2,vnear*k*k2,-vnear*k,vnear*k,vnear,vfar);
  958. }
  959. // setup lights. it makes a difference whether this is done in the
  960. // GL_PROJECTION matrix mode (lights are scene relative) or the
  961. // GL_MODELVIEW matrix mode (lights are camera relative, bad!).
  962. static GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
  963. static GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  964. static GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  965. glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
  966. glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  967. glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
  968. glColor3f (1.0, 1.0, 1.0);
  969. // clear the window
  970. glClearColor (0.5,0.5,0.5,0);
  971. glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  972. // snapshot camera position (in MS Windows it is changed by the GUI thread)
  973. float view2_xyz[3];
  974. float view2_hpr[3];
  975. memcpy (view2_xyz,view_xyz,sizeof(float)*3);
  976. memcpy (view2_hpr,view_hpr,sizeof(float)*3);
  977. // go to GL_MODELVIEW matrix mode and set the camera
  978. glMatrixMode (GL_MODELVIEW);
  979. glLoadIdentity();
  980. setCamera (view2_xyz[0],view2_xyz[1],view2_xyz[2],
  981. view2_hpr[0],view2_hpr[1],view2_hpr[2]);
  982. // set the light position (for some reason we have to do this in model view.
  983. static GLfloat light_position[] = { LIGHTX, LIGHTY, 1.0, 0.0 };
  984. glLightfv (GL_LIGHT0, GL_POSITION, light_position);
  985. // draw the background (ground, sky etc)
  986. drawSky (view2_xyz);
  987. drawGround();
  988. // draw the little markers on the ground
  989. drawPyramidGrid();
  990. // leave openGL in a known state - flat shaded white, no textures
  991. glEnable (GL_LIGHTING);
  992. glDisable (GL_TEXTURE_2D);
  993. glShadeModel (GL_FLAT);
  994. glEnable (GL_DEPTH_TEST);
  995. glDepthFunc (GL_LESS);
  996. glColor3f (1,1,1);
  997. setColor (1,1,1,1);
  998. // draw the rest of the objects. set drawing state first.
  999. color[0] = 1;
  1000. color[1] = 1;
  1001. color[2] = 1;
  1002. color[3] = 1;
  1003. tnum = 0;
  1004. if (fn->step) fn->step (pause);
  1005. }
  1006. int dsGetShadows()
  1007. {
  1008. return use_shadows;
  1009. }
  1010. void dsSetShadows (int a)
  1011. {
  1012. use_shadows = (a != 0);
  1013. }
  1014. int dsGetTextures()
  1015. {
  1016. return use_textures;
  1017. }
  1018. void dsSetTextures (int a)
  1019. {
  1020. use_textures = (a != 0);
  1021. }
  1022. //***************************************************************************
  1023. // C interface
  1024. // sets lighting and texture modes, sets current color
  1025. static void setupDrawingMode()
  1026. {
  1027. glEnable (GL_LIGHTING);
  1028. if (tnum) {
  1029. if (use_textures) {
  1030. glEnable (GL_TEXTURE_2D);
  1031. texture[tnum]->bind (1);
  1032. glEnable (GL_TEXTURE_GEN_S);
  1033. glEnable (GL_TEXTURE_GEN_T);
  1034. glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
  1035. glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
  1036. static GLfloat s_params[4] = {1.0f,1.0f,0.0f,1};
  1037. static GLfloat t_params[4] = {0.817f,-0.817f,0.817f,1};
  1038. glTexGenfv (GL_S,GL_OBJECT_PLANE,s_params);
  1039. glTexGenfv (GL_T,GL_OBJECT_PLANE,t_params);
  1040. }
  1041. else {
  1042. glDisable (GL_TEXTURE_2D);
  1043. }
  1044. }
  1045. else {
  1046. glDisable (GL_TEXTURE_2D);
  1047. }
  1048. setColor (color[0],color[1],color[2],color[3]);
  1049. if (color[3] < 1) {
  1050. glEnable (GL_BLEND);
  1051. glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  1052. }
  1053. else {
  1054. glDisable (GL_BLEND);
  1055. }
  1056. }
  1057. static void setShadowDrawingMode()
  1058. {
  1059. glDisable (GL_LIGHTING);
  1060. if (use_textures) {
  1061. glEnable (GL_TEXTURE_2D);
  1062. ground_texture->bind (1);
  1063. glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
  1064. glEnable (GL_TEXTURE_2D);
  1065. glEnable (GL_TEXTURE_GEN_S);
  1066. glEnable (GL_TEXTURE_GEN_T);
  1067. glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
  1068. glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
  1069. static GLfloat s_params[4] = {ground_scale,0,0,ground_ofsx};
  1070. static GLfloat t_params[4] = {0,ground_scale,0,ground_ofsy};
  1071. glTexGenfv (GL_S,GL_EYE_PLANE,s_params);
  1072. glTexGenfv (GL_T,GL_EYE_PLANE,t_params);
  1073. }
  1074. else {
  1075. glDisable (GL_TEXTURE_2D);
  1076. glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
  1077. GROUND_B*SHADOW_INTENSITY);
  1078. }
  1079. glDepthRange (0,0.9999);
  1080. }
  1081. extern "C" void dsSimulationLoop (int argc, char **argv,
  1082. int window_width, int window_height,
  1083. dsFunctions *fn)
  1084. {
  1085. if (current_state != 0) dsError ("dsSimulationLoop() called more than once");
  1086. current_state = 1;
  1087. // look for flags that apply to us
  1088. int initial_pause = 0;
  1089. for (int i=1; i<argc; i++) {
  1090. if (strcmp(argv[i],"-notex")==0) use_textures = 0;
  1091. if (strcmp(argv[i],"-noshadow")==0) use_shadows = 0;
  1092. if (strcmp(argv[i],"-noshadows")==0) use_shadows = 0;
  1093. if (strcmp(argv[i],"-pause")==0) initial_pause = 1;
  1094. if (strcmp(argv[i],"-texturepath")==0)
  1095. if (++i < argc)
  1096. fn->path_to_textures = argv[i];
  1097. }
  1098. if (fn->version > DS_VERSION)
  1099. dsDebug ("bad version number in dsFunctions structure");
  1100. initMotionModel();
  1101. dsPlatformSimLoop (window_width,window_height,fn,initial_pause);
  1102. current_state = 0;
  1103. }
  1104. extern "C" void dsSetViewpoint (float xyz[3], float hpr[3])
  1105. {
  1106. if (current_state < 1) dsError ("dsSetViewpoint() called before simulation started");
  1107. if (xyz) {
  1108. view_xyz[0] = xyz[0];
  1109. view_xyz[1] = xyz[1];
  1110. view_xyz[2] = xyz[2];
  1111. }
  1112. if (hpr) {
  1113. view_hpr[0] = hpr[0];
  1114. view_hpr[1] = hpr[1];
  1115. view_hpr[2] = hpr[2];
  1116. wrapCameraAngles();
  1117. }
  1118. }
  1119. extern "C" void dsGetViewpoint (float xyz[3], float hpr[3])
  1120. {
  1121. if (current_state < 1) dsError ("dsGetViewpoint() called before simulation started");
  1122. if (xyz) {
  1123. xyz[0] = view_xyz[0];
  1124. xyz[1] = view_xyz[1];
  1125. xyz[2] = view_xyz[2];
  1126. }
  1127. if (hpr) {
  1128. hpr[0] = view_hpr[0];
  1129. hpr[1] = view_hpr[1];
  1130. hpr[2] = view_hpr[2];
  1131. }
  1132. }
  1133. extern "C" void dsSetTexture (int texture_number)
  1134. {
  1135. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1136. tnum = texture_number;
  1137. }
  1138. extern "C" void dsSetColor (float red, float green, float blue)
  1139. {
  1140. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1141. color[0] = red;
  1142. color[1] = green;
  1143. color[2] = blue;
  1144. color[3] = 1;
  1145. }
  1146. extern "C" void dsSetColorAlpha (float red, float green, float blue,
  1147. float alpha)
  1148. {
  1149. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1150. color[0] = red;
  1151. color[1] = green;
  1152. color[2] = blue;
  1153. color[3] = alpha;
  1154. }
  1155. extern "C" void dsDrawBox (const float pos[3], const float R[12],
  1156. const float sides[3])
  1157. {
  1158. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1159. setupDrawingMode();
  1160. glShadeModel (GL_FLAT);
  1161. setTransform (pos,R);
  1162. drawBox (sides);
  1163. glPopMatrix();
  1164. if (use_shadows) {
  1165. setShadowDrawingMode();
  1166. setShadowTransform();
  1167. setTransform (pos,R);
  1168. drawBox (sides);
  1169. glPopMatrix();
  1170. glPopMatrix();
  1171. glDepthRange (0,1);
  1172. }
  1173. }
  1174. extern "C" void dsDrawConvex (const float pos[3], const float R[12],
  1175. const float *_planes,unsigned int _planecount,
  1176. const float *_points, unsigned int _pointcount,
  1177. const unsigned int *_polygons)
  1178. {
  1179. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1180. setupDrawingMode();
  1181. glShadeModel (GL_FLAT);
  1182. setTransform (pos,R);
  1183. drawConvex(_planes,_planecount,_points,_pointcount,_polygons);
  1184. glPopMatrix();
  1185. if (use_shadows) {
  1186. setShadowDrawingMode();
  1187. setShadowTransform();
  1188. setTransform (pos,R);
  1189. drawConvex(_planes,_planecount,_points,_pointcount,_polygons);
  1190. glPopMatrix();
  1191. glPopMatrix();
  1192. glDepthRange (0,1);
  1193. }
  1194. }
  1195. extern "C" void dsDrawSphere (const float pos[3], const float R[12],
  1196. float radius)
  1197. {
  1198. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1199. setupDrawingMode();
  1200. glEnable (GL_NORMALIZE);
  1201. glShadeModel (GL_SMOOTH);
  1202. setTransform (pos,R);
  1203. glScaled (radius,radius,radius);
  1204. drawSphere();
  1205. glPopMatrix();
  1206. glDisable (GL_NORMALIZE);
  1207. // draw shadows
  1208. if (use_shadows) {
  1209. glDisable (GL_LIGHTING);
  1210. if (use_textures) {
  1211. ground_texture->bind (1);
  1212. glEnable (GL_TEXTURE_2D);
  1213. glDisable (GL_TEXTURE_GEN_S);
  1214. glDisable (GL_TEXTURE_GEN_T);
  1215. glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
  1216. }
  1217. else {
  1218. glDisable (GL_TEXTURE_2D);
  1219. glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
  1220. GROUND_B*SHADOW_INTENSITY);
  1221. }
  1222. glShadeModel (GL_FLAT);
  1223. glDepthRange (0,0.9999);
  1224. drawSphereShadow (pos[0],pos[1],pos[2],radius);
  1225. glDepthRange (0,1);
  1226. }
  1227. }
  1228. extern "C" void dsDrawTriangle (const float pos[3], const float R[12],
  1229. const float *v0, const float *v1,
  1230. const float *v2, int solid)
  1231. {
  1232. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1233. setupDrawingMode();
  1234. glShadeModel (GL_FLAT);
  1235. setTransform (pos,R);
  1236. drawTriangle (v0, v1, v2, solid);
  1237. glPopMatrix();
  1238. }
  1239. extern "C" void dsDrawCylinder (const float pos[3], const float R[12],
  1240. float length, float radius)
  1241. {
  1242. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1243. setupDrawingMode();
  1244. glShadeModel (GL_SMOOTH);
  1245. setTransform (pos,R);
  1246. drawCylinder (length,radius,0);
  1247. glPopMatrix();
  1248. if (use_shadows) {
  1249. setShadowDrawingMode();
  1250. setShadowTransform();
  1251. setTransform (pos,R);
  1252. drawCylinder (length,radius,0);
  1253. glPopMatrix();
  1254. glPopMatrix();
  1255. glDepthRange (0,1);
  1256. }
  1257. }
  1258. extern "C" void dsDrawCapsule (const float pos[3], const float R[12],
  1259. float length, float radius)
  1260. {
  1261. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1262. setupDrawingMode();
  1263. glShadeModel (GL_SMOOTH);
  1264. setTransform (pos,R);
  1265. drawCapsule (length,radius);
  1266. glPopMatrix();
  1267. if (use_shadows) {
  1268. setShadowDrawingMode();
  1269. setShadowTransform();
  1270. setTransform (pos,R);
  1271. drawCapsule (length,radius);
  1272. glPopMatrix();
  1273. glPopMatrix();
  1274. glDepthRange (0,1);
  1275. }
  1276. }
  1277. static void drawLine(const float pos1[3], const float pos2[3])
  1278. {
  1279. glDisable (GL_LIGHTING);
  1280. glLineWidth (2);
  1281. glShadeModel (GL_FLAT);
  1282. glBegin (GL_LINES);
  1283. glVertex3f (pos1[0],pos1[1],pos1[2]);
  1284. glVertex3f (pos2[0],pos2[1],pos2[2]);
  1285. glEnd();
  1286. }
  1287. extern "C" void dsDrawLine (const float pos1[3], const float pos2[3])
  1288. {
  1289. setupDrawingMode();
  1290. glColor4f(color[0], color[1], color[2], color[3]);
  1291. drawLine(pos1, pos2);
  1292. if (use_shadows) {
  1293. setShadowDrawingMode();
  1294. setShadowTransform();
  1295. drawLine(pos1, pos2);
  1296. glPopMatrix();
  1297. glDepthRange (0,1);
  1298. }
  1299. }
  1300. extern "C" void dsDrawBoxD (const double pos[3], const double R[12],
  1301. const double sides[3])
  1302. {
  1303. int i;
  1304. float pos2[3],R2[12],fsides[3];
  1305. for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  1306. for (i=0; i<12; i++) R2[i]=(float)R[i];
  1307. for (i=0; i<3; i++) fsides[i]=(float)sides[i];
  1308. dsDrawBox (pos2,R2,fsides);
  1309. }
  1310. extern "C" void dsDrawConvexD (const double pos[3], const double R[12],
  1311. const double *_planes, unsigned int _planecount,
  1312. const double *_points, unsigned int _pointcount,
  1313. const unsigned int *_polygons)
  1314. {
  1315. if (current_state != 2) dsError ("drawing function called outside simulation loop");
  1316. setupDrawingMode();
  1317. glShadeModel (GL_FLAT);
  1318. setTransformD (pos,R);
  1319. drawConvexD(_planes,_planecount,_points,_pointcount,_polygons);
  1320. glPopMatrix();
  1321. if (use_shadows) {
  1322. setShadowDrawingMode();
  1323. setShadowTransform();
  1324. setTransformD (pos,R);
  1325. drawConvexD(_planes,_planecount,_points,_pointcount,_polygons);
  1326. glPopMatrix();
  1327. glPopMatrix();
  1328. glDepthRange (0,1);
  1329. }
  1330. }
  1331. void dsDrawSphereD (const double pos[3], const double R[12], float radius)
  1332. {
  1333. int i;
  1334. float pos2[3],R2[12];
  1335. for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  1336. for (i=0; i<12; i++) R2[i]=(float)R[i];
  1337. dsDrawSphere (pos2,R2,radius);
  1338. }
  1339. void dsDrawTriangleD (const double pos[3], const double R[12],
  1340. const double *v0, const double *v1,
  1341. const double *v2, int solid)
  1342. {
  1343. int i;
  1344. float pos2[3],R2[12];
  1345. for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  1346. for (i=0; i<12; i++) R2[i]=(float)R[i];
  1347. setupDrawingMode();
  1348. glShadeModel (GL_FLAT);
  1349. setTransform (pos2,R2);
  1350. drawTriangleD (v0, v1, v2, solid);
  1351. glPopMatrix();
  1352. }
  1353. void dsDrawCylinderD (const double pos[3], const double R[12],
  1354. float length, float radius)
  1355. {
  1356. int i;
  1357. float pos2[3],R2[12];
  1358. for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  1359. for (i=0; i<12; i++) R2[i]=(float)R[i];
  1360. dsDrawCylinder (pos2,R2,length,radius);
  1361. }
  1362. void dsDrawCapsuleD (const double pos[3], const double R[12],
  1363. float length, float radius)
  1364. {
  1365. int i;
  1366. float pos2[3],R2[12];
  1367. for (i=0; i<3; i++) pos2[i]=(float)pos[i];
  1368. for (i=0; i<12; i++) R2[i]=(float)R[i];
  1369. dsDrawCapsule (pos2,R2,length,radius);
  1370. }
  1371. void dsDrawLineD (const double _pos1[3], const double _pos2[3])
  1372. {
  1373. int i;
  1374. float pos1[3],pos2[3];
  1375. for (i=0; i<3; i++) pos1[i]=(float)_pos1[i];
  1376. for (i=0; i<3; i++) pos2[i]=(float)_pos2[i];
  1377. dsDrawLine (pos1,pos2);
  1378. }
  1379. void dsSetSphereQuality (int n)
  1380. {
  1381. sphere_quality = n;
  1382. }
  1383. void dsSetCapsuleQuality (int n)
  1384. {
  1385. capped_cylinder_quality = n;
  1386. }
  1387. void dsSetDrawMode(int mode)
  1388. {
  1389. switch(mode)
  1390. {
  1391. case DS_POLYFILL:
  1392. glPolygonMode(GL_FRONT,GL_FILL);
  1393. break;
  1394. case DS_WIREFRAME:
  1395. glPolygonMode(GL_FRONT,GL_LINE);
  1396. break;
  1397. }
  1398. }