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