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
22 #include "glut_wrap.h"
26 /* Some <math.h> files do not define M_PI... */
28 #define M_PI 3.14159265358979323846
34 int winWidth
, winHeight
;
36 GLboolean redrawContinuously
= GL_FALSE
;
40 MoveNone
, MoveView
, MoveObject
, MoveTexture
42 enum MoveModes mode
= MoveNone
;
44 GLfloat objectXform
[4][4];
45 GLfloat textureXform
[MAX_TEX
][4][4];
47 void (*drawObject
) (void);
48 void (*loadTexture
) (void);
49 GLboolean textureEnabled
= GL_TRUE
;
50 GLboolean showProjection
= GL_TRUE
;
51 GLboolean linearFilter
= GL_TRUE
;
53 char *texFilename
[MAX_TEX
] = {
54 DEMOS_DATA_DIR
"girl.rgb",
55 DEMOS_DATA_DIR
"tile.rgb",
56 DEMOS_DATA_DIR
"bw.rgb",
57 DEMOS_DATA_DIR
"reflect.rgb"
61 GLfloat zoomFactor
= 1.0;
63 /*****************************************************************/
69 glActiveTextureARB(i
);
73 /* matrix = identity */
75 matrixIdentity(GLfloat matrix
[16])
95 /* matrix2 = transpose(matrix1) */
97 matrixTranspose(GLfloat matrix2
[16], GLfloat matrix1
[16])
99 matrix2
[0] = matrix1
[0];
100 matrix2
[1] = matrix1
[4];
101 matrix2
[2] = matrix1
[8];
102 matrix2
[3] = matrix1
[12];
104 matrix2
[4] = matrix1
[1];
105 matrix2
[5] = matrix1
[5];
106 matrix2
[6] = matrix1
[9];
107 matrix2
[7] = matrix1
[13];
109 matrix2
[8] = matrix1
[2];
110 matrix2
[9] = matrix1
[6];
111 matrix2
[10] = matrix1
[10];
112 matrix2
[11] = matrix1
[14];
114 matrix2
[12] = matrix1
[3];
115 matrix2
[13] = matrix1
[7];
116 matrix2
[14] = matrix1
[14];
117 matrix2
[15] = matrix1
[15];
120 /*****************************************************************/
122 /* load SGI .rgb image (pad with a border of the specified width and color) */
125 imgLoad(char *filenameIn
, int borderIn
, GLfloat borderColorIn
[4],
126 int *wOut
, int *hOut
, GLubyte
** imgOut
)
128 int border
= borderIn
;
131 GLubyte
*image
, *img
, *p
;
132 int i
, j
, components
;
134 image
= (GLubyte
*) read_texture(filenameIn
, &width
, &height
, &components
);
135 w
= width
+ 2 * border
;
136 h
= height
+ 2 * border
;
137 img
= (GLubyte
*) calloc(w
* h
, 4 * sizeof(unsigned char));
140 for (j
= -border
; j
< height
+ border
; ++j
) {
141 for (i
= -border
; i
< width
+ border
; ++i
) {
142 if (0 <= j
&& j
<= height
- 1 && 0 <= i
&& i
<= width
- 1) {
143 p
[0] = image
[4 * (j
* width
+ i
) + 0];
144 p
[1] = image
[4 * (j
* width
+ i
) + 1];
145 p
[2] = image
[4 * (j
* width
+ i
) + 2];
148 p
[0] = borderColorIn
[0] * 0xff;
149 p
[1] = borderColorIn
[1] * 0xff;
150 p
[2] = borderColorIn
[2] * 0xff;
151 p
[3] = borderColorIn
[3] * 0xff;
164 /*****************************************************************/
166 /* Load the image file specified on the command line as the current texture */
168 loadImageTextures(void)
170 GLfloat borderColor
[4] =
171 {1.0, 1.0, 1.0, 1.0};
174 for (tex
= 0; tex
< NumTextures
; tex
++) {
175 GLubyte
*image
, *texData3
, *texData4
;
176 GLint imgWidth
, imgHeight
;
180 printf("loading %s\n", texFilename
[tex
]);
181 image
= LoadRGBImage(texFilename
[tex
], &imgWidth
, &imgHeight
, &imgFormat
);
183 printf("can't find %s\n", texFilename
[tex
]);
186 assert(imgFormat
== GL_RGB
);
188 /* scale to 256x256 */
189 texData3
= malloc(256 * 256 * 4);
190 texData4
= malloc(256 * 256 * 4);
193 gluScaleImage(imgFormat
, imgWidth
, imgHeight
, GL_UNSIGNED_BYTE
, image
,
194 256, 256, GL_UNSIGNED_BYTE
, texData3
);
196 /* convert to rgba */
197 for (i
= 0; i
< 256 * 256; i
++) {
198 texData4
[i
*4+0] = texData3
[i
*3+0];
199 texData4
[i
*4+1] = texData3
[i
*3+1];
200 texData4
[i
*4+2] = texData3
[i
*3+2];
201 texData4
[i
*4+3] = 128;
204 /* put transparent border around image */
205 for (i
= 0; i
< 256; i
++) {
206 texData4
[i
*4+0] = 255;
207 texData4
[i
*4+1] = 255;
208 texData4
[i
*4+2] = 255;
212 for (i
= 0; i
< 256; i
++) {
213 texData4
[j
+ i
*4+0] = 255;
214 texData4
[j
+ i
*4+1] = 255;
215 texData4
[j
+ i
*4+2] = 255;
216 texData4
[j
+ i
*4+3] = 0;
218 for (i
= 0; i
< 256; i
++) {
225 for (i
= 0; i
< 256; i
++) {
226 j
= i
* 256 * 4 + 255 * 4;
233 ActiveTexture(GL_TEXTURE0_ARB
+ tex
);
234 glBindTexture(GL_TEXTURE_2D
, tex
+ 1);
236 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
237 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 256, 256, 0,
238 GL_RGBA
, GL_UNSIGNED_BYTE
, texData4
);
241 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
242 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
244 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
245 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
247 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
255 /* Create a simple spotlight pattern and make it the current texture */
257 loadSpotlightTexture(void)
259 static int texWidth
= 64, texHeight
= 64;
260 static GLubyte
*texData
;
261 GLfloat borderColor
[4] =
262 {0.1, 0.1, 0.1, 1.0};
268 texData
= (GLubyte
*) malloc(texWidth
* texHeight
* 4 * sizeof(GLubyte
));
271 for (j
= 0; j
< texHeight
; ++j
) {
272 float dy
= (texHeight
* 0.5 - j
+ 0.5) / (texHeight
* 0.5);
274 for (i
= 0; i
< texWidth
; ++i
) {
275 float dx
= (texWidth
* 0.5 - i
+ 0.5) / (texWidth
* 0.5);
276 float r
= cos(M_PI
/ 2.0 * sqrt(dx
* dx
+ dy
* dy
));
279 r
= (r
< 0) ? 0 : r
* r
;
280 c
= 0xff * (r
+ borderColor
[0]);
281 p
[0] = (c
<= 0xff) ? c
: 0xff;
282 c
= 0xff * (r
+ borderColor
[1]);
283 p
[1] = (c
<= 0xff) ? c
: 0xff;
284 c
= 0xff * (r
+ borderColor
[2]);
285 p
[2] = (c
<= 0xff) ? c
: 0xff;
286 c
= 0xff * (r
+ borderColor
[3]);
287 p
[3] = (c
<= 0xff) ? c
: 0xff;
293 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
294 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
296 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
297 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
299 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
300 gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, texWidth
, texHeight
,
301 GL_RGBA
, GL_UNSIGNED_BYTE
, texData
);
304 /*****************************************************************/
310 while ((error
= glGetError()) != GL_NO_ERROR
) {
311 fprintf(stderr
, "Error: %s\n", (char *) gluErrorString(error
));
320 glNormal3f(-1.0, 0.0, 0.0);
321 glColor3f(0.80, 0.50, 0.50);
322 glVertex3f(-0.5, -0.5, -0.5);
323 glVertex3f(-0.5, -0.5, 0.5);
324 glVertex3f(-0.5, 0.5, 0.5);
325 glVertex3f(-0.5, 0.5, -0.5);
327 glNormal3f(1.0, 0.0, 0.0);
328 glColor3f(0.50, 0.80, 0.50);
329 glVertex3f(0.5, 0.5, 0.5);
330 glVertex3f(0.5, -0.5, 0.5);
331 glVertex3f(0.5, -0.5, -0.5);
332 glVertex3f(0.5, 0.5, -0.5);
334 glNormal3f(0.0, -1.0, 0.0);
335 glColor3f(0.50, 0.50, 0.80);
336 glVertex3f(-0.5, -0.5, -0.5);
337 glVertex3f(0.5, -0.5, -0.5);
338 glVertex3f(0.5, -0.5, 0.5);
339 glVertex3f(-0.5, -0.5, 0.5);
341 glNormal3f(0.0, 1.0, 0.0);
342 glColor3f(0.50, 0.80, 0.80);
343 glVertex3f(0.5, 0.5, 0.5);
344 glVertex3f(0.5, 0.5, -0.5);
345 glVertex3f(-0.5, 0.5, -0.5);
346 glVertex3f(-0.5, 0.5, 0.5);
348 glNormal3f(0.0, 0.0, -1.0);
349 glColor3f(0.80, 0.50, 0.80);
350 glVertex3f(-0.5, -0.5, -0.5);
351 glVertex3f(-0.5, 0.5, -0.5);
352 glVertex3f(0.5, 0.5, -0.5);
353 glVertex3f(0.5, -0.5, -0.5);
355 glNormal3f(0.0, 0.0, 1.0);
356 glColor3f(1.00, 0.80, 0.50);
357 glVertex3f(0.5, 0.5, 0.5);
358 glVertex3f(-0.5, 0.5, 0.5);
359 glVertex3f(-0.5, -0.5, 0.5);
360 glVertex3f(0.5, -0.5, 0.5);
365 drawDodecahedron(void)
367 #define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */
368 #define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */
369 #define C (0.5 * 1.0)
370 GLfloat vertexes
[20][3] =
396 GLint polygons
[12][5] =
413 glColor3f(0.75, 0.75, 0.75);
414 for (i
= 0; i
< 12; ++i
) {
415 GLfloat
*p0
, *p1
, *p2
, d
;
416 GLfloat u
[3], v
[3], n
[3];
418 p0
= &vertexes
[polygons
[i
][0]][0];
419 p1
= &vertexes
[polygons
[i
][1]][0];
420 p2
= &vertexes
[polygons
[i
][2]][0];
422 u
[0] = p2
[0] - p1
[0];
423 u
[1] = p2
[1] - p1
[1];
424 u
[2] = p2
[2] - p1
[2];
426 v
[0] = p0
[0] - p1
[0];
427 v
[1] = p0
[1] - p1
[1];
428 v
[2] = p0
[2] - p1
[2];
430 n
[0] = u
[1] * v
[2] - u
[2] * v
[1];
431 n
[1] = u
[2] * v
[0] - u
[0] * v
[2];
432 n
[2] = u
[0] * v
[1] - u
[1] * v
[0];
434 d
= 1.0 / sqrt(n
[0] * n
[0] + n
[1] * n
[1] + n
[2] * n
[2]);
444 glVertex3fv(vertexes
[polygons
[i
][3]]);
445 glVertex3fv(vertexes
[polygons
[i
][4]]);
456 double majorStep
= (M_PI
/ numMajor
);
457 double minorStep
= (2.0 * M_PI
/ numMinor
);
460 glColor3f(0.50, 0.50, 0.50);
461 for (i
= 0; i
< numMajor
; ++i
) {
462 double a
= i
* majorStep
;
463 double b
= a
+ majorStep
;
464 double r0
= radius
* sin(a
);
465 double r1
= radius
* sin(b
);
466 GLfloat z0
= radius
* cos(a
);
467 GLfloat z1
= radius
* cos(b
);
469 glBegin(GL_TRIANGLE_STRIP
);
470 for (j
= 0; j
<= numMinor
; ++j
) {
471 double c
= j
* minorStep
;
475 glNormal3f((x
* r0
) / radius
, (y
* r0
) / radius
, z0
/ radius
);
476 glTexCoord2f(j
/ (GLfloat
) numMinor
, i
/ (GLfloat
) numMajor
);
477 glVertex3f(x
* r0
, y
* r0
, z0
);
479 glNormal3f((x
* r1
) / radius
, (y
* r1
) / radius
, z1
/ radius
);
480 glTexCoord2f(j
/ (GLfloat
) numMinor
, (i
+ 1) / (GLfloat
) numMajor
);
481 glVertex3f(x
* r1
, y
* r1
, z1
);
487 /*****************************************************************/
489 float xmin
= -0.035, xmax
= 0.035;
490 float ymin
= -0.035, ymax
= 0.035;
493 float distance
= -1.0;
496 loadTextureProjection(int texUnit
, GLfloat m
[16])
498 GLfloat mInverse
[4][4];
500 /* Should use true inverse, but since m consists only of rotations, we can
501 just use the transpose. */
502 matrixTranspose((GLfloat
*) mInverse
, m
);
504 ActiveTexture(GL_TEXTURE0_ARB
+ texUnit
);
505 glMatrixMode(GL_TEXTURE
);
507 glTranslatef(0.5, 0.5, 0.0);
508 glScalef(0.5, 0.5, 1.0);
509 glFrustum(xmin
, xmax
, ymin
, ymax
, nnear
, ffar
);
510 glTranslatef(0.0, 0.0, distance
);
511 glMultMatrixf((GLfloat
*) mInverse
);
512 glMatrixMode(GL_MODELVIEW
);
516 drawTextureProjection(void)
518 float t
= ffar
/ nnear
;
524 n
[0][2] = -(nnear
+ distance
);
528 n
[1][2] = -(nnear
+ distance
);
532 n
[2][2] = -(nnear
+ distance
);
536 n
[3][2] = -(nnear
+ distance
);
540 f
[0][2] = -(ffar
+ distance
);
544 f
[1][2] = -(ffar
+ distance
);
548 f
[2][2] = -(ffar
+ distance
);
552 f
[3][2] = -(ffar
+ distance
);
554 glColor3f(1.0, 1.0, 0.0);
555 glBegin(GL_LINE_LOOP
);
575 /*****************************************************************/
580 GLfloat light0Pos
[4] =
581 {0.3, 0.3, 0.0, 1.0};
583 {0.01, 0.01, 0.01, 1.00};
585 {0.65, 0.65, 0.65, 1.00};
587 {0.30, 0.30, 0.30, 1.00};
588 GLfloat matShine
= 10.0;
589 GLfloat eyePlaneS
[] =
590 {1.0, 0.0, 0.0, 0.0};
591 GLfloat eyePlaneT
[] =
592 {0.0, 1.0, 0.0, 0.0};
593 GLfloat eyePlaneR
[] =
594 {0.0, 0.0, 1.0, 0.0};
595 GLfloat eyePlaneQ
[] =
596 {0.0, 0.0, 0.0, 1.0};
600 glClearColor(0.41, 0.41, 0.31, 0.0);
602 glEnable(GL_DEPTH_TEST
);
604 /* glLineWidth(2.0);*/
606 glCullFace(GL_FRONT
);
607 glEnable(GL_CULL_FACE
);
609 glMatrixMode(GL_PROJECTION
);
610 glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
611 glMatrixMode(GL_MODELVIEW
);
612 glTranslatef(0, 0, -2);
614 matrixIdentity((GLfloat
*) objectXform
);
615 for (i
= 0; i
< NumTextures
; i
++) {
616 matrixIdentity((GLfloat
*) textureXform
[i
]);
619 glMatrixMode(GL_PROJECTION
);
622 glOrtho(0, 1, 0, 1, -1, 1);
623 glMatrixMode(GL_MODELVIEW
);
630 glMatrixMode(GL_PROJECTION
);
632 glMatrixMode(GL_MODELVIEW
);
635 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, matAmb
);
636 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, matDiff
);
637 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, matSpec
);
638 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, matShine
);
640 glEnable(GL_COLOR_MATERIAL
);
642 glLightfv(GL_LIGHT0
, GL_POSITION
, light0Pos
);
645 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
646 glEnable(GL_LIGHTING
);
653 for (i
= 0; i
< NumTextures
; i
++) {
654 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
656 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
657 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
658 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
660 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
661 glTexGenfv(GL_S
, GL_EYE_PLANE
, eyePlaneS
);
663 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
664 glTexGenfv(GL_T
, GL_EYE_PLANE
, eyePlaneT
);
666 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
667 glTexGenfv(GL_R
, GL_EYE_PLANE
, eyePlaneR
);
669 glTexGeni(GL_Q
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
670 glTexGenfv(GL_Q
, GL_EYE_PLANE
, eyePlaneQ
);
679 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
681 if (textureEnabled
) {
682 if (mode
== MoveTexture
|| mode
== MoveView
) {
683 /* Have OpenGL compute the new transformation (simple but slow). */
684 for (i
= 0; i
< NumTextures
; i
++) {
689 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
692 glRotatef(angle
*(i
+1), axis
[0], axis
[1], axis
[2]);
694 glMultMatrixf((GLfloat
*) textureXform
[i
]);
695 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) textureXform
[i
]);
699 for (i
= 0; i
< NumTextures
; i
++) {
700 loadTextureProjection(i
, (GLfloat
*) textureXform
[i
]);
703 if (showProjection
) {
704 for (i
= 0; i
< NumTextures
; i
++) {
705 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
707 glMultMatrixf((GLfloat
*) textureXform
[i
]);
708 glDisable(GL_LIGHTING
);
709 drawTextureProjection();
710 glEnable(GL_LIGHTING
);
714 for (i
= 0; i
< NumTextures
; i
++) {
715 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
716 glEnable(GL_TEXTURE_2D
);
717 glEnable(GL_TEXTURE_GEN_S
);
718 glEnable(GL_TEXTURE_GEN_T
);
719 glEnable(GL_TEXTURE_GEN_R
);
720 glEnable(GL_TEXTURE_GEN_Q
);
723 if (mode
== MoveObject
|| mode
== MoveView
) {
724 /* Have OpenGL compute the new transformation (simple but slow). */
727 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
728 glMultMatrixf((GLfloat
*) objectXform
);
729 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) objectXform
);
733 glMultMatrixf((GLfloat
*) objectXform
);
737 for (i
= 0; i
< NumTextures
; i
++) {
738 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
739 glDisable(GL_TEXTURE_2D
);
740 glDisable(GL_TEXTURE_GEN_S
);
741 glDisable(GL_TEXTURE_GEN_T
);
742 glDisable(GL_TEXTURE_GEN_R
);
743 glDisable(GL_TEXTURE_GEN_Q
);
746 if (zoomFactor
> 1.0) {
747 glDisable(GL_DEPTH_TEST
);
748 glCopyPixels(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
, GL_COLOR
);
749 glEnable(GL_DEPTH_TEST
);
756 /*****************************************************************/
758 /* simple trackball-like motion control */
759 static float lastPos
[3];
763 ptov(int x
, int y
, int width
, int height
, float v
[3])
767 /* project x,y onto a hemi-sphere centered within width, height */
768 v
[0] = (2.0 * x
- width
) / width
;
769 v
[1] = (height
- 2.0 * y
) / height
;
770 d
= sqrt(v
[0] * v
[0] + v
[1] * v
[1]);
771 v
[2] = cos((M_PI
/ 2.0) * ((d
< 1.0) ? d
: 1.0));
772 a
= 1.0 / sqrt(v
[0] * v
[0] + v
[1] * v
[1] + v
[2] * v
[2]);
779 startMotion(int x
, int y
, int but
, int time
)
781 if (but
== GLUT_LEFT_BUTTON
) {
783 } else if (but
== GLUT_MIDDLE_BUTTON
) {
790 ptov(x
, y
, winWidth
, winHeight
, lastPos
);
802 if (visible
== GLUT_VISIBLE
) {
803 if (redrawContinuously
)
804 glutIdleFunc(animate
);
806 if (redrawContinuously
)
812 stopMotion(int but
, int time
)
814 if ((but
== GLUT_LEFT_BUTTON
&& mode
== MoveView
) ||
815 (but
== GLUT_MIDDLE_BUTTON
&& mode
== MoveTexture
)) {
820 if (time
== lastTime
) {
821 /* redrawContinuously = GL_TRUE;*/
822 glutIdleFunc(animate
);
825 redrawContinuously
= GL_FALSE
;
828 if (!redrawContinuously
) {
834 trackMotion(int x
, int y
)
836 float curPos
[3], dx
, dy
, dz
;
838 ptov(x
, y
, winWidth
, winHeight
, curPos
);
840 dx
= curPos
[0] - lastPos
[0];
841 dy
= curPos
[1] - lastPos
[1];
842 dz
= curPos
[2] - lastPos
[2];
843 angle
= 90.0 * sqrt(dx
* dx
+ dy
* dy
+ dz
* dz
);
845 axis
[0] = lastPos
[1] * curPos
[2] - lastPos
[2] * curPos
[1];
846 axis
[1] = lastPos
[2] * curPos
[0] - lastPos
[0] * curPos
[2];
847 axis
[2] = lastPos
[0] * curPos
[1] - lastPos
[1] * curPos
[0];
849 lastTime
= glutGet(GLUT_ELAPSED_TIME
);
850 lastPos
[0] = curPos
[0];
851 lastPos
[1] = curPos
[1];
852 lastPos
[2] = curPos
[2];
856 /*****************************************************************/
867 drawObject
= drawCube
;
870 drawObject
= drawDodecahedron
;
873 drawObject
= drawSphere
;
888 static int texture
= 0;
892 if (texture
== 1 && texFilename
== NULL
) {
893 /* Skip file texture if not loaded. */
899 textureEnabled
= GL_FALSE
;
902 loadTexture
= loadImageTextures
;
904 textureEnabled
= GL_TRUE
;
907 loadTexture
= loadSpotlightTexture
;
909 textureEnabled
= GL_TRUE
;
919 printf("'h' - help\n");
920 printf("'l' - toggle linear/nearest filter\n");
921 printf("'s' - toggle projection frustum\n");
922 printf("'t' - toggle projected texture\n");
923 printf("'o' - toggle object\n");
924 printf("'z' - increase zoom factor\n");
925 printf("'Z' - decrease zoom factor\n");
926 printf("left mouse - move view\n");
927 printf("middle mouse - move projection\n");
932 key(unsigned char key
, int x
, int y
)
939 linearFilter
= !linearFilter
;
943 showProjection
= !showProjection
;
953 glPixelZoom(zoomFactor
, zoomFactor
);
954 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
958 if (zoomFactor
< 1.0)
960 glPixelZoom(zoomFactor
, zoomFactor
);
961 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
971 mouse(int button
, int state
, int x
, int y
)
973 if (state
== GLUT_DOWN
)
974 startMotion(x
, y
, button
, glutGet(GLUT_ELAPSED_TIME
));
975 else if (state
== GLUT_UP
)
976 stopMotion(button
, glutGet(GLUT_ELAPSED_TIME
));
981 reshape(int w
, int h
)
985 glViewport(0, 0, w
/ zoomFactor
, h
/ zoomFactor
);
992 if (selection
== 666) {
995 key((unsigned char) selection
, 0, 0);
999 main(int argc
, char **argv
)
1001 glutInitWindowSize(500,500);
1002 glutInit(&argc
, argv
);
1003 glutInitDisplayMode(GLUT_RGBA
| GLUT_DEPTH
| GLUT_DOUBLE
);
1004 (void) glutCreateWindow("projtex");
1008 NumTextures
= atoi(argv
[1]);
1010 assert(NumTextures
<= MAX_TEX
);
1012 loadTexture
= loadImageTextures
;
1013 drawObject
= drawCube
;
1015 glutDisplayFunc(display
);
1016 glutKeyboardFunc(key
);
1017 glutReshapeFunc(reshape
);
1018 glutMouseFunc(mouse
);
1019 glutMotionFunc(trackMotion
);
1020 glutVisibilityFunc(vis
);
1021 glutCreateMenu(menu
);
1022 glutAddMenuEntry("Toggle showing projection", 's');
1023 glutAddMenuEntry("Switch texture", 't');
1024 glutAddMenuEntry("Switch object", 'o');
1025 glutAddMenuEntry("Toggle filtering", 'l');
1026 glutAddMenuEntry("Quit", 666);
1027 glutAttachMenu(GLUT_RIGHT_BUTTON
);
1030 return 0; /* ANSI C requires main to return int. */