lesson10.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. (****************************************
  2. * NDS NeHe Lesson 10 *
  3. * Author: Dovoto *
  4. ****************************************)
  5. program Lesson10;
  6. {$mode objfpc}
  7. {$L build/Mud.pcx.o}
  8. {$L build/World.txt.o}
  9. {$L build/drunkenlogo.pcx.o}
  10. uses
  11. ctypes, nds9;
  12. {$include inc/Mud.pcx.inc}
  13. {$include inc/World.txt.inc}
  14. {$include inc/drunkenlogo.pcx.inc}
  15. const
  16. piover180: cfloat = 0.0174532925;
  17. var
  18. heading: cfloat = 0.0;
  19. xpos: cfloat = 0.0;
  20. zpos: cfloat = 0.0;
  21. yrot: cfloat = 0.0; // Y Rotation
  22. walkbias: cfloat = 0.0;
  23. walkbiasangle: cfloat = 0.0;
  24. lookupdown: cfloat = 0.0;
  25. texture: array [0..2] of integer; // Storage For 3 Textures (only going to use 1 on the DS for this demo)
  26. type
  27. tagVERTEX = record
  28. x, y, z: cfloat;
  29. u, v: cfloat;
  30. end;
  31. VERTEX = tagVERTEX;
  32. tagTRIANGLE = record
  33. vertex: array [0..2] of VERTEX;
  34. end;
  35. TRIANGLE = tagTRIANGLE;
  36. TTriangle = TRIANGLE;
  37. PTriangle = ^TRIANGLE;
  38. tagSECTOR = record
  39. numtriangles: integer;
  40. triangle: PTRIANGLE;
  41. end;
  42. SECTOR = tagSECTOR;
  43. TCubeRot = record
  44. x, y, z: cfloat;
  45. end;
  46. var
  47. sector1: SECTOR; // Our Model Goes Here:
  48. Myfile: pchar;
  49. cuberot: TCubeRot;
  50. procedure ShadowDemo(); forward;
  51. function DrawGLScene(): boolean;
  52. var
  53. x_m, y_m, z_m: cfloat;
  54. u_m, v_m: cfloat;
  55. xtrans, ztrans, ytrans: cfloat;
  56. sceneroty: cfloat;
  57. numtriangles: integer;
  58. loop_m: integer;
  59. begin
  60. // Reset The View
  61. xtrans := -xpos;
  62. ztrans := -zpos;
  63. ytrans := -walkbias - 0.25;
  64. sceneroty := 360.0 - yrot;
  65. glLoadIdentity();
  66. glRotatef(lookupdown,1.0,0,0);
  67. glRotatef(sceneroty,0,1.0,0);
  68. glTranslatef(xtrans, ytrans, ztrans);
  69. glBindTexture(GL_TEXTURE_2D, texture[0]);
  70. numtriangles := sector1.numtriangles;
  71. // Process Each Triangle
  72. for loop_m := 0 to numtriangles - 1 do
  73. begin
  74. glBegin(GL_TRIANGLES);
  75. glNormal3f( 0.0, 0.0, 1.0);
  76. x_m := sector1.triangle[loop_m].vertex[0].x;
  77. y_m := sector1.triangle[loop_m].vertex[0].y;
  78. z_m := sector1.triangle[loop_m].vertex[0].z;
  79. u_m := sector1.triangle[loop_m].vertex[0].u;
  80. v_m := sector1.triangle[loop_m].vertex[0].v;
  81. glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
  82. x_m := sector1.triangle[loop_m].vertex[1].x;
  83. y_m := sector1.triangle[loop_m].vertex[1].y;
  84. z_m := sector1.triangle[loop_m].vertex[1].z;
  85. u_m := sector1.triangle[loop_m].vertex[1].u;
  86. v_m := sector1.triangle[loop_m].vertex[1].v;
  87. glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
  88. x_m := sector1.triangle[loop_m].vertex[2].x;
  89. y_m := sector1.triangle[loop_m].vertex[2].y;
  90. z_m := sector1.triangle[loop_m].vertex[2].z;
  91. u_m := sector1.triangle[loop_m].vertex[2].u;
  92. v_m := sector1.triangle[loop_m].vertex[2].v;
  93. glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
  94. glEnd();
  95. end;
  96. ShadowDemo();
  97. DrawGLScene := true; // Everything Went OK
  98. end;
  99. function tsin(angle: cfloat): cfloat;
  100. var
  101. s: cint32;
  102. begin
  103. s := sinLerp(trunc((angle * DEGREES_IN_CIRCLE) / 360.0));
  104. tsin := f32tofloat(s);
  105. end;
  106. function tcos(angle: cfloat): cfloat;
  107. var
  108. c: cint32;
  109. begin
  110. c := cosLerp(trunc((angle * DEGREES_IN_CIRCLE) / 360.0));
  111. tcos := f32tofloat(c);
  112. end;
  113. procedure myGetStr(buff: pchar; size: integer);
  114. begin
  115. buff^ := Myfile^;
  116. inc(MyFile);
  117. while (buff^ <> #10) and (buff^ <> #13) do
  118. begin
  119. inc(buff);
  120. buff^ := Myfile^;
  121. inc(MyFile);
  122. end;
  123. buff[0] := #10;
  124. buff[1] := #0;
  125. end;
  126. procedure readstr(str: pchar);
  127. begin
  128. repeat
  129. myGetStr(str, 255);
  130. until ((str[0] <> '/') and (str[0] <> #10));
  131. end;
  132. procedure SetupWorld();
  133. var
  134. x, y, z: cfloat;
  135. u, v: cfloat;
  136. numtriangles: integer;
  137. oneline: array [0..254] of char;
  138. loop, vert: integer;
  139. begin
  140. readstr(oneline);
  141. sscanf(oneline, 'NUMPOLLIES %d'#10, @numtriangles);
  142. GetMem(sector1.triangle, numtriangles * sizeof(TTRIANGLE));
  143. sector1.numtriangles := numtriangles;
  144. for loop := 0 to numtriangles - 1 do
  145. begin
  146. for vert := 0 to 2 do
  147. begin
  148. readstr(oneline);
  149. sscanf(oneline, '%f %f %f %f %f', @x, @y, @z, @u, @v);
  150. sector1.triangle[loop].vertex[vert].x := x;
  151. sector1.triangle[loop].vertex[vert].y := y;
  152. sector1.triangle[loop].vertex[vert].z := z;
  153. sector1.triangle[loop].vertex[vert].u := u;
  154. sector1.triangle[loop].vertex[vert].v := v;
  155. end;
  156. end;
  157. end;
  158. // Load PCX files And Convert To Textures
  159. function LoadGLTextures(): boolean;
  160. var
  161. pcx: sImage;
  162. begin
  163. glGenTextures(2, @texture[0]);
  164. //load our texture
  165. loadPCX(pcuint8(Mud_pcx), @pcx);
  166. image8to16(@pcx);
  167. glBindTexture(0, texture[0]);
  168. glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128 , TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD or GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T, pcx.image.data8);
  169. imageDestroy(@pcx);
  170. loadPCX(pcuint8(drunkenlogo_pcx), @pcx);
  171. image8to16(@pcx);
  172. glBindTexture(0, texture[1]);
  173. glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128, TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD, pcx.image.data8);
  174. imageDestroy(@pcx);
  175. result := true;
  176. end;
  177. procedure TransformCube();
  178. begin
  179. glRotatef(cubeRot.x, 1.0, 0.0, 0.0);
  180. glRotatef(cubeRot.y, 0.0, 1.0, 0.0);
  181. glRotatef(cubeRot.z, 0.0, 0.0, 1.0);
  182. end;
  183. procedure EmitCube();
  184. begin
  185. glPushMatrix();
  186. glScalef(0.03, 0.03, 0.03);
  187. glRotatef(cubeRot.x, 1.0, 0.0, 0.0);
  188. glRotatef(cubeRot.y, 0.0, 1.0, 0.0);
  189. glRotatef(cubeRot.z, 0.0, 0.0, 1.0);
  190. glBegin(GL_QUADS);
  191. // Front Face
  192. glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
  193. glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
  194. glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0);
  195. glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
  196. // Back Face
  197. glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
  198. glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
  199. glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
  200. glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
  201. // Top Face
  202. glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
  203. glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0);
  204. glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 1.0);
  205. glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
  206. // Bottom Face
  207. glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
  208. glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0);
  209. glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
  210. glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
  211. // Right face
  212. glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
  213. glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
  214. glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, 1.0);
  215. glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
  216. // Left Face
  217. glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
  218. glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
  219. glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
  220. glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
  221. glEnd();
  222. glPopMatrix(1);
  223. end;
  224. procedure ShadowDemo();
  225. begin
  226. cubeRot.y := cubeRot.y + 0.8;
  227. //draw the actual cube
  228. glPushMatrix();
  229. glTranslatef(0.0, 0.4, -0.4); //draw the cube up in the air
  230. TransformCube();
  231. glBindTexture(GL_TEXTURE_2D, texture[1]);
  232. EmitCube();
  233. glPopMatrix(1);
  234. //draw the shadow:
  235. begin
  236. //draw the cube shadow on the ground
  237. glPushMatrix();
  238. glTranslatef(0.0, 0.0, -0.4);
  239. TransformCube();
  240. //use no texture. set shadow color: we'll use green just to show that it is possible
  241. glBindTexture(0, 0);
  242. glColor(RGB15(0, 8, 0));
  243. //1st shadow pass
  244. //be sure to use opaque here
  245. glPolyFmt(POLY_SHADOW or POLY_CULL_FRONT or POLY_ALPHA(31));
  246. EmitCube();
  247. //2nd shadow pass
  248. //be sure to use a different polyID here (shadow with polyID 0 can't be cast on surface with polyID 0)
  249. //we set the fog bit here because we want the shadow to be fogged later. i think it may be buggy but it looks better.
  250. glPolyFmt(POLY_SHADOW or POLY_CULL_BACK or POLY_ALPHA(15) or POLY_ID(1) or POLY_FOG);
  251. EmitCube();
  252. //reset poly attribute
  253. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_NONE or POLY_FORMAT_LIGHT0 or POLY_FOG);
  254. glPopMatrix(1);
  255. end;
  256. end;
  257. var
  258. thisXY: touchPosition;
  259. lastXY: touchPosition;
  260. dx, dy: cint16;
  261. i: integer;
  262. held: integer;
  263. begin
  264. MyFile := pchar(@World_txt);
  265. // Setup the Main screen for 3D
  266. videoSetMode(MODE_0_3D);
  267. vramSetBankA(VRAM_A_TEXTURE); //NEW must set up some memory for textures
  268. consoleDemoInit();
  269. // initialize the geometry engine
  270. glInit();
  271. // enable textures
  272. glEnable(GL_TEXTURE_2D);
  273. // enable antialiasing
  274. glEnable(GL_ANTIALIAS);
  275. // enable alpha blending for shadow demo
  276. glEnable(GL_BLEND);
  277. // setup the rear plane
  278. glClearColor(0,0,0,31); // BG must be opaque for AA to work
  279. glClearPolyID(63); // BG must have a unique polygon ID for AA to work
  280. glClearDepth($7FFF);
  281. // Set our viewport to be the same size as the screen
  282. glViewport(0,0,255,191);
  283. LoadGLTextures();
  284. SetupWorld();
  285. glMatrixMode(GL_PROJECTION);
  286. glLoadIdentity();
  287. gluPerspective(70, 256.0 / 192.0, 0.1, 100);
  288. glLight(0, RGB15(31,31,31) , 0, floattov10(-1.0), 0);
  289. //need to set up some material properties since DS does not have them set by default
  290. glMaterialf(GL_AMBIENT, RGB15(16,16,16));
  291. glMaterialf(GL_DIFFUSE, RGB15(16,16,16));
  292. glMaterialf(GL_SPECULAR, BIT(15) or RGB15(8,8,8));
  293. glMaterialf(GL_EMISSION, RGB15(16,16,16));
  294. //ds uses a table for shinyness..this generates a half-ass one
  295. glMaterialShinyness();
  296. //ds specific, several attributes can be set here
  297. glPolyFmt(POLY_ALPHA(31) or POLY_CULL_NONE or POLY_FORMAT_LIGHT0 or POLY_FOG);
  298. // Set the current matrix to be the model matrix
  299. glMatrixMode(GL_MODELVIEW);
  300. //setup demo fog parameters
  301. //these parameters are somewhat arbitrary, and designed to illustrate fog in just this one case.
  302. //you will certainly need to tweak them for your own use.
  303. //be sure to have set the POLY_FOG bit on any material you want to be fogged.
  304. glEnable(GL_FOG);
  305. glFogShift(2);
  306. glFogColor(0, 0, 0, 0);
  307. for i := 0 to 31 do
  308. glFogDensity(i, i * 4);
  309. glFogDensity(31, 127);
  310. glFogOffset($6000);
  311. while true do
  312. begin
  313. //these little button functions are pretty handy
  314. scanKeys();
  315. held := keysHeld();
  316. if (held and KEY_A) <> 0 then lookupdown := lookupdown - 1.0;
  317. if (held and KEY_B) <> 0 then lookupdown := lookupdown + 1.0;
  318. if (held and KEY_LEFT) <> 0 then
  319. begin
  320. heading := heading + 1.0;
  321. yrot := heading;
  322. end;
  323. if (held and KEY_RIGHT) <> 0 then
  324. begin
  325. heading := heading - 1.0;
  326. yrot := heading;
  327. end;
  328. if (held and KEY_DOWN) <> 0 then
  329. begin
  330. xpos := xpos + (tsin(heading)) * 0.05;
  331. zpos := zpos + (tcos(heading)) * 0.05;
  332. if (walkbiasangle >= 359.0) then
  333. walkbiasangle := 0.0
  334. else
  335. walkbiasangle:= walkbiasangle+10;
  336. walkbias := tsin(walkbiasangle) / 20.0;
  337. end;
  338. if (held and KEY_UP) <> 0 then
  339. begin
  340. xpos := xpos - (tsin(heading)) * 0.05;
  341. zpos := zpos - (tcos(heading)) * 0.05;
  342. if (walkbiasangle <= 1.0) then
  343. walkbiasangle := 359.0
  344. else
  345. walkbiasangle := walkbiasangle- 10;
  346. walkbias := tsin(walkbiasangle) / 20.0;
  347. end;
  348. glColor3f(1,1,1);
  349. DrawGLScene();
  350. // flush to screen
  351. glFlush(0);
  352. // wait for the screen to refresh
  353. swiWaitForVBlank();
  354. if (held and KEY_START) <> 0 then break;
  355. end;
  356. end.