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 23KB

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