fixed bug when using display lists
[mesa.git] / progs / demos / stex3d.c
1 /* $Id: stex3d.c,v 1.3 1999/12/16 08:54:22 brianp Exp $ */
2
3 /*-----------------------------
4 * stex3d.c GL example of the mesa 3d-texture extention to simulate procedural
5 * texturing, it uses a perlin noise and turbulence functions.
6 *
7 * Author: Daniel Barrero
8 * barrero@irit.fr
9 * dbarrero@pegasus.uniandes.edu.co
10 *
11 * Converted to GLUT by brianp on 1/1/98
12 *
13 *
14 * cc stex3d.c -o stex3d -lglut -lMesaGLU -lMesaGL -lX11 -lXext -lm
15 *
16 *---------------------------- */
17
18 /*
19 * $Log: stex3d.c,v $
20 * Revision 1.3 1999/12/16 08:54:22 brianp
21 * added a cast to malloc call
22 *
23 * Revision 1.2 1999/09/17 12:27:01 brianp
24 * silenced some warnings
25 *
26 * Revision 1.1.1.1 1999/08/19 00:55:40 jtg
27 * Imported sources
28 *
29 * Revision 3.1 1998/06/09 01:53:49 brianp
30 * main() should return an int
31 *
32 * Revision 3.0 1998/02/14 18:42:29 brianp
33 * initial rev
34 *
35 */
36
37
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <math.h>
42 #include <GL/gl.h>
43 #include <GL/glut.h>
44 /* function declarations */
45 #ifndef M_PI
46 #define M_PI 3.14159265358979323846
47 #endif
48
49 void init(void),
50 printHelp(void),
51 create3Dtexture(void),
52 setDefaults(void),
53 drawScene(void),
54 resize(int w, int h),
55 buildFigure(void),
56 initNoise(void);
57 float turbulence(float point[3], float lofreq, float hifreq);
58
59 int isExtSupported(char *ext);
60 void KeyHandler( unsigned char key, int x, int y );
61 GLenum parseCmdLine(int argc, char **argv);
62 float noise3(float vec[3]);
63
64 /* global variables */
65 GLenum rgb, doubleBuffer, directRender, windType; /* visualization state*/
66 float tex_width,tex_height,tex_depth; /* texture volume dimensions */
67 unsigned char *voxels; /* texture data ptr */
68 int angx,angy,angz;
69 GLuint figure;
70
71 /*function definitions */
72 int main(int argc, char **argv)
73 {
74
75 if (parseCmdLine(argc, argv) == GL_FALSE) {
76 exit(0);
77 }
78
79 glutInitWindowPosition(0, 0);
80 glutInitWindowSize(400, 400);
81 windType = (rgb) ? GLUT_RGB : GLUT_INDEX;
82 windType |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
83 windType |= GLUT_DEPTH;
84 glutInitDisplayMode(windType);
85
86 if (glutCreateWindow("stex3d") <= 0) {
87 exit(0);
88 }
89 /* init all */
90 init();
91
92 glutReshapeFunc(resize);
93 glutKeyboardFunc(KeyHandler);
94 glutDisplayFunc(drawScene);
95 glutMainLoop();
96 return 0;
97 }
98
99 void init()
100 {
101 /* init light */
102 GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
103 GLfloat mat_shininess[] = { 25.0 };
104 GLfloat gray[] = { 0.6, 0.6, 0.6, 0.0 };
105 GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 };
106 GLfloat light_position[] = { 0.0, 1.0, 1.0, 0.0 };
107
108 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
109 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
110 glLightfv(GL_LIGHT1, GL_POSITION, light_position);
111 glLightfv(GL_LIGHT1, GL_AMBIENT, gray);
112 glLightfv(GL_LIGHT1, GL_DIFFUSE, white);
113 glLightfv(GL_LIGHT1, GL_SPECULAR, white);
114 glColorMaterial(GL_FRONT, GL_DIFFUSE);
115 glEnable(GL_COLOR_MATERIAL);
116 glEnable(GL_LIGHTING);
117 glEnable(GL_LIGHT1);
118
119 /* create torus for texturing */
120 figure=glGenLists(1);
121 buildFigure();
122 /* tkSolidTorus(figure,0.3,1.2);*/
123
124 /* start the noise function variables */
125 initNoise();
126
127 /* see if the texture 3d extention is supported */
128 if (!isExtSupported("GL_EXT_texture3D")) {
129 printf("Sorry this GL implementation (%s) does not support 3d texture extentions\n",
130 (char *)(glGetString(GL_RENDERER)));
131 /* tkQuit();*/
132 }
133
134 /* if texture is supported then generate the texture */
135 create3Dtexture();
136
137 glEnable(GL_TEXTURE_3D_EXT);
138 /*
139 glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);
140 glEnable(GL_BLEND);
141 */
142 glEnable(GL_DEPTH_TEST);
143
144 glShadeModel(GL_FLAT);
145 glColor3f(0.6,0.7,0.8);
146 }
147
148 void buildFigure(void)
149 { GLint i, j;
150 float theta1, phi1, theta2, phi2, rings, sides;
151 float v0[03], v1[3], v2[3], v3[3];
152 float t0[03], t1[3], t2[3], t3[3];
153 float n0[3], n1[3], n2[3], n3[3];
154 float innerRadius=0.4;
155 float outerRadius=0.8;
156 float scalFac;
157
158 rings = 8;
159 sides = 10;
160 scalFac=1/(outerRadius*2);
161
162 glNewList(figure, GL_COMPILE);
163 for (i = 0; i < rings; i++) {
164 theta1 = (float)i * 2.0 * M_PI / rings;
165 theta2 = (float)(i + 1) * 2.0 * M_PI / rings;
166 for (j = 0; j < sides; j++) {
167 phi1 = (float)j * 2.0 * M_PI / sides;
168 phi2 = (float)(j + 1) * 2.0 * M_PI / sides;
169
170 v0[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi1));
171 v0[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi1));
172 v0[2] = innerRadius * sin(phi1);
173
174 v1[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi1));
175 v1[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi1));
176 v1[2] = innerRadius * sin(phi1);
177 v2[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi2));
178 v2[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi2));
179 v2[2] = innerRadius * sin(phi2);
180
181 v3[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi2));
182 v3[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi2));
183 v3[2] = innerRadius * sin(phi2);
184
185 n0[0] = cos(theta1) * (cos(phi1));
186 n0[1] = -sin(theta1) * (cos(phi1));
187 n0[2] = sin(phi1);
188
189 n1[0] = cos(theta2) * (cos(phi1));
190 n1[1] = -sin(theta2) * (cos(phi1));
191 n1[2] = sin(phi1);
192
193 n2[0] = cos(theta2) * (cos(phi2));
194 n2[1] = -sin(theta2) * (cos(phi2));
195 n2[2] = sin(phi2);
196
197 n3[0] = cos(theta1) * (cos(phi2));
198 n3[1] = -sin(theta1) * (cos(phi2));
199 n3[2] = sin(phi2);
200
201 t0[0] = v0[0]*scalFac + 0.5;
202 t0[1] = v0[1]*scalFac + 0.5;
203 t0[2] = v0[2]*scalFac + 0.5;
204
205 t1[0] = v1[0]*scalFac + 0.5;
206 t1[1] = v1[1]*scalFac + 0.5;
207 t1[2] = v1[2]*scalFac + 0.5;
208
209 t2[0] = v2[0]*scalFac + 0.5;
210 t2[1] = v2[1]*scalFac + 0.5;
211 t2[2] = v2[2]*scalFac + 0.5;
212
213 t3[0] = v3[0]*scalFac + 0.5;
214 t3[1] = v3[1]*scalFac + 0.5;
215 t3[2] = v3[2]*scalFac + 0.5;
216
217 glBegin(GL_POLYGON);
218 glNormal3fv(n3); glTexCoord3fv(t3); glVertex3fv(v3);
219 glNormal3fv(n2); glTexCoord3fv(t2); glVertex3fv(v2);
220 glNormal3fv(n1); glTexCoord3fv(t1); glVertex3fv(v1);
221 glNormal3fv(n0); glTexCoord3fv(t0); glVertex3fv(v0);
222 glEnd();
223 }
224 }
225 glEndList();
226 }
227
228 void create3Dtexture()
229 {
230 int i,j,k;
231 unsigned char *vp;
232 float vec[3];
233 int tmp;
234
235 printf("creating 3d textures...\n");
236 voxels = (unsigned char *) malloc((size_t)(4*tex_width*tex_height*tex_depth));
237 vp=voxels;
238 for (i=0;i<tex_width;i++){
239 vec[0]=i;
240 for (j=0;j<tex_height;j++) {
241 vec[1]=j;
242 for (k=0;k<tex_depth;k++) {
243 vec[2]=k;
244 tmp=(sin(k*i*j+turbulence(vec,0.01,1))+1)*127.5;
245 *vp++=0;
246 *vp++=0;
247 *vp++=tmp;
248 *vp++=tmp+128;
249 }
250 }
251 }
252
253 printf("setting up 3d texture...\n");
254 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
255 glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
256 glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
257 glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT);
258 glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT);
259 glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_R_EXT, GL_REPEAT);
260 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
261
262 glTexImage3DEXT(GL_TEXTURE_3D_EXT, 0, GL_RGBA,
263 tex_width, tex_height, tex_depth,
264 0, GL_RGBA, GL_UNSIGNED_BYTE, voxels);
265
266 printf("finished setting up 3d texture image...\n");
267 }
268
269 int isExtSupported(char *ext)
270 {
271 /* routine to find whether a specified OpenGL extension is supported */
272
273 char *c;
274 int len;
275 char *allext = (char *)(glGetString(GL_EXTENSIONS));
276
277 len = strlen(ext);
278 if (len <= 0) return 0;
279
280 c = allext;
281 while (c) {
282 if (!strncmp(c,ext,len)) return 1;
283 c = strchr(c+1,'G');
284 }
285 return 0;
286 }
287
288 void printHelp()
289 {
290 printf("\nUsage: stex3d <cmd line options>\n");
291 printf(" cmd line options:\n");
292 printf(" -help print this help!\n");
293 printf(" -rgb RGBA mode. (Default)\n");
294 printf(" -ci Color index mode.\n");
295 printf(" -sb Single buffer mode. (Default)\n");
296 printf(" -db Double buffer mode. \n");
297 printf(" -dr Direct render mode.\n");
298 printf(" -ir Indirect render mode. (Default)\n");
299 printf(" -wxxx Width of the texture (Default=64)\n");
300 printf(" -hxxx Height of the texture (Default=64)\n");
301 printf(" -dxxx Depth of the texture (Default=64)\n");
302 printf(" Keyboard Options:\n");
303 printf(" 1 Object Texture coordinates (Default)\n");
304 printf(" 2 Eye Texture coordinates \n");
305 printf(" x rotate around x clockwise\n");
306 printf(" X rotate around x counter clockwise\n");
307 printf(" y rotate around y clockwise\n");
308 printf(" Y rotate around y counter clockwise\n");
309 printf(" z rotate around z clockwise\n");
310 printf(" Z rotate around z counter clockwise\n");
311 printf(" t enable 3-D texuring (Default)\n");
312 printf(" T disable 3-D texuring\n");
313 printf(" s smooth shading \n");
314 printf(" S flat shading (Default)\n");
315 }
316
317 void setDefaults()
318 {
319 /* visualization defaults */
320 rgb = GL_TRUE;
321 doubleBuffer = GL_FALSE;
322 directRender = GL_TRUE;
323 angx=130;
324 angy=30;
325 angz=0;
326 /* texture values */
327 tex_width=64;
328 tex_height=64;
329 tex_depth=64;
330 }
331
332 GLenum parseCmdLine(int argc, char **argv)
333 {
334 GLint i;
335
336 setDefaults();
337
338 for (i = 1; i < argc; i++) {
339 if (strcmp(argv[i], "-ci") == 0) {
340 rgb = GL_FALSE;
341 } else if (strcmp(argv[i], "-rgb") == 0) {
342 rgb = GL_TRUE;
343 } else if (strcmp(argv[i], "-sb") == 0) {
344 doubleBuffer = GL_FALSE;
345 } else if (strcmp(argv[i], "-db") == 0) {
346 doubleBuffer = GL_TRUE;
347 } else if (strcmp(argv[i], "-dr") == 0) {
348 directRender = GL_TRUE;
349 } else if (strcmp(argv[i], "-ir") == 0) {
350 directRender = GL_FALSE;
351 } else if (strstr(argv[i], "-w") == 0) {
352 tex_width=atoi((argv[i])+2);
353 } else if (strstr(argv[i], "-h") == 0) {
354 tex_height=atoi((argv[i])+2);
355 } else if (strstr(argv[i], "-d") == 0) {
356 tex_depth=atoi((argv[i])+2);
357 } else if (strcmp(argv[i], "-help") == 0) {
358 printHelp();
359 return GL_FALSE;
360 } else {
361 printf("%s (Bad option).\n", argv[i]);
362 printHelp();
363 return GL_FALSE;
364 }
365 }
366 if(tex_width==0 || tex_height==0 || tex_depth==0) {
367 printf("%s (Bad option).\n", "size parameters can't be 0");
368 printHelp();
369 return GL_FALSE;
370 }
371 return GL_TRUE;
372 }
373
374 void drawScene()
375 {
376 /* clear background, z buffer etc */
377 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
378 glPushMatrix();
379 glRotatef(angx,1.0,0.0,0.0);
380 glRotatef(angy,0.0,1.0,0.0);
381 glRotatef(angz,0.0,0.0,1.0);
382
383 glCallList(figure);
384 glPopMatrix();
385 glFlush();
386 if(doubleBuffer)
387 glutSwapBuffers();
388 ;
389 }
390
391 void resize(int w, int h)
392 {
393 glViewport(0, 0, (GLint)w, (GLint)h);
394 glMatrixMode(GL_PROJECTION);
395 glLoadIdentity();
396 glOrtho(-2,2,-2,2,-5,10);
397 glMatrixMode(GL_MODELVIEW);
398 glLoadIdentity();
399 glTranslatef(0,0,-5);
400 }
401
402 void cleanEverything(void)
403 {
404 /* free(voxels); */
405 }
406
407
408 void KeyHandler( unsigned char key, int x, int y )
409 {
410 (void) x;
411 (void) y;
412 switch(key) {
413 case 27:
414 case 'q':
415 case 'Q': /* quit game. */
416 cleanEverything();
417 exit(0);
418 break;
419 case 'x':
420 angx+=10;
421 break;
422 case 'X':
423 angx-=10;
424 break;
425 case 'y':
426 angy+=10;
427 break;
428 case 'Y':
429 angy-=10;
430 break;
431 case 'z':
432 angz+=10;
433 break;
434 case 'Z':
435 angz-=10;
436 break;
437 case 't':
438 glEnable(GL_TEXTURE_3D_EXT);
439 break;
440 case 'T':
441 glDisable(GL_TEXTURE_3D_EXT);
442 break;
443 case 's':
444 glShadeModel(GL_SMOOTH);
445 break;
446 case 'S':
447 glShadeModel(GL_FLAT);
448 break;
449 case '1':
450 glDisable(GL_TEXTURE_GEN_S);
451 glDisable(GL_TEXTURE_GEN_T);
452 glDisable(GL_TEXTURE_GEN_R);
453 break;
454 case '2':
455 glEnable(GL_TEXTURE_GEN_S);
456 glEnable(GL_TEXTURE_GEN_T);
457 glEnable(GL_TEXTURE_GEN_R);
458 break;
459 default:
460 break;
461 }
462 glutPostRedisplay();
463 }
464
465 /*--------------------------------------------------------------------
466 noise function over R3 - implemented by a pseudorandom tricubic spline
467 EXCERPTED FROM SIGGRAPH 92, COURSE 23
468 PROCEDURAL MODELING
469 Ken Perlin
470 New York University
471 ----------------------------------------------------------------------*/
472
473
474 #define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
475 #define B 256
476 static int p[B + B + 2];
477 static float g[B + B + 2][3];
478 #define setup(i,b0,b1,r0,r1) \
479 t = vec[i] + 10000.; \
480 b0 = ((int)t) & (B-1); \
481 b1 = (b0+1) & (B-1); \
482 r0 = t - (int)t; \
483 r1 = r0 - 1.;
484
485 float noise3(float vec[3])
486 {
487 int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
488 float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
489 register int i, j;
490
491 setup(0, bx0,bx1, rx0,rx1);
492 setup(1, by0,by1, ry0,ry1);
493 setup(2, bz0,bz1, rz0,rz1);
494
495 i = p[ bx0 ];
496 j = p[ bx1 ];
497
498 b00 = p[ i + by0 ];
499 b10 = p[ j + by0 ];
500 b01 = p[ i + by1 ];
501 b11 = p[ j + by1 ];
502
503 #define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
504 #define surve(t) ( t * t * (3. - 2. * t) )
505 #define lerp(t, a, b) ( a + t * (b - a) )
506
507 sx = surve(rx0);
508 sy = surve(ry0);
509 sz = surve(rz0);
510
511 q = g[ b00 + bz0 ] ; u = at(rx0,ry0,rz0);
512 q = g[ b10 + bz0 ] ; v = at(rx1,ry0,rz0);
513 a = lerp(sx, u, v);
514
515 q = g[ b01 + bz0 ] ; u = at(rx0,ry1,rz0);
516 q = g[ b11 + bz0 ] ; v = at(rx1,ry1,rz0);
517 b = lerp(sx, u, v);
518
519 c = lerp(sy, a, b); /* interpolate in y at lo x */
520
521 q = g[ b00 + bz1 ] ; u = at(rx0,ry0,rz1);
522 q = g[ b10 + bz1 ] ; v = at(rx1,ry0,rz1);
523 a = lerp(sx, u, v);
524
525 q = g[ b01 + bz1 ] ; u = at(rx0,ry1,rz1);
526 q = g[ b11 + bz1 ] ; v = at(rx1,ry1,rz1);
527 b = lerp(sx, u, v);
528
529 d = lerp(sy, a, b); /* interpolate in y at hi x */
530
531 return 1.5 * lerp(sz, c, d); /* interpolate in z */
532 }
533
534 void initNoise()
535 {
536 /*long random();*/
537 int i, j, k;
538 float v[3], s;
539
540 /* Create an array of random gradient vectors uniformly on the unit sphere */
541 /*srandom(1);*/
542 srand(1);
543 for (i = 0 ; i < B ; i++) {
544 do { /* Choose uniformly in a cube */ for (j=0 ; j<3 ; j++)
545 v[j] = (float)((rand() % (B + B)) - B) / B;
546 s = DOT(v,v);
547 } while (s > 1.0); /* If not in sphere try again */ s = sqrt(s);
548 for (j = 0 ; j < 3 ; j++) /* Else normalize */
549 g[i][j] = v[j] / s;
550 }
551
552 /* Create a pseudorandom permutation of [1..B] */
553 for (i = 0 ; i < B ; i++)
554 p[i] = i;
555 for (i = B ; i > 0 ; i -= 2) {
556 k = p[i];
557 p[i] = p[j = rand() % B];
558 p[j] = k;
559 }
560
561 /* Extend g and p arrays to allow for faster indexing */
562 for (i = 0 ; i < B + 2 ; i++) {
563 p[B + i] = p[i];
564 for (j = 0 ; j < 3 ; j++)
565 g[B + i][j] = g[i][j];
566 }
567 }
568
569 float turbulence(float point[3], float lofreq, float hifreq)
570 {
571 float freq, t, p[3];
572
573 p[0] = point[0] + 123.456;
574 p[1] = point[1];
575 p[2] = point[2];
576
577 t = 0;
578 for (freq = lofreq ; freq < hifreq ; freq *= 2.) {
579 t += fabs(noise3(p)) / freq;
580 p[0] *= 2.;
581 p[1] *= 2.;
582 p[2] *= 2.;
583 }
584 return t - 0.3; /* readjust to make mean value = 0.0 */
585 }
586