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
26 #include "../util/readtex.c"
30 /* Some <math.h> files do not define M_PI... */
32 #define M_PI 3.14159265358979323846
38 int winWidth
, winHeight
;
40 GLboolean redrawContinuously
= GL_FALSE
;
44 MoveNone
, MoveView
, MoveObject
, MoveTexture
46 enum MoveModes mode
= MoveNone
;
48 GLfloat objectXform
[4][4];
49 GLfloat textureXform
[MAX_TEX
][4][4];
51 void (*drawObject
) (void);
52 void (*loadTexture
) (void);
53 GLboolean textureEnabled
= GL_TRUE
;
54 GLboolean showProjection
= GL_TRUE
;
55 GLboolean linearFilter
= GL_TRUE
;
57 char *texFilename
[MAX_TEX
] = {
61 "../images/reflect.rgb"
65 GLfloat zoomFactor
= 1.0;
67 /*****************************************************************/
70 void ActiveTexture(int i
)
72 glActiveTextureARB(i
);
76 /* matrix = identity */
78 matrixIdentity(GLfloat matrix
[16])
98 /* matrix2 = transpose(matrix1) */
100 matrixTranspose(GLfloat matrix2
[16], GLfloat matrix1
[16])
102 matrix2
[0] = matrix1
[0];
103 matrix2
[1] = matrix1
[4];
104 matrix2
[2] = matrix1
[8];
105 matrix2
[3] = matrix1
[12];
107 matrix2
[4] = matrix1
[1];
108 matrix2
[5] = matrix1
[5];
109 matrix2
[6] = matrix1
[9];
110 matrix2
[7] = matrix1
[13];
112 matrix2
[8] = matrix1
[2];
113 matrix2
[9] = matrix1
[6];
114 matrix2
[10] = matrix1
[10];
115 matrix2
[11] = matrix1
[14];
117 matrix2
[12] = matrix1
[3];
118 matrix2
[13] = matrix1
[7];
119 matrix2
[14] = matrix1
[14];
120 matrix2
[15] = matrix1
[15];
123 /*****************************************************************/
125 /* load SGI .rgb image (pad with a border of the specified width and color) */
128 imgLoad(char *filenameIn
, int borderIn
, GLfloat borderColorIn
[4],
129 int *wOut
, int *hOut
, GLubyte
** imgOut
)
131 int border
= borderIn
;
134 GLubyte
*image
, *img
, *p
;
135 int i
, j
, components
;
137 image
= (GLubyte
*) read_texture(filenameIn
, &width
, &height
, &components
);
138 w
= width
+ 2 * border
;
139 h
= height
+ 2 * border
;
140 img
= (GLubyte
*) calloc(w
* h
, 4 * sizeof(unsigned char));
143 for (j
= -border
; j
< height
+ border
; ++j
) {
144 for (i
= -border
; i
< width
+ border
; ++i
) {
145 if (0 <= j
&& j
<= height
- 1 && 0 <= i
&& i
<= width
- 1) {
146 p
[0] = image
[4 * (j
* width
+ i
) + 0];
147 p
[1] = image
[4 * (j
* width
+ i
) + 1];
148 p
[2] = image
[4 * (j
* width
+ i
) + 2];
151 p
[0] = borderColorIn
[0] * 0xff;
152 p
[1] = borderColorIn
[1] * 0xff;
153 p
[2] = borderColorIn
[2] * 0xff;
154 p
[3] = borderColorIn
[3] * 0xff;
167 /*****************************************************************/
169 /* Load the image file specified on the command line as the current texture */
171 loadImageTextures(void)
173 GLfloat borderColor
[4] =
174 {1.0, 1.0, 1.0, 1.0};
177 for (tex
= 0; tex
< NumTextures
; tex
++) {
178 GLubyte
*image
, *texData3
, *texData4
;
179 GLint imgWidth
, imgHeight
;
183 printf("loading %s\n", texFilename
[tex
]);
184 image
= LoadRGBImage(texFilename
[tex
], &imgWidth
, &imgHeight
, &imgFormat
);
186 printf("can't find %s\n", texFilename
[tex
]);
189 assert(imgFormat
== GL_RGB
);
191 /* scale to 256x256 */
192 texData3
= malloc(256 * 256 * 4);
193 texData4
= malloc(256 * 256 * 4);
196 gluScaleImage(imgFormat
, imgWidth
, imgHeight
, GL_UNSIGNED_BYTE
, image
,
197 256, 256, GL_UNSIGNED_BYTE
, texData3
);
199 /* convert to rgba */
200 for (i
= 0; i
< 256 * 256; i
++) {
201 texData4
[i
*4+0] = texData3
[i
*3+0];
202 texData4
[i
*4+1] = texData3
[i
*3+1];
203 texData4
[i
*4+2] = texData3
[i
*3+2];
204 texData4
[i
*4+3] = 128;
207 /* put transparent border around image */
208 for (i
= 0; i
< 256; i
++) {
209 texData4
[i
*4+0] = 255;
210 texData4
[i
*4+1] = 255;
211 texData4
[i
*4+2] = 255;
215 for (i
= 0; i
< 256; i
++) {
216 texData4
[j
+ i
*4+0] = 255;
217 texData4
[j
+ i
*4+1] = 255;
218 texData4
[j
+ i
*4+2] = 255;
219 texData4
[j
+ i
*4+3] = 0;
221 for (i
= 0; i
< 256; i
++) {
228 for (i
= 0; i
< 256; i
++) {
229 j
= i
* 256 * 4 + 255 * 4;
236 ActiveTexture(GL_TEXTURE0_ARB
+ tex
);
237 glBindTexture(GL_TEXTURE_2D
, tex
+ 1);
239 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
240 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 256, 256, 0,
241 GL_RGBA
, GL_UNSIGNED_BYTE
, texData4
);
244 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
245 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
247 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
248 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
250 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
254 /* Create a simple spotlight pattern and make it the current texture */
256 loadSpotlightTexture(void)
258 static int texWidth
= 64, texHeight
= 64;
259 static GLubyte
*texData
;
260 GLfloat borderColor
[4] =
261 {0.1, 0.1, 0.1, 1.0};
267 texData
= (GLubyte
*) malloc(texWidth
* texHeight
* 4 * sizeof(GLubyte
));
270 for (j
= 0; j
< texHeight
; ++j
) {
271 float dy
= (texHeight
* 0.5 - j
+ 0.5) / (texHeight
* 0.5);
273 for (i
= 0; i
< texWidth
; ++i
) {
274 float dx
= (texWidth
* 0.5 - i
+ 0.5) / (texWidth
* 0.5);
275 float r
= cos(M_PI
/ 2.0 * sqrt(dx
* dx
+ dy
* dy
));
278 r
= (r
< 0) ? 0 : r
* r
;
279 c
= 0xff * (r
+ borderColor
[0]);
280 p
[0] = (c
<= 0xff) ? c
: 0xff;
281 c
= 0xff * (r
+ borderColor
[1]);
282 p
[1] = (c
<= 0xff) ? c
: 0xff;
283 c
= 0xff * (r
+ borderColor
[2]);
284 p
[2] = (c
<= 0xff) ? c
: 0xff;
285 c
= 0xff * (r
+ borderColor
[3]);
286 p
[3] = (c
<= 0xff) ? c
: 0xff;
292 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
293 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
295 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
296 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
298 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
299 gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, texWidth
, texHeight
,
300 GL_RGBA
, GL_UNSIGNED_BYTE
, texData
);
303 /*****************************************************************/
309 while ((error
= glGetError()) != GL_NO_ERROR
) {
310 fprintf(stderr
, "Error: %s\n", (char *) gluErrorString(error
));
319 glNormal3f(-1.0, 0.0, 0.0);
320 glColor3f(0.80, 0.50, 0.50);
321 glVertex3f(-0.5, -0.5, -0.5);
322 glVertex3f(-0.5, -0.5, 0.5);
323 glVertex3f(-0.5, 0.5, 0.5);
324 glVertex3f(-0.5, 0.5, -0.5);
326 glNormal3f(1.0, 0.0, 0.0);
327 glColor3f(0.50, 0.80, 0.50);
328 glVertex3f(0.5, 0.5, 0.5);
329 glVertex3f(0.5, -0.5, 0.5);
330 glVertex3f(0.5, -0.5, -0.5);
331 glVertex3f(0.5, 0.5, -0.5);
333 glNormal3f(0.0, -1.0, 0.0);
334 glColor3f(0.50, 0.50, 0.80);
335 glVertex3f(-0.5, -0.5, -0.5);
336 glVertex3f(0.5, -0.5, -0.5);
337 glVertex3f(0.5, -0.5, 0.5);
338 glVertex3f(-0.5, -0.5, 0.5);
340 glNormal3f(0.0, 1.0, 0.0);
341 glColor3f(0.50, 0.80, 0.80);
342 glVertex3f(0.5, 0.5, 0.5);
343 glVertex3f(0.5, 0.5, -0.5);
344 glVertex3f(-0.5, 0.5, -0.5);
345 glVertex3f(-0.5, 0.5, 0.5);
347 glNormal3f(0.0, 0.0, -1.0);
348 glColor3f(0.80, 0.50, 0.80);
349 glVertex3f(-0.5, -0.5, -0.5);
350 glVertex3f(-0.5, 0.5, -0.5);
351 glVertex3f(0.5, 0.5, -0.5);
352 glVertex3f(0.5, -0.5, -0.5);
354 glNormal3f(0.0, 0.0, 1.0);
355 glColor3f(1.00, 0.80, 0.50);
356 glVertex3f(0.5, 0.5, 0.5);
357 glVertex3f(-0.5, 0.5, 0.5);
358 glVertex3f(-0.5, -0.5, 0.5);
359 glVertex3f(0.5, -0.5, 0.5);
364 drawDodecahedron(void)
366 #define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */
367 #define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */
368 #define C (0.5 * 1.0)
369 GLfloat vertexes
[20][3] =
395 GLint polygons
[12][5] =
412 glColor3f(0.75, 0.75, 0.75);
413 for (i
= 0; i
< 12; ++i
) {
414 GLfloat
*p0
, *p1
, *p2
, d
;
415 GLfloat u
[3], v
[3], n
[3];
417 p0
= &vertexes
[polygons
[i
][0]][0];
418 p1
= &vertexes
[polygons
[i
][1]][0];
419 p2
= &vertexes
[polygons
[i
][2]][0];
421 u
[0] = p2
[0] - p1
[0];
422 u
[1] = p2
[1] - p1
[1];
423 u
[2] = p2
[2] - p1
[2];
425 v
[0] = p0
[0] - p1
[0];
426 v
[1] = p0
[1] - p1
[1];
427 v
[2] = p0
[2] - p1
[2];
429 n
[0] = u
[1] * v
[2] - u
[2] * v
[1];
430 n
[1] = u
[2] * v
[0] - u
[0] * v
[2];
431 n
[2] = u
[0] * v
[1] - u
[1] * v
[0];
433 d
= 1.0 / sqrt(n
[0] * n
[0] + n
[1] * n
[1] + n
[2] * n
[2]);
443 glVertex3fv(vertexes
[polygons
[i
][3]]);
444 glVertex3fv(vertexes
[polygons
[i
][4]]);
455 double majorStep
= (M_PI
/ numMajor
);
456 double minorStep
= (2.0 * M_PI
/ numMinor
);
459 glColor3f(0.50, 0.50, 0.50);
460 for (i
= 0; i
< numMajor
; ++i
) {
461 double a
= i
* majorStep
;
462 double b
= a
+ majorStep
;
463 double r0
= radius
* sin(a
);
464 double r1
= radius
* sin(b
);
465 GLfloat z0
= radius
* cos(a
);
466 GLfloat z1
= radius
* cos(b
);
468 glBegin(GL_TRIANGLE_STRIP
);
469 for (j
= 0; j
<= numMinor
; ++j
) {
470 double c
= j
* minorStep
;
474 glNormal3f((x
* r0
) / radius
, (y
* r0
) / radius
, z0
/ radius
);
475 glTexCoord2f(j
/ (GLfloat
) numMinor
, i
/ (GLfloat
) numMajor
);
476 glVertex3f(x
* r0
, y
* r0
, z0
);
478 glNormal3f((x
* r1
) / radius
, (y
* r1
) / radius
, z1
/ radius
);
479 glTexCoord2f(j
/ (GLfloat
) numMinor
, (i
+ 1) / (GLfloat
) numMajor
);
480 glVertex3f(x
* r1
, y
* r1
, z1
);
486 /*****************************************************************/
488 float xmin
= -0.035, xmax
= 0.035;
489 float ymin
= -0.035, ymax
= 0.035;
492 float distance
= -1.0;
495 loadTextureProjection(int texUnit
, GLfloat m
[16])
497 GLfloat mInverse
[4][4];
499 /* Should use true inverse, but since m consists only of rotations, we can
500 just use the transpose. */
501 matrixTranspose((GLfloat
*) mInverse
, m
);
503 ActiveTexture(GL_TEXTURE0_ARB
+ texUnit
);
504 glMatrixMode(GL_TEXTURE
);
506 glTranslatef(0.5, 0.5, 0.0);
507 glScalef(0.5, 0.5, 1.0);
508 glFrustum(xmin
, xmax
, ymin
, ymax
, nnear
, ffar
);
509 glTranslatef(0.0, 0.0, distance
);
510 glMultMatrixf((GLfloat
*) mInverse
);
511 glMatrixMode(GL_MODELVIEW
);
515 drawTextureProjection(void)
517 float t
= ffar
/ nnear
;
523 n
[0][2] = -(nnear
+ distance
);
527 n
[1][2] = -(nnear
+ distance
);
531 n
[2][2] = -(nnear
+ distance
);
535 n
[3][2] = -(nnear
+ distance
);
539 f
[0][2] = -(ffar
+ distance
);
543 f
[1][2] = -(ffar
+ distance
);
547 f
[2][2] = -(ffar
+ distance
);
551 f
[3][2] = -(ffar
+ distance
);
553 glColor3f(1.0, 1.0, 0.0);
554 glBegin(GL_LINE_LOOP
);
574 /*****************************************************************/
579 GLfloat light0Pos
[4] =
580 {0.3, 0.3, 0.0, 1.0};
582 {0.01, 0.01, 0.01, 1.00};
584 {0.65, 0.65, 0.65, 1.00};
586 {0.30, 0.30, 0.30, 1.00};
587 GLfloat matShine
= 10.0;
588 GLfloat eyePlaneS
[] =
589 {1.0, 0.0, 0.0, 0.0};
590 GLfloat eyePlaneT
[] =
591 {0.0, 1.0, 0.0, 0.0};
592 GLfloat eyePlaneR
[] =
593 {0.0, 0.0, 1.0, 0.0};
594 GLfloat eyePlaneQ
[] =
595 {0.0, 0.0, 0.0, 1.0};
599 glClearColor(0.41, 0.41, 0.31, 0.0);
601 glEnable(GL_DEPTH_TEST
);
603 /* glLineWidth(2.0);*/
605 glCullFace(GL_FRONT
);
606 glEnable(GL_CULL_FACE
);
608 glMatrixMode(GL_PROJECTION
);
609 glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
610 glMatrixMode(GL_MODELVIEW
);
611 glTranslatef(0, 0, -2);
613 matrixIdentity((GLfloat
*) objectXform
);
614 for (i
= 0; i
< NumTextures
; i
++) {
615 matrixIdentity((GLfloat
*) textureXform
[i
]);
618 glMatrixMode(GL_PROJECTION
);
621 glOrtho(0, 1, 0, 1, -1, 1);
622 glMatrixMode(GL_MODELVIEW
);
629 glMatrixMode(GL_PROJECTION
);
631 glMatrixMode(GL_MODELVIEW
);
634 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, matAmb
);
635 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, matDiff
);
636 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, matSpec
);
637 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, matShine
);
639 glEnable(GL_COLOR_MATERIAL
);
641 glLightfv(GL_LIGHT0
, GL_POSITION
, light0Pos
);
644 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
645 glEnable(GL_LIGHTING
);
652 for (i
= 0; i
< NumTextures
; i
++) {
653 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
655 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
656 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
657 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
659 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
660 glTexGenfv(GL_S
, GL_EYE_PLANE
, eyePlaneS
);
662 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
663 glTexGenfv(GL_T
, GL_EYE_PLANE
, eyePlaneT
);
665 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
666 glTexGenfv(GL_R
, GL_EYE_PLANE
, eyePlaneR
);
668 glTexGeni(GL_Q
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
669 glTexGenfv(GL_Q
, GL_EYE_PLANE
, eyePlaneQ
);
678 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
680 if (textureEnabled
) {
681 if (mode
== MoveTexture
|| mode
== MoveView
) {
682 /* Have OpenGL compute the new transformation (simple but slow). */
683 for (i
= 0; i
< NumTextures
; i
++) {
688 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
691 glRotatef(angle
*(i
+1), axis
[0], axis
[1], axis
[2]);
693 glMultMatrixf((GLfloat
*) textureXform
[i
]);
694 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) textureXform
[i
]);
698 for (i
= 0; i
< NumTextures
; i
++) {
699 loadTextureProjection(i
, (GLfloat
*) textureXform
[i
]);
702 if (showProjection
) {
703 for (i
= 0; i
< NumTextures
; i
++) {
704 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
706 glMultMatrixf((GLfloat
*) textureXform
[i
]);
707 glDisable(GL_LIGHTING
);
708 drawTextureProjection();
709 glEnable(GL_LIGHTING
);
713 for (i
= 0; i
< NumTextures
; i
++) {
714 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
715 glEnable(GL_TEXTURE_2D
);
716 glEnable(GL_TEXTURE_GEN_S
);
717 glEnable(GL_TEXTURE_GEN_T
);
718 glEnable(GL_TEXTURE_GEN_R
);
719 glEnable(GL_TEXTURE_GEN_Q
);
722 if (mode
== MoveObject
|| mode
== MoveView
) {
723 /* Have OpenGL compute the new transformation (simple but slow). */
726 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
727 glMultMatrixf((GLfloat
*) objectXform
);
728 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) objectXform
);
732 glMultMatrixf((GLfloat
*) objectXform
);
736 for (i
= 0; i
< NumTextures
; i
++) {
737 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
738 glDisable(GL_TEXTURE_2D
);
739 glDisable(GL_TEXTURE_GEN_S
);
740 glDisable(GL_TEXTURE_GEN_T
);
741 glDisable(GL_TEXTURE_GEN_R
);
742 glDisable(GL_TEXTURE_GEN_Q
);
745 if (zoomFactor
> 1.0) {
746 glDisable(GL_DEPTH_TEST
);
747 glCopyPixels(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
, GL_COLOR
);
748 glEnable(GL_DEPTH_TEST
);
755 /*****************************************************************/
757 /* simple trackball-like motion control */
762 ptov(int x
, int y
, int width
, int height
, float v
[3])
766 /* project x,y onto a hemi-sphere centered within width, height */
767 v
[0] = (2.0 * x
- width
) / width
;
768 v
[1] = (height
- 2.0 * y
) / height
;
769 d
= sqrt(v
[0] * v
[0] + v
[1] * v
[1]);
770 v
[2] = cos((M_PI
/ 2.0) * ((d
< 1.0) ? d
: 1.0));
771 a
= 1.0 / sqrt(v
[0] * v
[0] + v
[1] * v
[1] + v
[2] * v
[2]);
778 startMotion(int x
, int y
, int but
, int time
)
780 if (but
== GLUT_LEFT_BUTTON
) {
782 } else if (but
== GLUT_MIDDLE_BUTTON
) {
789 ptov(x
, y
, winWidth
, winHeight
, lastPos
);
801 if (visible
== GLUT_VISIBLE
) {
802 if (redrawContinuously
)
803 glutIdleFunc(animate
);
805 if (redrawContinuously
)
811 stopMotion(int but
, int time
)
813 if ((but
== GLUT_LEFT_BUTTON
&& mode
== MoveView
) ||
814 (but
== GLUT_MIDDLE_BUTTON
&& mode
== MoveTexture
)) {
819 if (time
== lastTime
) {
820 /* redrawContinuously = GL_TRUE;*/
821 glutIdleFunc(animate
);
824 redrawContinuously
= GL_FALSE
;
827 if (!redrawContinuously
) {
833 trackMotion(int x
, int y
)
835 float curPos
[3], dx
, dy
, dz
;
837 ptov(x
, y
, winWidth
, winHeight
, curPos
);
839 dx
= curPos
[0] - lastPos
[0];
840 dy
= curPos
[1] - lastPos
[1];
841 dz
= curPos
[2] - lastPos
[2];
842 angle
= 90.0 * sqrt(dx
* dx
+ dy
* dy
+ dz
* dz
);
844 axis
[0] = lastPos
[1] * curPos
[2] - lastPos
[2] * curPos
[1];
845 axis
[1] = lastPos
[2] * curPos
[0] - lastPos
[0] * curPos
[2];
846 axis
[2] = lastPos
[0] * curPos
[1] - lastPos
[1] * curPos
[0];
848 lastTime
= glutGet(GLUT_ELAPSED_TIME
);
849 lastPos
[0] = curPos
[0];
850 lastPos
[1] = curPos
[1];
851 lastPos
[2] = curPos
[2];
855 /*****************************************************************/
866 drawObject
= drawCube
;
869 drawObject
= drawDodecahedron
;
872 drawObject
= drawSphere
;
887 static int texture
= 0;
891 if (texture
== 1 && texFilename
== NULL
) {
892 /* Skip file texture if not loaded. */
898 textureEnabled
= GL_FALSE
;
901 loadTexture
= loadImageTextures
;
903 textureEnabled
= GL_TRUE
;
906 loadTexture
= loadSpotlightTexture
;
908 textureEnabled
= GL_TRUE
;
918 printf("'h' - help\n");
919 printf("'l' - toggle linear/nearest filter\n");
920 printf("'s' - toggle projection frustum\n");
921 printf("'t' - toggle projected texture\n");
922 printf("'o' - toggle object\n");
923 printf("'z' - increase zoom factor\n");
924 printf("'Z' - decrease zoom factor\n");
925 printf("left mouse - move view\n");
926 printf("middle mouse - move projection\n");
931 key(unsigned char key
, int x
, int y
)
938 linearFilter
= !linearFilter
;
942 showProjection
= !showProjection
;
952 glPixelZoom(zoomFactor
, zoomFactor
);
953 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
957 if (zoomFactor
< 1.0)
959 glPixelZoom(zoomFactor
, zoomFactor
);
960 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
970 mouse(int button
, int state
, int x
, int y
)
972 if (state
== GLUT_DOWN
)
973 startMotion(x
, y
, button
, glutGet(GLUT_ELAPSED_TIME
));
974 else if (state
== GLUT_UP
)
975 stopMotion(button
, glutGet(GLUT_ELAPSED_TIME
));
980 reshape(int w
, int h
)
984 glViewport(0, 0, w
/ zoomFactor
, h
/ zoomFactor
);
991 if (selection
== 666) {
994 key((unsigned char) selection
, 0, 0);
998 main(int argc
, char **argv
)
1000 glutInit(&argc
, argv
);
1003 NumTextures
= atoi(argv
[1]);
1005 assert(NumTextures
<= MAX_TEX
);
1007 glutInitDisplayMode(GLUT_RGBA
| GLUT_DEPTH
| GLUT_DOUBLE
);
1008 (void) glutCreateWindow("projtex");
1011 loadTexture
= loadImageTextures
;
1012 drawObject
= drawCube
;
1014 glutDisplayFunc(display
);
1015 glutKeyboardFunc(key
);
1016 glutReshapeFunc(reshape
);
1017 glutMouseFunc(mouse
);
1018 glutMotionFunc(trackMotion
);
1019 glutVisibilityFunc(vis
);
1020 glutCreateMenu(menu
);
1021 glutAddMenuEntry("Toggle showing projection", 's');
1022 glutAddMenuEntry("Switch texture", 't');
1023 glutAddMenuEntry("Switch object", 'o');
1024 glutAddMenuEntry("Toggle filtering", 'l');
1025 glutAddMenuEntry("Quit", 666);
1026 glutAttachMenu(GLUT_RIGHT_BUTTON
);
1029 return 0; /* ANSI C requires main to return int. */