2 /* projtex.c - by David Yu and David Blythe, SGI */
5 ** Demonstrates simple projective texture mapping.
7 ** Button1 changes view, Button2 moves texture.
9 ** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli
10 ** "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92)
12 ** 1994,1995 -- David G Yu
14 ** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm
25 #include "../util/readtex.c"
29 /* Some <math.h> files do not define M_PI... */
31 #define M_PI 3.14159265358979323846
37 int winWidth
, winHeight
;
39 GLboolean redrawContinuously
= GL_FALSE
;
43 MoveNone
, MoveView
, MoveObject
, MoveTexture
45 enum MoveModes mode
= MoveNone
;
47 GLfloat objectXform
[4][4];
48 GLfloat textureXform
[MAX_TEX
][4][4];
50 void (*drawObject
) (void);
51 void (*loadTexture
) (void);
52 GLboolean textureEnabled
= GL_TRUE
;
53 GLboolean showProjection
= GL_TRUE
;
54 GLboolean linearFilter
= GL_TRUE
;
56 char *texFilename
[MAX_TEX
] = {
60 "../images/reflect.rgb"
64 GLfloat zoomFactor
= 1.0;
66 /*****************************************************************/
69 void ActiveTexture(int i
)
71 glActiveTextureARB(i
);
75 /* matrix = identity */
77 matrixIdentity(GLfloat matrix
[16])
97 /* matrix2 = transpose(matrix1) */
99 matrixTranspose(GLfloat matrix2
[16], GLfloat matrix1
[16])
101 matrix2
[0] = matrix1
[0];
102 matrix2
[1] = matrix1
[4];
103 matrix2
[2] = matrix1
[8];
104 matrix2
[3] = matrix1
[12];
106 matrix2
[4] = matrix1
[1];
107 matrix2
[5] = matrix1
[5];
108 matrix2
[6] = matrix1
[9];
109 matrix2
[7] = matrix1
[13];
111 matrix2
[8] = matrix1
[2];
112 matrix2
[9] = matrix1
[6];
113 matrix2
[10] = matrix1
[10];
114 matrix2
[11] = matrix1
[14];
116 matrix2
[12] = matrix1
[3];
117 matrix2
[13] = matrix1
[7];
118 matrix2
[14] = matrix1
[14];
119 matrix2
[15] = matrix1
[15];
122 /*****************************************************************/
124 /* load SGI .rgb image (pad with a border of the specified width and color) */
127 imgLoad(char *filenameIn
, int borderIn
, GLfloat borderColorIn
[4],
128 int *wOut
, int *hOut
, GLubyte
** imgOut
)
130 int border
= borderIn
;
133 GLubyte
*image
, *img
, *p
;
134 int i
, j
, components
;
136 image
= (GLubyte
*) read_texture(filenameIn
, &width
, &height
, &components
);
137 w
= width
+ 2 * border
;
138 h
= height
+ 2 * border
;
139 img
= (GLubyte
*) calloc(w
* h
, 4 * sizeof(unsigned char));
142 for (j
= -border
; j
< height
+ border
; ++j
) {
143 for (i
= -border
; i
< width
+ border
; ++i
) {
144 if (0 <= j
&& j
<= height
- 1 && 0 <= i
&& i
<= width
- 1) {
145 p
[0] = image
[4 * (j
* width
+ i
) + 0];
146 p
[1] = image
[4 * (j
* width
+ i
) + 1];
147 p
[2] = image
[4 * (j
* width
+ i
) + 2];
150 p
[0] = borderColorIn
[0] * 0xff;
151 p
[1] = borderColorIn
[1] * 0xff;
152 p
[2] = borderColorIn
[2] * 0xff;
153 p
[3] = borderColorIn
[3] * 0xff;
166 /*****************************************************************/
168 /* Load the image file specified on the command line as the current texture */
170 loadImageTextures(void)
172 GLfloat borderColor
[4] =
173 {1.0, 1.0, 1.0, 1.0};
176 for (tex
= 0; tex
< NumTextures
; tex
++) {
177 GLubyte
*image
, *texData3
, *texData4
;
178 GLint imgWidth
, imgHeight
;
182 printf("loading %s\n", texFilename
[tex
]);
183 image
= LoadRGBImage(texFilename
[tex
], &imgWidth
, &imgHeight
, &imgFormat
);
185 printf("can't find %s\n", texFilename
[tex
]);
188 assert(imgFormat
== GL_RGB
);
190 /* scale to 256x256 */
191 texData3
= malloc(256 * 256 * 4);
192 texData4
= malloc(256 * 256 * 4);
195 gluScaleImage(imgFormat
, imgWidth
, imgHeight
, GL_UNSIGNED_BYTE
, image
,
196 256, 256, GL_UNSIGNED_BYTE
, texData3
);
198 /* convert to rgba */
199 for (i
= 0; i
< 256 * 256; i
++) {
200 texData4
[i
*4+0] = texData3
[i
*3+0];
201 texData4
[i
*4+1] = texData3
[i
*3+1];
202 texData4
[i
*4+2] = texData3
[i
*3+2];
203 texData4
[i
*4+3] = 128;
206 /* put transparent border around image */
207 for (i
= 0; i
< 256; i
++) {
208 texData4
[i
*4+0] = 255;
209 texData4
[i
*4+1] = 255;
210 texData4
[i
*4+2] = 255;
214 for (i
= 0; i
< 256; i
++) {
215 texData4
[j
+ i
*4+0] = 255;
216 texData4
[j
+ i
*4+1] = 255;
217 texData4
[j
+ i
*4+2] = 255;
218 texData4
[j
+ i
*4+3] = 0;
220 for (i
= 0; i
< 256; i
++) {
227 for (i
= 0; i
< 256; i
++) {
228 j
= i
* 256 * 4 + 255 * 4;
235 ActiveTexture(GL_TEXTURE0_ARB
+ tex
);
236 glBindTexture(GL_TEXTURE_2D
, tex
+ 1);
238 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
239 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 256, 256, 0,
240 GL_RGBA
, GL_UNSIGNED_BYTE
, texData4
);
243 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
244 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
246 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
247 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
249 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
253 /* Create a simple spotlight pattern and make it the current texture */
255 loadSpotlightTexture(void)
257 static int texWidth
= 64, texHeight
= 64;
258 static GLubyte
*texData
;
259 GLfloat borderColor
[4] =
260 {0.1, 0.1, 0.1, 1.0};
266 texData
= (GLubyte
*) malloc(texWidth
* texHeight
* 4 * sizeof(GLubyte
));
269 for (j
= 0; j
< texHeight
; ++j
) {
270 float dy
= (texHeight
* 0.5 - j
+ 0.5) / (texHeight
* 0.5);
272 for (i
= 0; i
< texWidth
; ++i
) {
273 float dx
= (texWidth
* 0.5 - i
+ 0.5) / (texWidth
* 0.5);
274 float r
= cos(M_PI
/ 2.0 * sqrt(dx
* dx
+ dy
* dy
));
277 r
= (r
< 0) ? 0 : r
* r
;
278 c
= 0xff * (r
+ borderColor
[0]);
279 p
[0] = (c
<= 0xff) ? c
: 0xff;
280 c
= 0xff * (r
+ borderColor
[1]);
281 p
[1] = (c
<= 0xff) ? c
: 0xff;
282 c
= 0xff * (r
+ borderColor
[2]);
283 p
[2] = (c
<= 0xff) ? c
: 0xff;
284 c
= 0xff * (r
+ borderColor
[3]);
285 p
[3] = (c
<= 0xff) ? c
: 0xff;
291 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
292 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
294 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
295 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
297 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
298 gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, texWidth
, texHeight
,
299 GL_RGBA
, GL_UNSIGNED_BYTE
, texData
);
302 /*****************************************************************/
308 while ((error
= glGetError()) != GL_NO_ERROR
) {
309 fprintf(stderr
, "Error: %s\n", (char *) gluErrorString(error
));
318 glNormal3f(-1.0, 0.0, 0.0);
319 glColor3f(0.80, 0.50, 0.50);
320 glVertex3f(-0.5, -0.5, -0.5);
321 glVertex3f(-0.5, -0.5, 0.5);
322 glVertex3f(-0.5, 0.5, 0.5);
323 glVertex3f(-0.5, 0.5, -0.5);
325 glNormal3f(1.0, 0.0, 0.0);
326 glColor3f(0.50, 0.80, 0.50);
327 glVertex3f(0.5, 0.5, 0.5);
328 glVertex3f(0.5, -0.5, 0.5);
329 glVertex3f(0.5, -0.5, -0.5);
330 glVertex3f(0.5, 0.5, -0.5);
332 glNormal3f(0.0, -1.0, 0.0);
333 glColor3f(0.50, 0.50, 0.80);
334 glVertex3f(-0.5, -0.5, -0.5);
335 glVertex3f(0.5, -0.5, -0.5);
336 glVertex3f(0.5, -0.5, 0.5);
337 glVertex3f(-0.5, -0.5, 0.5);
339 glNormal3f(0.0, 1.0, 0.0);
340 glColor3f(0.50, 0.80, 0.80);
341 glVertex3f(0.5, 0.5, 0.5);
342 glVertex3f(0.5, 0.5, -0.5);
343 glVertex3f(-0.5, 0.5, -0.5);
344 glVertex3f(-0.5, 0.5, 0.5);
346 glNormal3f(0.0, 0.0, -1.0);
347 glColor3f(0.80, 0.50, 0.80);
348 glVertex3f(-0.5, -0.5, -0.5);
349 glVertex3f(-0.5, 0.5, -0.5);
350 glVertex3f(0.5, 0.5, -0.5);
351 glVertex3f(0.5, -0.5, -0.5);
353 glNormal3f(0.0, 0.0, 1.0);
354 glColor3f(1.00, 0.80, 0.50);
355 glVertex3f(0.5, 0.5, 0.5);
356 glVertex3f(-0.5, 0.5, 0.5);
357 glVertex3f(-0.5, -0.5, 0.5);
358 glVertex3f(0.5, -0.5, 0.5);
363 drawDodecahedron(void)
365 #define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */
366 #define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */
367 #define C (0.5 * 1.0)
368 GLfloat vertexes
[20][3] =
394 GLint polygons
[12][5] =
411 glColor3f(0.75, 0.75, 0.75);
412 for (i
= 0; i
< 12; ++i
) {
413 GLfloat
*p0
, *p1
, *p2
, d
;
414 GLfloat u
[3], v
[3], n
[3];
416 p0
= &vertexes
[polygons
[i
][0]][0];
417 p1
= &vertexes
[polygons
[i
][1]][0];
418 p2
= &vertexes
[polygons
[i
][2]][0];
420 u
[0] = p2
[0] - p1
[0];
421 u
[1] = p2
[1] - p1
[1];
422 u
[2] = p2
[2] - p1
[2];
424 v
[0] = p0
[0] - p1
[0];
425 v
[1] = p0
[1] - p1
[1];
426 v
[2] = p0
[2] - p1
[2];
428 n
[0] = u
[1] * v
[2] - u
[2] * v
[1];
429 n
[1] = u
[2] * v
[0] - u
[0] * v
[2];
430 n
[2] = u
[0] * v
[1] - u
[1] * v
[0];
432 d
= 1.0 / sqrt(n
[0] * n
[0] + n
[1] * n
[1] + n
[2] * n
[2]);
442 glVertex3fv(vertexes
[polygons
[i
][3]]);
443 glVertex3fv(vertexes
[polygons
[i
][4]]);
454 double majorStep
= (M_PI
/ numMajor
);
455 double minorStep
= (2.0 * M_PI
/ numMinor
);
458 glColor3f(0.50, 0.50, 0.50);
459 for (i
= 0; i
< numMajor
; ++i
) {
460 double a
= i
* majorStep
;
461 double b
= a
+ majorStep
;
462 double r0
= radius
* sin(a
);
463 double r1
= radius
* sin(b
);
464 GLfloat z0
= radius
* cos(a
);
465 GLfloat z1
= radius
* cos(b
);
467 glBegin(GL_TRIANGLE_STRIP
);
468 for (j
= 0; j
<= numMinor
; ++j
) {
469 double c
= j
* minorStep
;
473 glNormal3f((x
* r0
) / radius
, (y
* r0
) / radius
, z0
/ radius
);
474 glTexCoord2f(j
/ (GLfloat
) numMinor
, i
/ (GLfloat
) numMajor
);
475 glVertex3f(x
* r0
, y
* r0
, z0
);
477 glNormal3f((x
* r1
) / radius
, (y
* r1
) / radius
, z1
/ radius
);
478 glTexCoord2f(j
/ (GLfloat
) numMinor
, (i
+ 1) / (GLfloat
) numMajor
);
479 glVertex3f(x
* r1
, y
* r1
, z1
);
485 /*****************************************************************/
487 float xmin
= -0.035, xmax
= 0.035;
488 float ymin
= -0.035, ymax
= 0.035;
491 float distance
= -1.0;
494 loadTextureProjection(int texUnit
, GLfloat m
[16])
496 GLfloat mInverse
[4][4];
498 /* Should use true inverse, but since m consists only of rotations, we can
499 just use the transpose. */
500 matrixTranspose((GLfloat
*) mInverse
, m
);
502 ActiveTexture(GL_TEXTURE0_ARB
+ texUnit
);
503 glMatrixMode(GL_TEXTURE
);
505 glTranslatef(0.5, 0.5, 0.0);
506 glScalef(0.5, 0.5, 1.0);
507 glFrustum(xmin
, xmax
, ymin
, ymax
, nnear
, ffar
);
508 glTranslatef(0.0, 0.0, distance
);
509 glMultMatrixf((GLfloat
*) mInverse
);
510 glMatrixMode(GL_MODELVIEW
);
514 drawTextureProjection(void)
516 float t
= ffar
/ nnear
;
522 n
[0][2] = -(nnear
+ distance
);
526 n
[1][2] = -(nnear
+ distance
);
530 n
[2][2] = -(nnear
+ distance
);
534 n
[3][2] = -(nnear
+ distance
);
538 f
[0][2] = -(ffar
+ distance
);
542 f
[1][2] = -(ffar
+ distance
);
546 f
[2][2] = -(ffar
+ distance
);
550 f
[3][2] = -(ffar
+ distance
);
552 glColor3f(1.0, 1.0, 0.0);
553 glBegin(GL_LINE_LOOP
);
573 /*****************************************************************/
578 GLfloat light0Pos
[4] =
579 {0.3, 0.3, 0.0, 1.0};
581 {0.01, 0.01, 0.01, 1.00};
583 {0.65, 0.65, 0.65, 1.00};
585 {0.30, 0.30, 0.30, 1.00};
586 GLfloat matShine
= 10.0;
587 GLfloat eyePlaneS
[] =
588 {1.0, 0.0, 0.0, 0.0};
589 GLfloat eyePlaneT
[] =
590 {0.0, 1.0, 0.0, 0.0};
591 GLfloat eyePlaneR
[] =
592 {0.0, 0.0, 1.0, 0.0};
593 GLfloat eyePlaneQ
[] =
594 {0.0, 0.0, 0.0, 1.0};
598 glClearColor(0.41, 0.41, 0.31, 0.0);
600 glEnable(GL_DEPTH_TEST
);
602 /* glLineWidth(2.0);*/
604 glCullFace(GL_FRONT
);
605 glEnable(GL_CULL_FACE
);
607 glMatrixMode(GL_PROJECTION
);
608 glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
609 glMatrixMode(GL_MODELVIEW
);
610 glTranslatef(0, 0, -2);
612 matrixIdentity((GLfloat
*) objectXform
);
613 for (i
= 0; i
< NumTextures
; i
++) {
614 matrixIdentity((GLfloat
*) textureXform
[i
]);
617 glMatrixMode(GL_PROJECTION
);
620 glOrtho(0, 1, 0, 1, -1, 1);
621 glMatrixMode(GL_MODELVIEW
);
628 glMatrixMode(GL_PROJECTION
);
630 glMatrixMode(GL_MODELVIEW
);
633 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, matAmb
);
634 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, matDiff
);
635 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, matSpec
);
636 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, matShine
);
638 glEnable(GL_COLOR_MATERIAL
);
640 glLightfv(GL_LIGHT0
, GL_POSITION
, light0Pos
);
643 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
644 glEnable(GL_LIGHTING
);
651 for (i
= 0; i
< NumTextures
; i
++) {
652 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
654 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
655 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
656 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
658 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
659 glTexGenfv(GL_S
, GL_EYE_PLANE
, eyePlaneS
);
661 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
662 glTexGenfv(GL_T
, GL_EYE_PLANE
, eyePlaneT
);
664 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
665 glTexGenfv(GL_R
, GL_EYE_PLANE
, eyePlaneR
);
667 glTexGeni(GL_Q
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
668 glTexGenfv(GL_Q
, GL_EYE_PLANE
, eyePlaneQ
);
677 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
679 if (textureEnabled
) {
680 if (mode
== MoveTexture
|| mode
== MoveView
) {
681 /* Have OpenGL compute the new transformation (simple but slow). */
682 for (i
= 0; i
< NumTextures
; i
++) {
687 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
690 glRotatef(angle
*(i
+1), axis
[0], axis
[1], axis
[2]);
692 glMultMatrixf((GLfloat
*) textureXform
[i
]);
693 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) textureXform
[i
]);
697 for (i
= 0; i
< NumTextures
; i
++) {
698 loadTextureProjection(i
, (GLfloat
*) textureXform
[i
]);
701 if (showProjection
) {
702 for (i
= 0; i
< NumTextures
; i
++) {
703 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
705 glMultMatrixf((GLfloat
*) textureXform
[i
]);
706 glDisable(GL_LIGHTING
);
707 drawTextureProjection();
708 glEnable(GL_LIGHTING
);
712 for (i
= 0; i
< NumTextures
; i
++) {
713 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
714 glEnable(GL_TEXTURE_2D
);
715 glEnable(GL_TEXTURE_GEN_S
);
716 glEnable(GL_TEXTURE_GEN_T
);
717 glEnable(GL_TEXTURE_GEN_R
);
718 glEnable(GL_TEXTURE_GEN_Q
);
721 if (mode
== MoveObject
|| mode
== MoveView
) {
722 /* Have OpenGL compute the new transformation (simple but slow). */
725 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
726 glMultMatrixf((GLfloat
*) objectXform
);
727 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) objectXform
);
731 glMultMatrixf((GLfloat
*) objectXform
);
735 for (i
= 0; i
< NumTextures
; i
++) {
736 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
737 glDisable(GL_TEXTURE_2D
);
738 glDisable(GL_TEXTURE_GEN_S
);
739 glDisable(GL_TEXTURE_GEN_T
);
740 glDisable(GL_TEXTURE_GEN_R
);
741 glDisable(GL_TEXTURE_GEN_Q
);
744 if (zoomFactor
> 1.0) {
745 glDisable(GL_DEPTH_TEST
);
746 glCopyPixels(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
, GL_COLOR
);
747 glEnable(GL_DEPTH_TEST
);
754 /*****************************************************************/
756 /* simple trackball-like motion control */
761 ptov(int x
, int y
, int width
, int height
, float v
[3])
765 /* project x,y onto a hemi-sphere centered within width, height */
766 v
[0] = (2.0 * x
- width
) / width
;
767 v
[1] = (height
- 2.0 * y
) / height
;
768 d
= sqrt(v
[0] * v
[0] + v
[1] * v
[1]);
769 v
[2] = cos((M_PI
/ 2.0) * ((d
< 1.0) ? d
: 1.0));
770 a
= 1.0 / sqrt(v
[0] * v
[0] + v
[1] * v
[1] + v
[2] * v
[2]);
777 startMotion(int x
, int y
, int but
, int time
)
779 if (but
== GLUT_LEFT_BUTTON
) {
781 } else if (but
== GLUT_MIDDLE_BUTTON
) {
788 ptov(x
, y
, winWidth
, winHeight
, lastPos
);
800 if (visible
== GLUT_VISIBLE
) {
801 if (redrawContinuously
)
802 glutIdleFunc(animate
);
804 if (redrawContinuously
)
810 stopMotion(int but
, int time
)
812 if ((but
== GLUT_LEFT_BUTTON
&& mode
== MoveView
) ||
813 (but
== GLUT_MIDDLE_BUTTON
&& mode
== MoveTexture
)) {
818 if (time
== lastTime
) {
819 /* redrawContinuously = GL_TRUE;*/
820 glutIdleFunc(animate
);
823 redrawContinuously
= GL_FALSE
;
826 if (!redrawContinuously
) {
832 trackMotion(int x
, int y
)
834 float curPos
[3], dx
, dy
, dz
;
836 ptov(x
, y
, winWidth
, winHeight
, curPos
);
838 dx
= curPos
[0] - lastPos
[0];
839 dy
= curPos
[1] - lastPos
[1];
840 dz
= curPos
[2] - lastPos
[2];
841 angle
= 90.0 * sqrt(dx
* dx
+ dy
* dy
+ dz
* dz
);
843 axis
[0] = lastPos
[1] * curPos
[2] - lastPos
[2] * curPos
[1];
844 axis
[1] = lastPos
[2] * curPos
[0] - lastPos
[0] * curPos
[2];
845 axis
[2] = lastPos
[0] * curPos
[1] - lastPos
[1] * curPos
[0];
847 lastTime
= glutGet(GLUT_ELAPSED_TIME
);
848 lastPos
[0] = curPos
[0];
849 lastPos
[1] = curPos
[1];
850 lastPos
[2] = curPos
[2];
854 /*****************************************************************/
865 drawObject
= drawCube
;
868 drawObject
= drawDodecahedron
;
871 drawObject
= drawSphere
;
886 static int texture
= 0;
890 if (texture
== 1 && texFilename
== NULL
) {
891 /* Skip file texture if not loaded. */
897 textureEnabled
= GL_FALSE
;
900 loadTexture
= loadImageTextures
;
902 textureEnabled
= GL_TRUE
;
905 loadTexture
= loadSpotlightTexture
;
907 textureEnabled
= GL_TRUE
;
917 printf("'h' - help\n");
918 printf("'l' - toggle linear/nearest filter\n");
919 printf("'s' - toggle projection frustum\n");
920 printf("'t' - toggle projected texture\n");
921 printf("'o' - toggle object\n");
922 printf("'z' - increase zoom factor\n");
923 printf("'Z' - decrease zoom factor\n");
924 printf("left mouse - move view\n");
925 printf("middle mouse - move projection\n");
930 key(unsigned char key
, int x
, int y
)
937 linearFilter
= !linearFilter
;
941 showProjection
= !showProjection
;
951 glPixelZoom(zoomFactor
, zoomFactor
);
952 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
956 if (zoomFactor
< 1.0)
958 glPixelZoom(zoomFactor
, zoomFactor
);
959 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
969 mouse(int button
, int state
, int x
, int y
)
971 if (state
== GLUT_DOWN
)
972 startMotion(x
, y
, button
, glutGet(GLUT_ELAPSED_TIME
));
973 else if (state
== GLUT_UP
)
974 stopMotion(button
, glutGet(GLUT_ELAPSED_TIME
));
979 reshape(int w
, int h
)
983 glViewport(0, 0, w
/ zoomFactor
, h
/ zoomFactor
);
990 if (selection
== 666) {
993 key((unsigned char) selection
, 0, 0);
997 main(int argc
, char **argv
)
999 glutInit(&argc
, argv
);
1002 NumTextures
= atoi(argv
[1]);
1004 assert(NumTextures
<= MAX_TEX
);
1006 glutInitDisplayMode(GLUT_RGBA
| GLUT_DEPTH
| GLUT_DOUBLE
);
1007 (void) glutCreateWindow("projtex");
1009 loadTexture
= loadImageTextures
;
1010 drawObject
= drawCube
;
1012 glutDisplayFunc(display
);
1013 glutKeyboardFunc(key
);
1014 glutReshapeFunc(reshape
);
1015 glutMouseFunc(mouse
);
1016 glutMotionFunc(trackMotion
);
1017 glutVisibilityFunc(vis
);
1018 glutCreateMenu(menu
);
1019 glutAddMenuEntry("Toggle showing projection", 's');
1020 glutAddMenuEntry("Switch texture", 't');
1021 glutAddMenuEntry("Switch object", 'o');
1022 glutAddMenuEntry("Toggle filtering", 'l');
1023 glutAddMenuEntry("Quit", 666);
1024 glutAttachMenu(GLUT_RIGHT_BUTTON
);
1027 return 0; /* ANSI C requires main to return int. */