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