Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

projtex.c 24KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. /* projtex.c - by David Yu and David Blythe, SGI */
  2. /**
  3. ** Demonstrates simple projective texture mapping.
  4. **
  5. ** Button1 changes view, Button2 moves texture.
  6. **
  7. ** (See: Segal, Korobkin, van Widenfelt, Foran, and Haeberli
  8. ** "Fast Shadows and Lighting Effects Using Texture Mapping", SIGGRAPH '92)
  9. **
  10. ** 1994,1995 -- David G Yu
  11. **
  12. ** cc -o projtex projtex.c texture.c -lglut -lGLU -lGL -lX11 -lm
  13. **/
  14. #include <assert.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <math.h>
  18. #include <GL/glew.h>
  19. #include <GL/glut.h>
  20. #include "readtex.h"
  21. /* Some <math.h> files do not define M_PI... */
  22. #ifndef M_PI
  23. #define M_PI 3.14159265358979323846
  24. #endif
  25. #define MAX_TEX 4
  26. int NumTextures = 1;
  27. int winWidth, winHeight;
  28. GLboolean redrawContinuously = GL_FALSE;
  29. float angle, axis[3];
  30. enum MoveModes {
  31. MoveNone, MoveView, MoveObject, MoveTexture
  32. };
  33. enum MoveModes mode = MoveNone;
  34. GLfloat objectXform[4][4];
  35. GLfloat textureXform[MAX_TEX][4][4];
  36. void (*drawObject) (void);
  37. void (*loadTexture) (void);
  38. GLboolean textureEnabled = GL_TRUE;
  39. GLboolean showProjection = GL_TRUE;
  40. GLboolean linearFilter = GL_TRUE;
  41. char *texFilename[MAX_TEX] = {
  42. "../images/girl.rgb",
  43. "../images/tile.rgb",
  44. "../images/bw.rgb",
  45. "../images/reflect.rgb"
  46. };
  47. GLfloat zoomFactor = 1.0;
  48. /*****************************************************************/
  49. static void
  50. ActiveTexture(int i)
  51. {
  52. glActiveTextureARB(i);
  53. }
  54. /* matrix = identity */
  55. static void
  56. matrixIdentity(GLfloat matrix[16])
  57. {
  58. matrix[0] = 1.0;
  59. matrix[1] = 0.0;
  60. matrix[2] = 0.0;
  61. matrix[3] = 0.0;
  62. matrix[4] = 0.0;
  63. matrix[5] = 1.0;
  64. matrix[6] = 0.0;
  65. matrix[7] = 0.0;
  66. matrix[8] = 0.0;
  67. matrix[9] = 0.0;
  68. matrix[10] = 1.0;
  69. matrix[11] = 0.0;
  70. matrix[12] = 0.0;
  71. matrix[13] = 0.0;
  72. matrix[14] = 0.0;
  73. matrix[15] = 1.0;
  74. }
  75. /* matrix2 = transpose(matrix1) */
  76. static void
  77. matrixTranspose(GLfloat matrix2[16], GLfloat matrix1[16])
  78. {
  79. matrix2[0] = matrix1[0];
  80. matrix2[1] = matrix1[4];
  81. matrix2[2] = matrix1[8];
  82. matrix2[3] = matrix1[12];
  83. matrix2[4] = matrix1[1];
  84. matrix2[5] = matrix1[5];
  85. matrix2[6] = matrix1[9];
  86. matrix2[7] = matrix1[13];
  87. matrix2[8] = matrix1[2];
  88. matrix2[9] = matrix1[6];
  89. matrix2[10] = matrix1[10];
  90. matrix2[11] = matrix1[14];
  91. matrix2[12] = matrix1[3];
  92. matrix2[13] = matrix1[7];
  93. matrix2[14] = matrix1[14];
  94. matrix2[15] = matrix1[15];
  95. }
  96. /*****************************************************************/
  97. /* load SGI .rgb image (pad with a border of the specified width and color) */
  98. #if 0
  99. static void
  100. imgLoad(char *filenameIn, int borderIn, GLfloat borderColorIn[4],
  101. int *wOut, int *hOut, GLubyte ** imgOut)
  102. {
  103. int border = borderIn;
  104. int width, height;
  105. int w, h;
  106. GLubyte *image, *img, *p;
  107. int i, j, components;
  108. image = (GLubyte *) read_texture(filenameIn, &width, &height, &components);
  109. w = width + 2 * border;
  110. h = height + 2 * border;
  111. img = (GLubyte *) calloc(w * h, 4 * sizeof(unsigned char));
  112. p = img;
  113. for (j = -border; j < height + border; ++j) {
  114. for (i = -border; i < width + border; ++i) {
  115. if (0 <= j && j <= height - 1 && 0 <= i && i <= width - 1) {
  116. p[0] = image[4 * (j * width + i) + 0];
  117. p[1] = image[4 * (j * width + i) + 1];
  118. p[2] = image[4 * (j * width + i) + 2];
  119. p[3] = 0xff;
  120. } else {
  121. p[0] = borderColorIn[0] * 0xff;
  122. p[1] = borderColorIn[1] * 0xff;
  123. p[2] = borderColorIn[2] * 0xff;
  124. p[3] = borderColorIn[3] * 0xff;
  125. }
  126. p += 4;
  127. }
  128. }
  129. free(image);
  130. *wOut = w;
  131. *hOut = h;
  132. *imgOut = img;
  133. }
  134. #endif
  135. /*****************************************************************/
  136. /* Load the image file specified on the command line as the current texture */
  137. static void
  138. loadImageTextures(void)
  139. {
  140. GLfloat borderColor[4] =
  141. {1.0, 1.0, 1.0, 1.0};
  142. int tex;
  143. for (tex = 0; tex < NumTextures; tex++) {
  144. GLubyte *image, *texData3, *texData4;
  145. GLint imgWidth, imgHeight;
  146. GLenum imgFormat;
  147. int i, j;
  148. printf("loading %s\n", texFilename[tex]);
  149. image = LoadRGBImage(texFilename[tex], &imgWidth, &imgHeight, &imgFormat);
  150. if (!image) {
  151. printf("can't find %s\n", texFilename[tex]);
  152. exit(1);
  153. }
  154. assert(imgFormat == GL_RGB);
  155. /* scale to 256x256 */
  156. texData3 = malloc(256 * 256 * 4);
  157. texData4 = malloc(256 * 256 * 4);
  158. assert(texData3);
  159. assert(texData4);
  160. gluScaleImage(imgFormat, imgWidth, imgHeight, GL_UNSIGNED_BYTE, image,
  161. 256, 256, GL_UNSIGNED_BYTE, texData3);
  162. /* convert to rgba */
  163. for (i = 0; i < 256 * 256; i++) {
  164. texData4[i*4+0] = texData3[i*3+0];
  165. texData4[i*4+1] = texData3[i*3+1];
  166. texData4[i*4+2] = texData3[i*3+2];
  167. texData4[i*4+3] = 128;
  168. }
  169. /* put transparent border around image */
  170. for (i = 0; i < 256; i++) {
  171. texData4[i*4+0] = 255;
  172. texData4[i*4+1] = 255;
  173. texData4[i*4+2] = 255;
  174. texData4[i*4+3] = 0;
  175. }
  176. j = 256 * 255 * 4;
  177. for (i = 0; i < 256; i++) {
  178. texData4[j + i*4+0] = 255;
  179. texData4[j + i*4+1] = 255;
  180. texData4[j + i*4+2] = 255;
  181. texData4[j + i*4+3] = 0;
  182. }
  183. for (i = 0; i < 256; i++) {
  184. j = i * 256 * 4;
  185. texData4[j+0] = 255;
  186. texData4[j+1] = 255;
  187. texData4[j+2] = 255;
  188. texData4[j+3] = 0;
  189. }
  190. for (i = 0; i < 256; i++) {
  191. j = i * 256 * 4 + 255 * 4;
  192. texData4[j+0] = 255;
  193. texData4[j+1] = 255;
  194. texData4[j+2] = 255;
  195. texData4[j+3] = 0;
  196. }
  197. ActiveTexture(GL_TEXTURE0_ARB + tex);
  198. glBindTexture(GL_TEXTURE_2D, tex + 1);
  199. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  200. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
  201. GL_RGBA, GL_UNSIGNED_BYTE, texData4);
  202. if (linearFilter) {
  203. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  204. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  205. } else {
  206. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  207. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  208. }
  209. glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
  210. free(texData3);
  211. free(texData4);
  212. free(image);
  213. }
  214. }
  215. /* Create a simple spotlight pattern and make it the current texture */
  216. static void
  217. loadSpotlightTexture(void)
  218. {
  219. static int texWidth = 64, texHeight = 64;
  220. static GLubyte *texData;
  221. GLfloat borderColor[4] =
  222. {0.1, 0.1, 0.1, 1.0};
  223. if (!texData) {
  224. GLubyte *p;
  225. int i, j;
  226. texData = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
  227. p = texData;
  228. for (j = 0; j < texHeight; ++j) {
  229. float dy = (texHeight * 0.5 - j + 0.5) / (texHeight * 0.5);
  230. for (i = 0; i < texWidth; ++i) {
  231. float dx = (texWidth * 0.5 - i + 0.5) / (texWidth * 0.5);
  232. float r = cos(M_PI / 2.0 * sqrt(dx * dx + dy * dy));
  233. float c;
  234. r = (r < 0) ? 0 : r * r;
  235. c = 0xff * (r + borderColor[0]);
  236. p[0] = (c <= 0xff) ? c : 0xff;
  237. c = 0xff * (r + borderColor[1]);
  238. p[1] = (c <= 0xff) ? c : 0xff;
  239. c = 0xff * (r + borderColor[2]);
  240. p[2] = (c <= 0xff) ? c : 0xff;
  241. c = 0xff * (r + borderColor[3]);
  242. p[3] = (c <= 0xff) ? c : 0xff;
  243. p += 4;
  244. }
  245. }
  246. }
  247. if (linearFilter) {
  248. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  249. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  250. } else {
  251. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  252. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  253. }
  254. glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
  255. gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
  256. GL_RGBA, GL_UNSIGNED_BYTE, texData);
  257. }
  258. /*****************************************************************/
  259. static void
  260. checkErrors(void)
  261. {
  262. GLenum error;
  263. while ((error = glGetError()) != GL_NO_ERROR) {
  264. fprintf(stderr, "Error: %s\n", (char *) gluErrorString(error));
  265. }
  266. }
  267. static void
  268. drawCube(void)
  269. {
  270. glBegin(GL_QUADS);
  271. glNormal3f(-1.0, 0.0, 0.0);
  272. glColor3f(0.80, 0.50, 0.50);
  273. glVertex3f(-0.5, -0.5, -0.5);
  274. glVertex3f(-0.5, -0.5, 0.5);
  275. glVertex3f(-0.5, 0.5, 0.5);
  276. glVertex3f(-0.5, 0.5, -0.5);
  277. glNormal3f(1.0, 0.0, 0.0);
  278. glColor3f(0.50, 0.80, 0.50);
  279. glVertex3f(0.5, 0.5, 0.5);
  280. glVertex3f(0.5, -0.5, 0.5);
  281. glVertex3f(0.5, -0.5, -0.5);
  282. glVertex3f(0.5, 0.5, -0.5);
  283. glNormal3f(0.0, -1.0, 0.0);
  284. glColor3f(0.50, 0.50, 0.80);
  285. glVertex3f(-0.5, -0.5, -0.5);
  286. glVertex3f(0.5, -0.5, -0.5);
  287. glVertex3f(0.5, -0.5, 0.5);
  288. glVertex3f(-0.5, -0.5, 0.5);
  289. glNormal3f(0.0, 1.0, 0.0);
  290. glColor3f(0.50, 0.80, 0.80);
  291. glVertex3f(0.5, 0.5, 0.5);
  292. glVertex3f(0.5, 0.5, -0.5);
  293. glVertex3f(-0.5, 0.5, -0.5);
  294. glVertex3f(-0.5, 0.5, 0.5);
  295. glNormal3f(0.0, 0.0, -1.0);
  296. glColor3f(0.80, 0.50, 0.80);
  297. glVertex3f(-0.5, -0.5, -0.5);
  298. glVertex3f(-0.5, 0.5, -0.5);
  299. glVertex3f(0.5, 0.5, -0.5);
  300. glVertex3f(0.5, -0.5, -0.5);
  301. glNormal3f(0.0, 0.0, 1.0);
  302. glColor3f(1.00, 0.80, 0.50);
  303. glVertex3f(0.5, 0.5, 0.5);
  304. glVertex3f(-0.5, 0.5, 0.5);
  305. glVertex3f(-0.5, -0.5, 0.5);
  306. glVertex3f(0.5, -0.5, 0.5);
  307. glEnd();
  308. }
  309. static void
  310. drawDodecahedron(void)
  311. {
  312. #define A (0.5 * 1.61803) /* (sqrt(5) + 1) / 2 */
  313. #define B (0.5 * 0.61803) /* (sqrt(5) - 1) / 2 */
  314. #define C (0.5 * 1.0)
  315. GLfloat vertexes[20][3] =
  316. {
  317. {-A, 0.0, B},
  318. {-A, 0.0, -B},
  319. {A, 0.0, -B},
  320. {A, 0.0, B},
  321. {B, -A, 0.0},
  322. {-B, -A, 0.0},
  323. {-B, A, 0.0},
  324. {B, A, 0.0},
  325. {0.0, B, -A},
  326. {0.0, -B, -A},
  327. {0.0, -B, A},
  328. {0.0, B, A},
  329. {-C, -C, C},
  330. {-C, -C, -C},
  331. {C, -C, -C},
  332. {C, -C, C},
  333. {-C, C, C},
  334. {-C, C, -C},
  335. {C, C, -C},
  336. {C, C, C},
  337. };
  338. #undef A
  339. #undef B
  340. #undef C
  341. GLint polygons[12][5] =
  342. {
  343. {0, 12, 10, 11, 16},
  344. {1, 17, 8, 9, 13},
  345. {2, 14, 9, 8, 18},
  346. {3, 19, 11, 10, 15},
  347. {4, 14, 2, 3, 15},
  348. {5, 12, 0, 1, 13},
  349. {6, 17, 1, 0, 16},
  350. {7, 19, 3, 2, 18},
  351. {8, 17, 6, 7, 18},
  352. {9, 14, 4, 5, 13},
  353. {10, 12, 5, 4, 15},
  354. {11, 19, 7, 6, 16},
  355. };
  356. int i;
  357. glColor3f(0.75, 0.75, 0.75);
  358. for (i = 0; i < 12; ++i) {
  359. GLfloat *p0, *p1, *p2, d;
  360. GLfloat u[3], v[3], n[3];
  361. p0 = &vertexes[polygons[i][0]][0];
  362. p1 = &vertexes[polygons[i][1]][0];
  363. p2 = &vertexes[polygons[i][2]][0];
  364. u[0] = p2[0] - p1[0];
  365. u[1] = p2[1] - p1[1];
  366. u[2] = p2[2] - p1[2];
  367. v[0] = p0[0] - p1[0];
  368. v[1] = p0[1] - p1[1];
  369. v[2] = p0[2] - p1[2];
  370. n[0] = u[1] * v[2] - u[2] * v[1];
  371. n[1] = u[2] * v[0] - u[0] * v[2];
  372. n[2] = u[0] * v[1] - u[1] * v[0];
  373. d = 1.0 / sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
  374. n[0] *= d;
  375. n[1] *= d;
  376. n[2] *= d;
  377. glBegin(GL_POLYGON);
  378. glNormal3fv(n);
  379. glVertex3fv(p0);
  380. glVertex3fv(p1);
  381. glVertex3fv(p2);
  382. glVertex3fv(vertexes[polygons[i][3]]);
  383. glVertex3fv(vertexes[polygons[i][4]]);
  384. glEnd();
  385. }
  386. }
  387. static void
  388. drawSphere(void)
  389. {
  390. int numMajor = 24;
  391. int numMinor = 32;
  392. float radius = 0.8;
  393. double majorStep = (M_PI / numMajor);
  394. double minorStep = (2.0 * M_PI / numMinor);
  395. int i, j;
  396. glColor3f(0.50, 0.50, 0.50);
  397. for (i = 0; i < numMajor; ++i) {
  398. double a = i * majorStep;
  399. double b = a + majorStep;
  400. double r0 = radius * sin(a);
  401. double r1 = radius * sin(b);
  402. GLfloat z0 = radius * cos(a);
  403. GLfloat z1 = radius * cos(b);
  404. glBegin(GL_TRIANGLE_STRIP);
  405. for (j = 0; j <= numMinor; ++j) {
  406. double c = j * minorStep;
  407. GLfloat x = cos(c);
  408. GLfloat y = sin(c);
  409. glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
  410. glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
  411. glVertex3f(x * r0, y * r0, z0);
  412. glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
  413. glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
  414. glVertex3f(x * r1, y * r1, z1);
  415. }
  416. glEnd();
  417. }
  418. }
  419. /*****************************************************************/
  420. float xmin = -0.035, xmax = 0.035;
  421. float ymin = -0.035, ymax = 0.035;
  422. float nnear = 0.1;
  423. float ffar = 1.9;
  424. float distance = -1.0;
  425. static void
  426. loadTextureProjection(int texUnit, GLfloat m[16])
  427. {
  428. GLfloat mInverse[4][4];
  429. /* Should use true inverse, but since m consists only of rotations, we can
  430. just use the transpose. */
  431. matrixTranspose((GLfloat *) mInverse, m);
  432. ActiveTexture(GL_TEXTURE0_ARB + texUnit);
  433. glMatrixMode(GL_TEXTURE);
  434. glLoadIdentity();
  435. glTranslatef(0.5, 0.5, 0.0);
  436. glScalef(0.5, 0.5, 1.0);
  437. glFrustum(xmin, xmax, ymin, ymax, nnear, ffar);
  438. glTranslatef(0.0, 0.0, distance);
  439. glMultMatrixf((GLfloat *) mInverse);
  440. glMatrixMode(GL_MODELVIEW);
  441. }
  442. static void
  443. drawTextureProjection(void)
  444. {
  445. float t = ffar / nnear;
  446. GLfloat n[4][3];
  447. GLfloat f[4][3];
  448. n[0][0] = xmin;
  449. n[0][1] = ymin;
  450. n[0][2] = -(nnear + distance);
  451. n[1][0] = xmax;
  452. n[1][1] = ymin;
  453. n[1][2] = -(nnear + distance);
  454. n[2][0] = xmax;
  455. n[2][1] = ymax;
  456. n[2][2] = -(nnear + distance);
  457. n[3][0] = xmin;
  458. n[3][1] = ymax;
  459. n[3][2] = -(nnear + distance);
  460. f[0][0] = xmin * t;
  461. f[0][1] = ymin * t;
  462. f[0][2] = -(ffar + distance);
  463. f[1][0] = xmax * t;
  464. f[1][1] = ymin * t;
  465. f[1][2] = -(ffar + distance);
  466. f[2][0] = xmax * t;
  467. f[2][1] = ymax * t;
  468. f[2][2] = -(ffar + distance);
  469. f[3][0] = xmin * t;
  470. f[3][1] = ymax * t;
  471. f[3][2] = -(ffar + distance);
  472. glColor3f(1.0, 1.0, 0.0);
  473. glBegin(GL_LINE_LOOP);
  474. glVertex3fv(n[0]);
  475. glVertex3fv(n[1]);
  476. glVertex3fv(n[2]);
  477. glVertex3fv(n[3]);
  478. glVertex3fv(f[3]);
  479. glVertex3fv(f[2]);
  480. glVertex3fv(f[1]);
  481. glVertex3fv(f[0]);
  482. glVertex3fv(n[0]);
  483. glVertex3fv(n[1]);
  484. glVertex3fv(f[1]);
  485. glVertex3fv(f[0]);
  486. glVertex3fv(f[3]);
  487. glVertex3fv(f[2]);
  488. glVertex3fv(n[2]);
  489. glVertex3fv(n[3]);
  490. glEnd();
  491. }
  492. /*****************************************************************/
  493. static void
  494. initialize(void)
  495. {
  496. GLfloat light0Pos[4] =
  497. {0.3, 0.3, 0.0, 1.0};
  498. GLfloat matAmb[4] =
  499. {0.01, 0.01, 0.01, 1.00};
  500. GLfloat matDiff[4] =
  501. {0.65, 0.65, 0.65, 1.00};
  502. GLfloat matSpec[4] =
  503. {0.30, 0.30, 0.30, 1.00};
  504. GLfloat matShine = 10.0;
  505. GLfloat eyePlaneS[] =
  506. {1.0, 0.0, 0.0, 0.0};
  507. GLfloat eyePlaneT[] =
  508. {0.0, 1.0, 0.0, 0.0};
  509. GLfloat eyePlaneR[] =
  510. {0.0, 0.0, 1.0, 0.0};
  511. GLfloat eyePlaneQ[] =
  512. {0.0, 0.0, 0.0, 1.0};
  513. int i;
  514. /* Setup Misc. */
  515. glClearColor(0.41, 0.41, 0.31, 0.0);
  516. glEnable(GL_DEPTH_TEST);
  517. /* glLineWidth(2.0);*/
  518. glCullFace(GL_FRONT);
  519. glEnable(GL_CULL_FACE);
  520. glMatrixMode(GL_PROJECTION);
  521. glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 3);
  522. glMatrixMode(GL_MODELVIEW);
  523. glTranslatef(0, 0, -2);
  524. matrixIdentity((GLfloat *) objectXform);
  525. for (i = 0; i < NumTextures; i++) {
  526. matrixIdentity((GLfloat *) textureXform[i]);
  527. }
  528. glMatrixMode(GL_PROJECTION);
  529. glPushMatrix();
  530. glLoadIdentity();
  531. glOrtho(0, 1, 0, 1, -1, 1);
  532. glMatrixMode(GL_MODELVIEW);
  533. glPushMatrix();
  534. glLoadIdentity();
  535. glRasterPos2i(0, 0);
  536. glPopMatrix();
  537. glMatrixMode(GL_PROJECTION);
  538. glPopMatrix();
  539. glMatrixMode(GL_MODELVIEW);
  540. /* Setup Lighting */
  541. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb);
  542. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
  543. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
  544. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
  545. glEnable(GL_COLOR_MATERIAL);
  546. glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  547. glEnable(GL_LIGHT0);
  548. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  549. glEnable(GL_LIGHTING);
  550. /* Setup Texture */
  551. (*loadTexture) ();
  552. for (i = 0; i < NumTextures; i++) {
  553. ActiveTexture(GL_TEXTURE0_ARB + i);
  554. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  555. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  556. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  557. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  558. glTexGenfv(GL_S, GL_EYE_PLANE, eyePlaneS);
  559. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  560. glTexGenfv(GL_T, GL_EYE_PLANE, eyePlaneT);
  561. glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  562. glTexGenfv(GL_R, GL_EYE_PLANE, eyePlaneR);
  563. glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  564. glTexGenfv(GL_Q, GL_EYE_PLANE, eyePlaneQ);
  565. }
  566. }
  567. static void
  568. display(void)
  569. {
  570. int i;
  571. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  572. if (textureEnabled) {
  573. if (mode == MoveTexture || mode == MoveView) {
  574. /* Have OpenGL compute the new transformation (simple but slow). */
  575. for (i = 0; i < NumTextures; i++) {
  576. glPushMatrix();
  577. glLoadIdentity();
  578. #if 0
  579. if (i & 1)
  580. glRotatef(angle, axis[0], axis[1], axis[2]);
  581. else
  582. #endif
  583. glRotatef(angle*(i+1), axis[0], axis[1], axis[2]);
  584. glMultMatrixf((GLfloat *) textureXform[i]);
  585. glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) textureXform[i]);
  586. glPopMatrix();
  587. }
  588. }
  589. for (i = 0; i < NumTextures; i++) {
  590. loadTextureProjection(i, (GLfloat *) textureXform[i]);
  591. }
  592. if (showProjection) {
  593. for (i = 0; i < NumTextures; i++) {
  594. ActiveTexture(GL_TEXTURE0_ARB + i);
  595. glPushMatrix();
  596. glMultMatrixf((GLfloat *) textureXform[i]);
  597. glDisable(GL_LIGHTING);
  598. drawTextureProjection();
  599. glEnable(GL_LIGHTING);
  600. glPopMatrix();
  601. }
  602. }
  603. for (i = 0; i < NumTextures; i++) {
  604. ActiveTexture(GL_TEXTURE0_ARB + i);
  605. glEnable(GL_TEXTURE_2D);
  606. glEnable(GL_TEXTURE_GEN_S);
  607. glEnable(GL_TEXTURE_GEN_T);
  608. glEnable(GL_TEXTURE_GEN_R);
  609. glEnable(GL_TEXTURE_GEN_Q);
  610. }
  611. }
  612. if (mode == MoveObject || mode == MoveView) {
  613. /* Have OpenGL compute the new transformation (simple but slow). */
  614. glPushMatrix();
  615. glLoadIdentity();
  616. glRotatef(angle, axis[0], axis[1], axis[2]);
  617. glMultMatrixf((GLfloat *) objectXform);
  618. glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) objectXform);
  619. glPopMatrix();
  620. }
  621. glPushMatrix();
  622. glMultMatrixf((GLfloat *) objectXform);
  623. (*drawObject) ();
  624. glPopMatrix();
  625. for (i = 0; i < NumTextures; i++) {
  626. ActiveTexture(GL_TEXTURE0_ARB + i);
  627. glDisable(GL_TEXTURE_2D);
  628. glDisable(GL_TEXTURE_GEN_S);
  629. glDisable(GL_TEXTURE_GEN_T);
  630. glDisable(GL_TEXTURE_GEN_R);
  631. glDisable(GL_TEXTURE_GEN_Q);
  632. }
  633. if (zoomFactor > 1.0) {
  634. glDisable(GL_DEPTH_TEST);
  635. glCopyPixels(0, 0, winWidth / zoomFactor, winHeight / zoomFactor, GL_COLOR);
  636. glEnable(GL_DEPTH_TEST);
  637. }
  638. glFlush();
  639. glutSwapBuffers();
  640. checkErrors();
  641. }
  642. /*****************************************************************/
  643. /* simple trackball-like motion control */
  644. static float lastPos[3];
  645. static int lastTime;
  646. static void
  647. ptov(int x, int y, int width, int height, float v[3])
  648. {
  649. float d, a;
  650. /* project x,y onto a hemi-sphere centered within width, height */
  651. v[0] = (2.0 * x - width) / width;
  652. v[1] = (height - 2.0 * y) / height;
  653. d = sqrt(v[0] * v[0] + v[1] * v[1]);
  654. v[2] = cos((M_PI / 2.0) * ((d < 1.0) ? d : 1.0));
  655. a = 1.0 / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  656. v[0] *= a;
  657. v[1] *= a;
  658. v[2] *= a;
  659. }
  660. static void
  661. startMotion(int x, int y, int but, int time)
  662. {
  663. if (but == GLUT_LEFT_BUTTON) {
  664. mode = MoveView;
  665. } else if (but == GLUT_MIDDLE_BUTTON) {
  666. mode = MoveTexture;
  667. } else {
  668. return;
  669. }
  670. lastTime = time;
  671. ptov(x, y, winWidth, winHeight, lastPos);
  672. }
  673. static void
  674. animate(void)
  675. {
  676. glutPostRedisplay();
  677. }
  678. static void
  679. vis(int visible)
  680. {
  681. if (visible == GLUT_VISIBLE) {
  682. if (redrawContinuously)
  683. glutIdleFunc(animate);
  684. } else {
  685. if (redrawContinuously)
  686. glutIdleFunc(NULL);
  687. }
  688. }
  689. static void
  690. stopMotion(int but, int time)
  691. {
  692. if ((but == GLUT_LEFT_BUTTON && mode == MoveView) ||
  693. (but == GLUT_MIDDLE_BUTTON && mode == MoveTexture)) {
  694. } else {
  695. return;
  696. }
  697. if (time == lastTime) {
  698. /* redrawContinuously = GL_TRUE;*/
  699. glutIdleFunc(animate);
  700. } else {
  701. angle = 0.0;
  702. redrawContinuously = GL_FALSE;
  703. glutIdleFunc(0);
  704. }
  705. if (!redrawContinuously) {
  706. mode = MoveNone;
  707. }
  708. }
  709. static void
  710. trackMotion(int x, int y)
  711. {
  712. float curPos[3], dx, dy, dz;
  713. ptov(x, y, winWidth, winHeight, curPos);
  714. dx = curPos[0] - lastPos[0];
  715. dy = curPos[1] - lastPos[1];
  716. dz = curPos[2] - lastPos[2];
  717. angle = 90.0 * sqrt(dx * dx + dy * dy + dz * dz);
  718. axis[0] = lastPos[1] * curPos[2] - lastPos[2] * curPos[1];
  719. axis[1] = lastPos[2] * curPos[0] - lastPos[0] * curPos[2];
  720. axis[2] = lastPos[0] * curPos[1] - lastPos[1] * curPos[0];
  721. lastTime = glutGet(GLUT_ELAPSED_TIME);
  722. lastPos[0] = curPos[0];
  723. lastPos[1] = curPos[1];
  724. lastPos[2] = curPos[2];
  725. glutPostRedisplay();
  726. }
  727. /*****************************************************************/
  728. static void
  729. object(void)
  730. {
  731. static int object;
  732. object++;
  733. object %= 3;
  734. switch (object) {
  735. case 0:
  736. drawObject = drawCube;
  737. break;
  738. case 1:
  739. drawObject = drawDodecahedron;
  740. break;
  741. case 2:
  742. drawObject = drawSphere;
  743. break;
  744. default:
  745. break;
  746. }
  747. }
  748. static void
  749. nop(void)
  750. {
  751. }
  752. static void
  753. texture(void)
  754. {
  755. static int texture = 0;
  756. texture++;
  757. texture %= 3;
  758. if (texture == 1 && texFilename == NULL) {
  759. /* Skip file texture if not loaded. */
  760. texture++;
  761. }
  762. switch (texture) {
  763. case 0:
  764. loadTexture = nop;
  765. textureEnabled = GL_FALSE;
  766. break;
  767. case 1:
  768. loadTexture = loadImageTextures;
  769. (*loadTexture) ();
  770. textureEnabled = GL_TRUE;
  771. break;
  772. case 2:
  773. loadTexture = loadSpotlightTexture;
  774. (*loadTexture) ();
  775. textureEnabled = GL_TRUE;
  776. break;
  777. default:
  778. break;
  779. }
  780. }
  781. static void
  782. help(void)
  783. {
  784. printf("'h' - help\n");
  785. printf("'l' - toggle linear/nearest filter\n");
  786. printf("'s' - toggle projection frustum\n");
  787. printf("'t' - toggle projected texture\n");
  788. printf("'o' - toggle object\n");
  789. printf("'z' - increase zoom factor\n");
  790. printf("'Z' - decrease zoom factor\n");
  791. printf("left mouse - move view\n");
  792. printf("middle mouse - move projection\n");
  793. }
  794. /* ARGSUSED1 */
  795. static void
  796. key(unsigned char key, int x, int y)
  797. {
  798. switch (key) {
  799. case '\033':
  800. exit(0);
  801. break;
  802. case 'l':
  803. linearFilter = !linearFilter;
  804. (*loadTexture) ();
  805. break;
  806. case 's':
  807. showProjection = !showProjection;
  808. break;
  809. case 't':
  810. texture();
  811. break;
  812. case 'o':
  813. object();
  814. break;
  815. case 'z':
  816. zoomFactor += 1.0;
  817. glPixelZoom(zoomFactor, zoomFactor);
  818. glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
  819. break;
  820. case 'Z':
  821. zoomFactor -= 1.0;
  822. if (zoomFactor < 1.0)
  823. zoomFactor = 1.0;
  824. glPixelZoom(zoomFactor, zoomFactor);
  825. glViewport(0, 0, winWidth / zoomFactor, winHeight / zoomFactor);
  826. break;
  827. case 'h':
  828. help();
  829. break;
  830. }
  831. glutPostRedisplay();
  832. }
  833. static void
  834. mouse(int button, int state, int x, int y)
  835. {
  836. if (state == GLUT_DOWN)
  837. startMotion(x, y, button, glutGet(GLUT_ELAPSED_TIME));
  838. else if (state == GLUT_UP)
  839. stopMotion(button, glutGet(GLUT_ELAPSED_TIME));
  840. glutPostRedisplay();
  841. }
  842. static void
  843. reshape(int w, int h)
  844. {
  845. winWidth = w;
  846. winHeight = h;
  847. glViewport(0, 0, w / zoomFactor, h / zoomFactor);
  848. }
  849. static void
  850. menu(int selection)
  851. {
  852. if (selection == 666) {
  853. exit(0);
  854. }
  855. key((unsigned char) selection, 0, 0);
  856. }
  857. int
  858. main(int argc, char **argv)
  859. {
  860. glutInitWindowSize(500,500);
  861. glutInit(&argc, argv);
  862. glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  863. (void) glutCreateWindow("projtex");
  864. glewInit();
  865. if (argc > 1) {
  866. NumTextures = atoi(argv[1]);
  867. }
  868. assert(NumTextures <= MAX_TEX);
  869. loadTexture = loadImageTextures;
  870. drawObject = drawCube;
  871. initialize();
  872. glutDisplayFunc(display);
  873. glutKeyboardFunc(key);
  874. glutReshapeFunc(reshape);
  875. glutMouseFunc(mouse);
  876. glutMotionFunc(trackMotion);
  877. glutVisibilityFunc(vis);
  878. glutCreateMenu(menu);
  879. glutAddMenuEntry("Toggle showing projection", 's');
  880. glutAddMenuEntry("Switch texture", 't');
  881. glutAddMenuEntry("Switch object", 'o');
  882. glutAddMenuEntry("Toggle filtering", 'l');
  883. glutAddMenuEntry("Quit", 666);
  884. glutAttachMenu(GLUT_RIGHT_BUTTON);
  885. texture();
  886. glutMainLoop();
  887. return 0; /* ANSI C requires main to return int. */
  888. }