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