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