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 /* 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
] = {
57 "../images/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
);
251 /* Create a simple spotlight pattern and make it the current texture */
253 loadSpotlightTexture(void)
255 static int texWidth
= 64, texHeight
= 64;
256 static GLubyte
*texData
;
257 GLfloat borderColor
[4] =
258 {0.1, 0.1, 0.1, 1.0};
264 texData
= (GLubyte
*) malloc(texWidth
* texHeight
* 4 * sizeof(GLubyte
));
267 for (j
= 0; j
< texHeight
; ++j
) {
268 float dy
= (texHeight
* 0.5 - j
+ 0.5) / (texHeight
* 0.5);
270 for (i
= 0; i
< texWidth
; ++i
) {
271 float dx
= (texWidth
* 0.5 - i
+ 0.5) / (texWidth
* 0.5);
272 float r
= cos(M_PI
/ 2.0 * sqrt(dx
* dx
+ dy
* dy
));
275 r
= (r
< 0) ? 0 : r
* r
;
276 c
= 0xff * (r
+ borderColor
[0]);
277 p
[0] = (c
<= 0xff) ? c
: 0xff;
278 c
= 0xff * (r
+ borderColor
[1]);
279 p
[1] = (c
<= 0xff) ? c
: 0xff;
280 c
= 0xff * (r
+ borderColor
[2]);
281 p
[2] = (c
<= 0xff) ? c
: 0xff;
282 c
= 0xff * (r
+ borderColor
[3]);
283 p
[3] = (c
<= 0xff) ? c
: 0xff;
289 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
290 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
292 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
293 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
295 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, borderColor
);
296 gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, texWidth
, texHeight
,
297 GL_RGBA
, GL_UNSIGNED_BYTE
, texData
);
300 /*****************************************************************/
306 while ((error
= glGetError()) != GL_NO_ERROR
) {
307 fprintf(stderr
, "Error: %s\n", (char *) gluErrorString(error
));
316 glNormal3f(-1.0, 0.0, 0.0);
317 glColor3f(0.80, 0.50, 0.50);
318 glVertex3f(-0.5, -0.5, -0.5);
319 glVertex3f(-0.5, -0.5, 0.5);
320 glVertex3f(-0.5, 0.5, 0.5);
321 glVertex3f(-0.5, 0.5, -0.5);
323 glNormal3f(1.0, 0.0, 0.0);
324 glColor3f(0.50, 0.80, 0.50);
325 glVertex3f(0.5, 0.5, 0.5);
326 glVertex3f(0.5, -0.5, 0.5);
327 glVertex3f(0.5, -0.5, -0.5);
328 glVertex3f(0.5, 0.5, -0.5);
330 glNormal3f(0.0, -1.0, 0.0);
331 glColor3f(0.50, 0.50, 0.80);
332 glVertex3f(-0.5, -0.5, -0.5);
333 glVertex3f(0.5, -0.5, -0.5);
334 glVertex3f(0.5, -0.5, 0.5);
335 glVertex3f(-0.5, -0.5, 0.5);
337 glNormal3f(0.0, 1.0, 0.0);
338 glColor3f(0.50, 0.80, 0.80);
339 glVertex3f(0.5, 0.5, 0.5);
340 glVertex3f(0.5, 0.5, -0.5);
341 glVertex3f(-0.5, 0.5, -0.5);
342 glVertex3f(-0.5, 0.5, 0.5);
344 glNormal3f(0.0, 0.0, -1.0);
345 glColor3f(0.80, 0.50, 0.80);
346 glVertex3f(-0.5, -0.5, -0.5);
347 glVertex3f(-0.5, 0.5, -0.5);
348 glVertex3f(0.5, 0.5, -0.5);
349 glVertex3f(0.5, -0.5, -0.5);
351 glNormal3f(0.0, 0.0, 1.0);
352 glColor3f(1.00, 0.80, 0.50);
353 glVertex3f(0.5, 0.5, 0.5);
354 glVertex3f(-0.5, 0.5, 0.5);
355 glVertex3f(-0.5, -0.5, 0.5);
356 glVertex3f(0.5, -0.5, 0.5);
361 drawDodecahedron(void)
363 #define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */
364 #define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */
365 #define C (0.5 * 1.0)
366 GLfloat vertexes
[20][3] =
392 GLint polygons
[12][5] =
409 glColor3f(0.75, 0.75, 0.75);
410 for (i
= 0; i
< 12; ++i
) {
411 GLfloat
*p0
, *p1
, *p2
, d
;
412 GLfloat u
[3], v
[3], n
[3];
414 p0
= &vertexes
[polygons
[i
][0]][0];
415 p1
= &vertexes
[polygons
[i
][1]][0];
416 p2
= &vertexes
[polygons
[i
][2]][0];
418 u
[0] = p2
[0] - p1
[0];
419 u
[1] = p2
[1] - p1
[1];
420 u
[2] = p2
[2] - p1
[2];
422 v
[0] = p0
[0] - p1
[0];
423 v
[1] = p0
[1] - p1
[1];
424 v
[2] = p0
[2] - p1
[2];
426 n
[0] = u
[1] * v
[2] - u
[2] * v
[1];
427 n
[1] = u
[2] * v
[0] - u
[0] * v
[2];
428 n
[2] = u
[0] * v
[1] - u
[1] * v
[0];
430 d
= 1.0 / sqrt(n
[0] * n
[0] + n
[1] * n
[1] + n
[2] * n
[2]);
440 glVertex3fv(vertexes
[polygons
[i
][3]]);
441 glVertex3fv(vertexes
[polygons
[i
][4]]);
452 double majorStep
= (M_PI
/ numMajor
);
453 double minorStep
= (2.0 * M_PI
/ numMinor
);
456 glColor3f(0.50, 0.50, 0.50);
457 for (i
= 0; i
< numMajor
; ++i
) {
458 double a
= i
* majorStep
;
459 double b
= a
+ majorStep
;
460 double r0
= radius
* sin(a
);
461 double r1
= radius
* sin(b
);
462 GLfloat z0
= radius
* cos(a
);
463 GLfloat z1
= radius
* cos(b
);
465 glBegin(GL_TRIANGLE_STRIP
);
466 for (j
= 0; j
<= numMinor
; ++j
) {
467 double c
= j
* minorStep
;
471 glNormal3f((x
* r0
) / radius
, (y
* r0
) / radius
, z0
/ radius
);
472 glTexCoord2f(j
/ (GLfloat
) numMinor
, i
/ (GLfloat
) numMajor
);
473 glVertex3f(x
* r0
, y
* r0
, z0
);
475 glNormal3f((x
* r1
) / radius
, (y
* r1
) / radius
, z1
/ radius
);
476 glTexCoord2f(j
/ (GLfloat
) numMinor
, (i
+ 1) / (GLfloat
) numMajor
);
477 glVertex3f(x
* r1
, y
* r1
, z1
);
483 /*****************************************************************/
485 float xmin
= -0.035, xmax
= 0.035;
486 float ymin
= -0.035, ymax
= 0.035;
489 float distance
= -1.0;
492 loadTextureProjection(int texUnit
, GLfloat m
[16])
494 GLfloat mInverse
[4][4];
496 /* Should use true inverse, but since m consists only of rotations, we can
497 just use the transpose. */
498 matrixTranspose((GLfloat
*) mInverse
, m
);
500 ActiveTexture(GL_TEXTURE0_ARB
+ texUnit
);
501 glMatrixMode(GL_TEXTURE
);
503 glTranslatef(0.5, 0.5, 0.0);
504 glScalef(0.5, 0.5, 1.0);
505 glFrustum(xmin
, xmax
, ymin
, ymax
, nnear
, ffar
);
506 glTranslatef(0.0, 0.0, distance
);
507 glMultMatrixf((GLfloat
*) mInverse
);
508 glMatrixMode(GL_MODELVIEW
);
512 drawTextureProjection(void)
514 float t
= ffar
/ nnear
;
520 n
[0][2] = -(nnear
+ distance
);
524 n
[1][2] = -(nnear
+ distance
);
528 n
[2][2] = -(nnear
+ distance
);
532 n
[3][2] = -(nnear
+ distance
);
536 f
[0][2] = -(ffar
+ distance
);
540 f
[1][2] = -(ffar
+ distance
);
544 f
[2][2] = -(ffar
+ distance
);
548 f
[3][2] = -(ffar
+ distance
);
550 glColor3f(1.0, 1.0, 0.0);
551 glBegin(GL_LINE_LOOP
);
571 /*****************************************************************/
576 GLfloat light0Pos
[4] =
577 {0.3, 0.3, 0.0, 1.0};
579 {0.01, 0.01, 0.01, 1.00};
581 {0.65, 0.65, 0.65, 1.00};
583 {0.30, 0.30, 0.30, 1.00};
584 GLfloat matShine
= 10.0;
585 GLfloat eyePlaneS
[] =
586 {1.0, 0.0, 0.0, 0.0};
587 GLfloat eyePlaneT
[] =
588 {0.0, 1.0, 0.0, 0.0};
589 GLfloat eyePlaneR
[] =
590 {0.0, 0.0, 1.0, 0.0};
591 GLfloat eyePlaneQ
[] =
592 {0.0, 0.0, 0.0, 1.0};
596 glClearColor(0.41, 0.41, 0.31, 0.0);
598 glEnable(GL_DEPTH_TEST
);
600 /* glLineWidth(2.0);*/
602 glCullFace(GL_FRONT
);
603 glEnable(GL_CULL_FACE
);
605 glMatrixMode(GL_PROJECTION
);
606 glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
607 glMatrixMode(GL_MODELVIEW
);
608 glTranslatef(0, 0, -2);
610 matrixIdentity((GLfloat
*) objectXform
);
611 for (i
= 0; i
< NumTextures
; i
++) {
612 matrixIdentity((GLfloat
*) textureXform
[i
]);
615 glMatrixMode(GL_PROJECTION
);
618 glOrtho(0, 1, 0, 1, -1, 1);
619 glMatrixMode(GL_MODELVIEW
);
626 glMatrixMode(GL_PROJECTION
);
628 glMatrixMode(GL_MODELVIEW
);
631 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, matAmb
);
632 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, matDiff
);
633 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, matSpec
);
634 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, matShine
);
636 glEnable(GL_COLOR_MATERIAL
);
638 glLightfv(GL_LIGHT0
, GL_POSITION
, light0Pos
);
641 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE
, GL_TRUE
);
642 glEnable(GL_LIGHTING
);
649 for (i
= 0; i
< NumTextures
; i
++) {
650 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
652 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
653 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
654 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
656 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
657 glTexGenfv(GL_S
, GL_EYE_PLANE
, eyePlaneS
);
659 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
660 glTexGenfv(GL_T
, GL_EYE_PLANE
, eyePlaneT
);
662 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
663 glTexGenfv(GL_R
, GL_EYE_PLANE
, eyePlaneR
);
665 glTexGeni(GL_Q
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
666 glTexGenfv(GL_Q
, GL_EYE_PLANE
, eyePlaneQ
);
675 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
677 if (textureEnabled
) {
678 if (mode
== MoveTexture
|| mode
== MoveView
) {
679 /* Have OpenGL compute the new transformation (simple but slow). */
680 for (i
= 0; i
< NumTextures
; i
++) {
685 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
688 glRotatef(angle
*(i
+1), axis
[0], axis
[1], axis
[2]);
690 glMultMatrixf((GLfloat
*) textureXform
[i
]);
691 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) textureXform
[i
]);
695 for (i
= 0; i
< NumTextures
; i
++) {
696 loadTextureProjection(i
, (GLfloat
*) textureXform
[i
]);
699 if (showProjection
) {
700 for (i
= 0; i
< NumTextures
; i
++) {
701 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
703 glMultMatrixf((GLfloat
*) textureXform
[i
]);
704 glDisable(GL_LIGHTING
);
705 drawTextureProjection();
706 glEnable(GL_LIGHTING
);
710 for (i
= 0; i
< NumTextures
; i
++) {
711 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
712 glEnable(GL_TEXTURE_2D
);
713 glEnable(GL_TEXTURE_GEN_S
);
714 glEnable(GL_TEXTURE_GEN_T
);
715 glEnable(GL_TEXTURE_GEN_R
);
716 glEnable(GL_TEXTURE_GEN_Q
);
719 if (mode
== MoveObject
|| mode
== MoveView
) {
720 /* Have OpenGL compute the new transformation (simple but slow). */
723 glRotatef(angle
, axis
[0], axis
[1], axis
[2]);
724 glMultMatrixf((GLfloat
*) objectXform
);
725 glGetFloatv(GL_MODELVIEW_MATRIX
, (GLfloat
*) objectXform
);
729 glMultMatrixf((GLfloat
*) objectXform
);
733 for (i
= 0; i
< NumTextures
; i
++) {
734 ActiveTexture(GL_TEXTURE0_ARB
+ i
);
735 glDisable(GL_TEXTURE_2D
);
736 glDisable(GL_TEXTURE_GEN_S
);
737 glDisable(GL_TEXTURE_GEN_T
);
738 glDisable(GL_TEXTURE_GEN_R
);
739 glDisable(GL_TEXTURE_GEN_Q
);
742 if (zoomFactor
> 1.0) {
743 glDisable(GL_DEPTH_TEST
);
744 glCopyPixels(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
, GL_COLOR
);
745 glEnable(GL_DEPTH_TEST
);
752 /*****************************************************************/
754 /* simple trackball-like motion control */
755 static float lastPos
[3];
759 ptov(int x
, int y
, int width
, int height
, float v
[3])
763 /* project x,y onto a hemi-sphere centered within width, height */
764 v
[0] = (2.0 * x
- width
) / width
;
765 v
[1] = (height
- 2.0 * y
) / height
;
766 d
= sqrt(v
[0] * v
[0] + v
[1] * v
[1]);
767 v
[2] = cos((M_PI
/ 2.0) * ((d
< 1.0) ? d
: 1.0));
768 a
= 1.0 / sqrt(v
[0] * v
[0] + v
[1] * v
[1] + v
[2] * v
[2]);
775 startMotion(int x
, int y
, int but
, int time
)
777 if (but
== GLUT_LEFT_BUTTON
) {
779 } else if (but
== GLUT_MIDDLE_BUTTON
) {
786 ptov(x
, y
, winWidth
, winHeight
, lastPos
);
798 if (visible
== GLUT_VISIBLE
) {
799 if (redrawContinuously
)
800 glutIdleFunc(animate
);
802 if (redrawContinuously
)
808 stopMotion(int but
, int time
)
810 if ((but
== GLUT_LEFT_BUTTON
&& mode
== MoveView
) ||
811 (but
== GLUT_MIDDLE_BUTTON
&& mode
== MoveTexture
)) {
816 if (time
== lastTime
) {
817 /* redrawContinuously = GL_TRUE;*/
818 glutIdleFunc(animate
);
821 redrawContinuously
= GL_FALSE
;
824 if (!redrawContinuously
) {
830 trackMotion(int x
, int y
)
832 float curPos
[3], dx
, dy
, dz
;
834 ptov(x
, y
, winWidth
, winHeight
, curPos
);
836 dx
= curPos
[0] - lastPos
[0];
837 dy
= curPos
[1] - lastPos
[1];
838 dz
= curPos
[2] - lastPos
[2];
839 angle
= 90.0 * sqrt(dx
* dx
+ dy
* dy
+ dz
* dz
);
841 axis
[0] = lastPos
[1] * curPos
[2] - lastPos
[2] * curPos
[1];
842 axis
[1] = lastPos
[2] * curPos
[0] - lastPos
[0] * curPos
[2];
843 axis
[2] = lastPos
[0] * curPos
[1] - lastPos
[1] * curPos
[0];
845 lastTime
= glutGet(GLUT_ELAPSED_TIME
);
846 lastPos
[0] = curPos
[0];
847 lastPos
[1] = curPos
[1];
848 lastPos
[2] = curPos
[2];
852 /*****************************************************************/
863 drawObject
= drawCube
;
866 drawObject
= drawDodecahedron
;
869 drawObject
= drawSphere
;
884 static int texture
= 0;
888 if (texture
== 1 && texFilename
== NULL
) {
889 /* Skip file texture if not loaded. */
895 textureEnabled
= GL_FALSE
;
898 loadTexture
= loadImageTextures
;
900 textureEnabled
= GL_TRUE
;
903 loadTexture
= loadSpotlightTexture
;
905 textureEnabled
= GL_TRUE
;
915 printf("'h' - help\n");
916 printf("'l' - toggle linear/nearest filter\n");
917 printf("'s' - toggle projection frustum\n");
918 printf("'t' - toggle projected texture\n");
919 printf("'o' - toggle object\n");
920 printf("'z' - increase zoom factor\n");
921 printf("'Z' - decrease zoom factor\n");
922 printf("left mouse - move view\n");
923 printf("middle mouse - move projection\n");
928 key(unsigned char key
, int x
, int y
)
935 linearFilter
= !linearFilter
;
939 showProjection
= !showProjection
;
949 glPixelZoom(zoomFactor
, zoomFactor
);
950 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
954 if (zoomFactor
< 1.0)
956 glPixelZoom(zoomFactor
, zoomFactor
);
957 glViewport(0, 0, winWidth
/ zoomFactor
, winHeight
/ zoomFactor
);
967 mouse(int button
, int state
, int x
, int y
)
969 if (state
== GLUT_DOWN
)
970 startMotion(x
, y
, button
, glutGet(GLUT_ELAPSED_TIME
));
971 else if (state
== GLUT_UP
)
972 stopMotion(button
, glutGet(GLUT_ELAPSED_TIME
));
977 reshape(int w
, int h
)
981 glViewport(0, 0, w
/ zoomFactor
, h
/ zoomFactor
);
988 if (selection
== 666) {
991 key((unsigned char) selection
, 0, 0);
995 main(int argc
, char **argv
)
997 glutInit(&argc
, argv
);
1000 NumTextures
= atoi(argv
[1]);
1002 assert(NumTextures
<= MAX_TEX
);
1004 glutInitDisplayMode(GLUT_RGBA
| GLUT_DEPTH
| GLUT_DOUBLE
);
1005 glutInitWindowSize(500,500);
1006 (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. */