1 /* $Id: stex3d.c,v 1.3 1999/12/16 08:54:22 brianp Exp $ */
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.
7 * Author: Daniel Barrero
9 * dbarrero@pegasus.uniandes.edu.co
11 * Converted to GLUT by brianp on 1/1/98
14 * cc stex3d.c -o stex3d -lglut -lMesaGLU -lMesaGL -lX11 -lXext -lm
16 *---------------------------- */
20 * Revision 1.3 1999/12/16 08:54:22 brianp
21 * added a cast to malloc call
23 * Revision 1.2 1999/09/17 12:27:01 brianp
24 * silenced some warnings
26 * Revision 1.1.1.1 1999/08/19 00:55:40 jtg
29 * Revision 3.1 1998/06/09 01:53:49 brianp
30 * main() should return an int
32 * Revision 3.0 1998/02/14 18:42:29 brianp
44 /* function declarations */
46 #define M_PI 3.14159265358979323846
51 create3Dtexture(void),
57 float turbulence(float point
[3], float lofreq
, float hifreq
);
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]);
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 */
71 /*function definitions */
72 int main(int argc
, char **argv
)
75 if (parseCmdLine(argc
, argv
) == GL_FALSE
) {
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
);
86 if (glutCreateWindow("stex3d") <= 0) {
92 glutReshapeFunc(resize
);
93 glutKeyboardFunc(KeyHandler
);
94 glutDisplayFunc(drawScene
);
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 };
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
);
119 /* create torus for texturing */
120 figure
=glGenLists(1);
122 /* tkSolidTorus(figure,0.3,1.2);*/
124 /* start the noise function variables */
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
)));
134 /* if texture is supported then generate the texture */
137 glEnable(GL_TEXTURE_3D_EXT
);
139 glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);
142 glEnable(GL_DEPTH_TEST
);
144 glShadeModel(GL_FLAT
);
145 glColor3f(0.6,0.7,0.8);
148 void buildFigure(void)
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;
160 scalFac
=1/(outerRadius
*2);
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
;
170 v0
[0] = cos(theta1
) * (outerRadius
+ innerRadius
* cos(phi1
));
171 v0
[1] = -sin(theta1
) * (outerRadius
+ innerRadius
* cos(phi1
));
172 v0
[2] = innerRadius
* sin(phi1
);
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
);
181 v3
[0] = cos(theta1
) * (outerRadius
+ innerRadius
* cos(phi2
));
182 v3
[1] = -sin(theta1
) * (outerRadius
+ innerRadius
* cos(phi2
));
183 v3
[2] = innerRadius
* sin(phi2
);
185 n0
[0] = cos(theta1
) * (cos(phi1
));
186 n0
[1] = -sin(theta1
) * (cos(phi1
));
189 n1
[0] = cos(theta2
) * (cos(phi1
));
190 n1
[1] = -sin(theta2
) * (cos(phi1
));
193 n2
[0] = cos(theta2
) * (cos(phi2
));
194 n2
[1] = -sin(theta2
) * (cos(phi2
));
197 n3
[0] = cos(theta1
) * (cos(phi2
));
198 n3
[1] = -sin(theta1
) * (cos(phi2
));
201 t0
[0] = v0
[0]*scalFac
+ 0.5;
202 t0
[1] = v0
[1]*scalFac
+ 0.5;
203 t0
[2] = v0
[2]*scalFac
+ 0.5;
205 t1
[0] = v1
[0]*scalFac
+ 0.5;
206 t1
[1] = v1
[1]*scalFac
+ 0.5;
207 t1
[2] = v1
[2]*scalFac
+ 0.5;
209 t2
[0] = v2
[0]*scalFac
+ 0.5;
210 t2
[1] = v2
[1]*scalFac
+ 0.5;
211 t2
[2] = v2
[2]*scalFac
+ 0.5;
213 t3
[0] = v3
[0]*scalFac
+ 0.5;
214 t3
[1] = v3
[1]*scalFac
+ 0.5;
215 t3
[2] = v3
[2]*scalFac
+ 0.5;
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
);
228 void create3Dtexture()
235 printf("creating 3d textures...\n");
236 voxels
= (unsigned char *) malloc((size_t)(4*tex_width
*tex_height
*tex_depth
));
238 for (i
=0;i
<tex_width
;i
++){
240 for (j
=0;j
<tex_height
;j
++) {
242 for (k
=0;k
<tex_depth
;k
++) {
244 tmp
=(sin(k
*i
*j
+turbulence(vec
,0.01,1))+1)*127.5;
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
);
262 glTexImage3DEXT(GL_TEXTURE_3D_EXT
, 0, GL_RGBA
,
263 tex_width
, tex_height
, tex_depth
,
264 0, GL_RGBA
, GL_UNSIGNED_BYTE
, voxels
);
266 printf("finished setting up 3d texture image...\n");
269 int isExtSupported(char *ext
)
271 /* routine to find whether a specified OpenGL extension is supported */
275 char *allext
= (char *)(glGetString(GL_EXTENSIONS
));
278 if (len
<= 0) return 0;
282 if (!strncmp(c
,ext
,len
)) return 1;
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");
319 /* visualization defaults */
321 doubleBuffer
= GL_FALSE
;
322 directRender
= GL_TRUE
;
332 GLenum
parseCmdLine(int argc
, char **argv
)
338 for (i
= 1; i
< argc
; i
++) {
339 if (strcmp(argv
[i
], "-ci") == 0) {
341 } else if (strcmp(argv
[i
], "-rgb") == 0) {
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) {
361 printf("%s (Bad option).\n", argv
[i
]);
366 if(tex_width
==0 || tex_height
==0 || tex_depth
==0) {
367 printf("%s (Bad option).\n", "size parameters can't be 0");
376 /* clear background, z buffer etc */
377 glClear(GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
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);
391 void resize(int w
, int h
)
393 glViewport(0, 0, (GLint
)w
, (GLint
)h
);
394 glMatrixMode(GL_PROJECTION
);
396 glOrtho(-2,2,-2,2,-5,10);
397 glMatrixMode(GL_MODELVIEW
);
399 glTranslatef(0,0,-5);
402 void cleanEverything(void)
408 void KeyHandler( unsigned char key
, int x
, int y
)
415 case 'Q': /* quit game. */
438 glEnable(GL_TEXTURE_3D_EXT
);
441 glDisable(GL_TEXTURE_3D_EXT
);
444 glShadeModel(GL_SMOOTH
);
447 glShadeModel(GL_FLAT
);
450 glDisable(GL_TEXTURE_GEN_S
);
451 glDisable(GL_TEXTURE_GEN_T
);
452 glDisable(GL_TEXTURE_GEN_R
);
455 glEnable(GL_TEXTURE_GEN_S
);
456 glEnable(GL_TEXTURE_GEN_T
);
457 glEnable(GL_TEXTURE_GEN_R
);
465 /*--------------------------------------------------------------------
466 noise function over R3 - implemented by a pseudorandom tricubic spline
467 EXCERPTED FROM SIGGRAPH 92, COURSE 23
471 ----------------------------------------------------------------------*/
474 #define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
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); \
485 float noise3(float vec
[3])
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
;
491 setup(0, bx0
,bx1
, rx0
,rx1
);
492 setup(1, by0
,by1
, ry0
,ry1
);
493 setup(2, bz0
,bz1
, rz0
,rz1
);
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) )
511 q
= g
[ b00
+ bz0
] ; u
= at(rx0
,ry0
,rz0
);
512 q
= g
[ b10
+ bz0
] ; v
= at(rx1
,ry0
,rz0
);
515 q
= g
[ b01
+ bz0
] ; u
= at(rx0
,ry1
,rz0
);
516 q
= g
[ b11
+ bz0
] ; v
= at(rx1
,ry1
,rz0
);
519 c
= lerp(sy
, a
, b
); /* interpolate in y at lo x */
521 q
= g
[ b00
+ bz1
] ; u
= at(rx0
,ry0
,rz1
);
522 q
= g
[ b10
+ bz1
] ; v
= at(rx1
,ry0
,rz1
);
525 q
= g
[ b01
+ bz1
] ; u
= at(rx0
,ry1
,rz1
);
526 q
= g
[ b11
+ bz1
] ; v
= at(rx1
,ry1
,rz1
);
529 d
= lerp(sy
, a
, b
); /* interpolate in y at hi x */
531 return 1.5 * lerp(sz
, c
, d
); /* interpolate in z */
540 /* Create an array of random gradient vectors uniformly on the unit sphere */
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
;
547 } while (s
> 1.0); /* If not in sphere try again */ s
= sqrt(s
);
548 for (j
= 0 ; j
< 3 ; j
++) /* Else normalize */
552 /* Create a pseudorandom permutation of [1..B] */
553 for (i
= 0 ; i
< B
; i
++)
555 for (i
= B
; i
> 0 ; i
-= 2) {
557 p
[i
] = p
[j
= rand() % B
];
561 /* Extend g and p arrays to allow for faster indexing */
562 for (i
= 0 ; i
< B
+ 2 ; i
++) {
564 for (j
= 0 ; j
< 3 ; j
++)
565 g
[B
+ i
][j
] = g
[i
][j
];
569 float turbulence(float point
[3], float lofreq
, float hifreq
)
573 p
[0] = point
[0] + 123.456;
578 for (freq
= lofreq
; freq
< hifreq
; freq
*= 2.) {
579 t
+= fabs(noise3(p
)) / freq
;
584 return t
- 0.3; /* readjust to make mean value = 0.0 */