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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. /*
  2. * This program is under the GNU GPL.
  3. * Use at your own risk.
  4. *
  5. * written by David Bucciarelli (tech.hmw@plus.it)
  6. * Humanware s.r.l.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <math.h>
  11. #include <time.h>
  12. #ifdef WIN32
  13. #include <windows.h>
  14. #endif
  15. #include <GL/glut.h>
  16. #include "../util/readtex.c"
  17. #include "shadow.c"
  18. #ifdef XMESA
  19. #include "GL/xmesa.h"
  20. static int fullscreen=1;
  21. #endif
  22. static int WIDTH=640;
  23. static int HEIGHT=480;
  24. #define FRAME 50
  25. #define BASESIZE 10.0
  26. #define BASERES 12
  27. #define TEAPOTRES 3
  28. #ifndef M_PI
  29. #define M_PI 3.1415926535
  30. #endif
  31. extern void shadowmatrix(GLfloat [4][4], GLfloat [4], GLfloat [4]);
  32. extern void findplane(GLfloat [4], GLfloat [3], GLfloat [3], GLfloat [3]);
  33. static int win=0;
  34. static float obs[3]={5.0,0.0,1.0};
  35. static float dir[3];
  36. static float v=0.0;
  37. static float alpha=-90.0;
  38. static float beta=90.0;
  39. static GLfloat baseshadow[4][4];
  40. static GLfloat lightpos[4]={2.3,0.0,3.0,1.0};
  41. static GLfloat lightdir[3]={-2.3,0.0,-3.0};
  42. static GLfloat lightalpha=0.0;
  43. static int fog=1;
  44. static int bfcull=1;
  45. static int usetex=1;
  46. static int help=1;
  47. static int joyavailable=0;
  48. static int joyactive=0;
  49. static GLuint t1id,t2id;
  50. static GLuint teapotdlist,basedlist,lightdlist;
  51. static float gettime(void)
  52. {
  53. static clock_t told=0;
  54. clock_t tnew,ris;
  55. tnew=clock();
  56. ris=tnew-told;
  57. told=tnew;
  58. return(ris/(float)CLOCKS_PER_SEC);
  59. }
  60. static void calcposobs(void)
  61. {
  62. dir[0]=sin(alpha*M_PI/180.0);
  63. dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
  64. dir[2]=cos(beta*M_PI/180.0);
  65. obs[0]+=v*dir[0];
  66. obs[1]+=v*dir[1];
  67. obs[2]+=v*dir[2];
  68. }
  69. static void special(int k, int x, int y)
  70. {
  71. switch(k) {
  72. case GLUT_KEY_LEFT:
  73. alpha-=2.0;
  74. break;
  75. case GLUT_KEY_RIGHT:
  76. alpha+=2.0;
  77. break;
  78. case GLUT_KEY_DOWN:
  79. beta-=2.0;
  80. break;
  81. case GLUT_KEY_UP:
  82. beta+=2.0;
  83. break;
  84. }
  85. }
  86. static void key(unsigned char k, int x, int y)
  87. {
  88. switch(k) {
  89. case 27:
  90. exit(0);
  91. break;
  92. case 'a':
  93. v+=0.005;
  94. break;
  95. case 'z':
  96. v-=0.005;
  97. break;
  98. case 'j':
  99. joyactive=(!joyactive);
  100. break;
  101. case 'h':
  102. help=(!help);
  103. break;
  104. case 'f':
  105. fog=(!fog);
  106. break;
  107. case 't':
  108. usetex=(!usetex);
  109. break;
  110. case 'b':
  111. if(bfcull) {
  112. glDisable(GL_CULL_FACE);
  113. bfcull=0;
  114. } else {
  115. glEnable(GL_CULL_FACE);
  116. bfcull=1;
  117. }
  118. break;
  119. #ifdef XMESA
  120. case ' ':
  121. XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
  122. fullscreen=(!fullscreen);
  123. break;
  124. #endif
  125. }
  126. }
  127. static void reshape(int w, int h)
  128. {
  129. WIDTH=w;
  130. HEIGHT=h;
  131. glMatrixMode(GL_PROJECTION);
  132. glLoadIdentity();
  133. gluPerspective(45.0,w/(float)h,0.2,40.0);
  134. glMatrixMode(GL_MODELVIEW);
  135. glLoadIdentity();
  136. glViewport(0,0,w,h);
  137. }
  138. static void printstring(void *font, char *string)
  139. {
  140. int len,i;
  141. len=(int)strlen(string);
  142. for(i=0;i<len;i++)
  143. glutBitmapCharacter(font,string[i]);
  144. }
  145. static void printhelp(void)
  146. {
  147. glEnable(GL_BLEND);
  148. glColor4f(0.5,0.5,0.5,0.5);
  149. glRecti(40,40,600,440);
  150. glDisable(GL_BLEND);
  151. glColor3f(1.0,0.0,0.0);
  152. glRasterPos2i(300,420);
  153. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
  154. glRasterPos2i(60,390);
  155. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Togle Help");
  156. glRasterPos2i(60,360);
  157. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Togle Textures");
  158. glRasterPos2i(60,330);
  159. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Togle Fog");
  160. glRasterPos2i(60,300);
  161. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"b - Togle Back face culling");
  162. glRasterPos2i(60,270);
  163. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
  164. glRasterPos2i(60,240);
  165. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
  166. glRasterPos2i(60,210);
  167. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
  168. glRasterPos2i(60,180);
  169. if(joyavailable)
  170. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Togle jostick control (Joystick control available)");
  171. else
  172. printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)");
  173. }
  174. static void drawbase(void)
  175. {
  176. int i,j;
  177. float x,y,dx,dy;
  178. glBindTexture(GL_TEXTURE_2D,t1id);
  179. dx=BASESIZE/BASERES;
  180. dy=-BASESIZE/BASERES;
  181. for(y=BASESIZE/2.0,j=0;j<BASERES;y+=dy,j++) {
  182. glBegin(GL_QUAD_STRIP);
  183. glColor3f(1.0,1.0,1.0);
  184. glNormal3f(0.0,0.0,1.0);
  185. for(x=-BASESIZE/2.0,i=0;i<BASERES;x+=dx,i++) {
  186. glTexCoord2f(x,y);
  187. glVertex3f(x,y,0.0);
  188. glTexCoord2f(x,y+dy);
  189. glVertex3f(x,y+dy,0.0);
  190. }
  191. glEnd();
  192. }
  193. }
  194. static void drawteapot(void)
  195. {
  196. static float xrot=0.0;
  197. static float zrot=0.0;
  198. glPushMatrix();
  199. glRotatef(lightalpha,0.0,0.0,1.0);
  200. glMultMatrixf((GLfloat *)baseshadow);
  201. glRotatef(-lightalpha,0.0,0.0,1.0);
  202. glTranslatef(0.0,0.0,1.0);
  203. glRotatef(xrot,1.0,0.0,0.0);
  204. glRotatef(zrot,0.0,0.0,1.0);
  205. glDisable(GL_TEXTURE_2D);
  206. glDisable(GL_DEPTH_TEST);
  207. glDisable(GL_LIGHTING);
  208. glColor3f(0.0,0.0,0.0);
  209. glCallList(teapotdlist);
  210. glEnable(GL_DEPTH_TEST);
  211. glEnable(GL_LIGHTING);
  212. if(usetex)
  213. glEnable(GL_TEXTURE_2D);
  214. glPopMatrix();
  215. glPushMatrix();
  216. glTranslatef(0.0,0.0,1.0);
  217. glRotatef(xrot,1.0,0.0,0.0);
  218. glRotatef(zrot,0.0,0.0,1.0);
  219. glCallList(teapotdlist);
  220. glPopMatrix();
  221. xrot+=2.0;
  222. zrot+=1.0;
  223. }
  224. static void drawlight1(void)
  225. {
  226. glPushMatrix();
  227. glRotatef(lightalpha,0.0,0.0,1.0);
  228. glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
  229. glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightdir);
  230. glPopMatrix();
  231. }
  232. static void drawlight2(void)
  233. {
  234. glPushMatrix();
  235. glRotatef(lightalpha,0.0,0.0,1.0);
  236. glTranslatef(lightpos[0],lightpos[1],lightpos[2]);
  237. glDisable(GL_TEXTURE_2D);
  238. glCallList(lightdlist);
  239. if(usetex)
  240. glEnable(GL_TEXTURE_2D);
  241. glPopMatrix();
  242. lightalpha+=1.0;
  243. }
  244. static void dojoy(void)
  245. {
  246. #ifdef WIN32
  247. static UINT max[2]={0,0};
  248. static UINT min[2]={0xffffffff,0xffffffff},center[2];
  249. MMRESULT res;
  250. JOYINFO joy;
  251. res=joyGetPos(JOYSTICKID1,&joy);
  252. if(res==JOYERR_NOERROR) {
  253. joyavailable=1;
  254. if(max[0]<joy.wXpos)
  255. max[0]=joy.wXpos;
  256. if(min[0]>joy.wXpos)
  257. min[0]=joy.wXpos;
  258. center[0]=(max[0]+min[0])/2;
  259. if(max[1]<joy.wYpos)
  260. max[1]=joy.wYpos;
  261. if(min[1]>joy.wYpos)
  262. min[1]=joy.wYpos;
  263. center[1]=(max[1]+min[1])/2;
  264. if(joyactive) {
  265. if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
  266. alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
  267. if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
  268. beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
  269. if(joy.wButtons & JOY_BUTTON1)
  270. v+=0.005;
  271. if(joy.wButtons & JOY_BUTTON2)
  272. v-=0.005;
  273. }
  274. } else
  275. joyavailable=0;
  276. #endif
  277. }
  278. static void draw(void)
  279. {
  280. static int count=0;
  281. static char frbuf[80];
  282. float fr;
  283. dojoy();
  284. glEnable(GL_DEPTH_TEST);
  285. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  286. if(usetex)
  287. glEnable(GL_TEXTURE_2D);
  288. else
  289. glDisable(GL_TEXTURE_2D);
  290. if(fog)
  291. glEnable(GL_FOG);
  292. else
  293. glDisable(GL_FOG);
  294. glEnable(GL_LIGHTING);
  295. glShadeModel(GL_SMOOTH);
  296. glPushMatrix();
  297. calcposobs();
  298. gluLookAt(obs[0],obs[1],obs[2],
  299. obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
  300. 0.0,0.0,1.0);
  301. drawlight1();
  302. glCallList(basedlist);
  303. drawteapot();
  304. drawlight2();
  305. glPopMatrix();
  306. if((count % FRAME)==0) {
  307. fr=gettime();
  308. sprintf(frbuf,"Frame rate: %f",FRAME/fr);
  309. }
  310. glDisable(GL_LIGHTING);
  311. glDisable(GL_TEXTURE_2D);
  312. glDisable(GL_DEPTH_TEST);
  313. glDisable(GL_FOG);
  314. glShadeModel(GL_FLAT);
  315. glMatrixMode(GL_PROJECTION);
  316. glLoadIdentity();
  317. glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
  318. glMatrixMode(GL_MODELVIEW);
  319. glLoadIdentity();
  320. glColor3f(1.0,0.0,0.0);
  321. glRasterPos2i(10,10);
  322. printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
  323. glRasterPos2i(350,470);
  324. printstring(GLUT_BITMAP_HELVETICA_10,"Teapot V1.2 Written by David Bucciarelli (tech.hmw@plus.it)");
  325. if(help)
  326. printhelp();
  327. reshape(WIDTH,HEIGHT);
  328. glutSwapBuffers();
  329. count++;
  330. }
  331. static void inittextures(void)
  332. {
  333. glGenTextures(1,&t1id);
  334. glBindTexture(GL_TEXTURE_2D,t1id);
  335. glPixelStorei(GL_UNPACK_ALIGNMENT,4);
  336. if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
  337. fprintf(stderr,"Error reading a texture.\n");
  338. exit(-1);
  339. }
  340. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  341. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  342. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
  343. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  344. glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
  345. glGenTextures(1,&t2id);
  346. glBindTexture(GL_TEXTURE_2D,t2id);
  347. if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
  348. fprintf(stderr,"Error reading a texture.\n");
  349. exit(-1);
  350. }
  351. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  352. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  353. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
  354. glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  355. glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
  356. }
  357. static void initlight(void)
  358. {
  359. float lamb[4]={0.2,0.2,0.2,1.0};
  360. float lspec[4]={1.0,1.0,1.0,1.0};
  361. glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,70.0);
  362. glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,20.0);
  363. glLightfv(GL_LIGHT0,GL_AMBIENT,lamb);
  364. glLightfv(GL_LIGHT0,GL_SPECULAR,lspec);
  365. glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,20.0);
  366. glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,lspec);
  367. glEnable(GL_LIGHT0);
  368. }
  369. static void initdlists(void)
  370. {
  371. GLUquadricObj *lcone,*lbase;
  372. GLfloat plane[4];
  373. GLfloat v0[3]={0.0,0.0,0.0};
  374. GLfloat v1[3]={1.0,0.0,0.0};
  375. GLfloat v2[3]={0.0,1.0,0.0};
  376. findplane(plane,v0,v1,v2);
  377. shadowmatrix(baseshadow,plane,lightpos);
  378. teapotdlist=glGenLists(1);
  379. glNewList(teapotdlist,GL_COMPILE);
  380. glRotatef(90.0,1.0,0.0,0.0);
  381. glCullFace(GL_FRONT);
  382. glBindTexture(GL_TEXTURE_2D,t2id);
  383. glutSolidTeapot(0.75);
  384. glCullFace(GL_BACK);
  385. glEndList();
  386. basedlist=glGenLists(1);
  387. glNewList(basedlist,GL_COMPILE);
  388. drawbase();
  389. glEndList();
  390. lightdlist=glGenLists(1);
  391. glNewList(lightdlist,GL_COMPILE);
  392. glDisable(GL_LIGHTING);
  393. lcone=gluNewQuadric();
  394. lbase=gluNewQuadric();
  395. glRotatef(45.0,0.0,1.0,0.0);
  396. glColor3f(1.0,1.0,1.0);
  397. glCullFace(GL_FRONT);
  398. gluDisk(lbase,0.0,0.2,12.0,1.0);
  399. glCullFace(GL_BACK);
  400. glColor3f(0.5,0.0,0.0);
  401. gluCylinder(lcone,0.2,0.0,0.5,12,1);
  402. gluDeleteQuadric(lcone);
  403. gluDeleteQuadric(lbase);
  404. glEnable(GL_LIGHTING);
  405. glEndList();
  406. }
  407. int main(int ac, char **av)
  408. {
  409. float fogcolor[4]={0.025,0.025,0.025,1.0};
  410. fprintf(stderr,"Teapot V1.2\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
  411. /*
  412. if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
  413. fprintf(stderr,"Error setting the process class.\n");
  414. return 0;
  415. }
  416. if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
  417. fprintf(stderr,"Error setting the process priority.\n");
  418. return 0;
  419. }
  420. */
  421. glutInitWindowPosition(0,0);
  422. glutInitWindowSize(WIDTH,HEIGHT);
  423. glutInit(&ac,av);
  424. glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
  425. if(!(win=glutCreateWindow("Teapot"))) {
  426. fprintf(stderr,"Error, couldn't open window\n");
  427. return -1;
  428. }
  429. reshape(WIDTH,HEIGHT);
  430. glShadeModel(GL_SMOOTH);
  431. glEnable(GL_DEPTH_TEST);
  432. glEnable(GL_CULL_FACE);
  433. glEnable(GL_TEXTURE_2D);
  434. glEnable(GL_FOG);
  435. glFogi(GL_FOG_MODE,GL_EXP2);
  436. glFogfv(GL_FOG_COLOR,fogcolor);
  437. glFogf(GL_FOG_DENSITY,0.04);
  438. glHint(GL_FOG_HINT,GL_NICEST);
  439. glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  440. calcposobs();
  441. inittextures();
  442. initlight();
  443. initdlists();
  444. glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
  445. glutReshapeFunc(reshape);
  446. glutDisplayFunc(draw);
  447. glutKeyboardFunc(key);
  448. glutSpecialFunc(special);
  449. glutIdleFunc(draw);
  450. glutMainLoop();
  451. return 0;
  452. }