Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/drawstuff/src/drawstuff.cpp @ 216

Last change on this file since 216 was 216, checked in by mathiask, 16 years ago

[Physik] add ode-0.9

File size: 39.7 KB
Line 
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}
Note: See TracBrowser for help on using the repository browser.