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