123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- (****************************************
- * NDS NeHe Lesson 10 *
- * Author: Dovoto *
- ****************************************)
- program Lesson10;
- {$mode objfpc}
- {$L build/Mud.pcx.o}
- {$L build/World.txt.o}
- {$L build/drunkenlogo.pcx.o}
- uses
- ctypes, nds9;
- {$include inc/Mud.pcx.inc}
- {$include inc/World.txt.inc}
- {$include inc/drunkenlogo.pcx.inc}
- const
- piover180: cfloat = 0.0174532925;
- var
- heading: cfloat = 0.0;
- xpos: cfloat = 0.0;
- zpos: cfloat = 0.0;
- yrot: cfloat = 0.0; // Y Rotation
- walkbias: cfloat = 0.0;
- walkbiasangle: cfloat = 0.0;
- lookupdown: cfloat = 0.0;
- texture: array [0..2] of integer; // Storage For 3 Textures (only going to use 1 on the DS for this demo)
- type
- tagVERTEX = record
- x, y, z: cfloat;
- u, v: cfloat;
- end;
- VERTEX = tagVERTEX;
- tagTRIANGLE = record
- vertex: array [0..2] of VERTEX;
- end;
- TRIANGLE = tagTRIANGLE;
- TTriangle = TRIANGLE;
- PTriangle = ^TRIANGLE;
- tagSECTOR = record
- numtriangles: integer;
- triangle: PTRIANGLE;
- end;
- SECTOR = tagSECTOR;
- TCubeRot = record
- x, y, z: cfloat;
- end;
- var
- sector1: SECTOR; // Our Model Goes Here:
- Myfile: pchar;
- cuberot: TCubeRot;
- procedure ShadowDemo(); forward;
-
- function DrawGLScene(): boolean;
- var
- x_m, y_m, z_m: cfloat;
- u_m, v_m: cfloat;
- xtrans, ztrans, ytrans: cfloat;
- sceneroty: cfloat;
- numtriangles: integer;
- loop_m: integer;
- begin
- // Reset The View
- xtrans := -xpos;
- ztrans := -zpos;
- ytrans := -walkbias - 0.25;
- sceneroty := 360.0 - yrot;
- glLoadIdentity();
- glRotatef(lookupdown,1.0,0,0);
- glRotatef(sceneroty,0,1.0,0);
- glTranslatef(xtrans, ytrans, ztrans);
- glBindTexture(GL_TEXTURE_2D, texture[0]);
- numtriangles := sector1.numtriangles;
- // Process Each Triangle
- for loop_m := 0 to numtriangles - 1 do
- begin
- glBegin(GL_TRIANGLES);
- glNormal3f( 0.0, 0.0, 1.0);
- x_m := sector1.triangle[loop_m].vertex[0].x;
- y_m := sector1.triangle[loop_m].vertex[0].y;
- z_m := sector1.triangle[loop_m].vertex[0].z;
- u_m := sector1.triangle[loop_m].vertex[0].u;
- v_m := sector1.triangle[loop_m].vertex[0].v;
- glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
- x_m := sector1.triangle[loop_m].vertex[1].x;
- y_m := sector1.triangle[loop_m].vertex[1].y;
- z_m := sector1.triangle[loop_m].vertex[1].z;
- u_m := sector1.triangle[loop_m].vertex[1].u;
- v_m := sector1.triangle[loop_m].vertex[1].v;
- glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
- x_m := sector1.triangle[loop_m].vertex[2].x;
- y_m := sector1.triangle[loop_m].vertex[2].y;
- z_m := sector1.triangle[loop_m].vertex[2].z;
- u_m := sector1.triangle[loop_m].vertex[2].u;
- v_m := sector1.triangle[loop_m].vertex[2].v;
- glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
- glEnd();
- end;
- ShadowDemo();
- DrawGLScene := true; // Everything Went OK
- end;
- function tsin(angle: cfloat): cfloat;
- var
- s: cint32;
- begin
- s := sinLerp(trunc((angle * DEGREES_IN_CIRCLE) / 360.0));
- tsin := f32tofloat(s);
- end;
- function tcos(angle: cfloat): cfloat;
- var
- c: cint32;
- begin
- c := cosLerp(trunc((angle * DEGREES_IN_CIRCLE) / 360.0));
- tcos := f32tofloat(c);
- end;
- procedure myGetStr(buff: pchar; size: integer);
- begin
- buff^ := Myfile^;
- inc(MyFile);
- while (buff^ <> #10) and (buff^ <> #13) do
- begin
- inc(buff);
- buff^ := Myfile^;
- inc(MyFile);
- end;
- buff[0] := #10;
- buff[1] := #0;
- end;
- procedure readstr(str: pchar);
- begin
- repeat
- myGetStr(str, 255);
- until ((str[0] <> '/') and (str[0] <> #10));
- end;
- procedure SetupWorld();
- var
- x, y, z: cfloat;
- u, v: cfloat;
- numtriangles: integer;
- oneline: array [0..254] of char;
- loop, vert: integer;
- begin
- readstr(oneline);
- sscanf(oneline, 'NUMPOLLIES %d'#10, @numtriangles);
- GetMem(sector1.triangle, numtriangles * sizeof(TTRIANGLE));
- sector1.numtriangles := numtriangles;
- for loop := 0 to numtriangles - 1 do
- begin
- for vert := 0 to 2 do
- begin
- readstr(oneline);
- sscanf(oneline, '%f %f %f %f %f', @x, @y, @z, @u, @v);
- sector1.triangle[loop].vertex[vert].x := x;
- sector1.triangle[loop].vertex[vert].y := y;
- sector1.triangle[loop].vertex[vert].z := z;
- sector1.triangle[loop].vertex[vert].u := u;
- sector1.triangle[loop].vertex[vert].v := v;
- end;
- end;
- end;
- // Load PCX files And Convert To Textures
- function LoadGLTextures(): boolean;
- var
- pcx: sImage;
- begin
- glGenTextures(2, @texture[0]);
- //load our texture
- loadPCX(pcuint8(Mud_pcx), @pcx);
- image8to16(@pcx);
- glBindTexture(0, texture[0]);
- 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);
- imageDestroy(@pcx);
- loadPCX(pcuint8(drunkenlogo_pcx), @pcx);
- image8to16(@pcx);
- glBindTexture(0, texture[1]);
- glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128, TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD, pcx.image.data8);
- imageDestroy(@pcx);
- result := true;
- end;
- procedure TransformCube();
- begin
- glRotatef(cubeRot.x, 1.0, 0.0, 0.0);
- glRotatef(cubeRot.y, 0.0, 1.0, 0.0);
- glRotatef(cubeRot.z, 0.0, 0.0, 1.0);
- end;
- procedure EmitCube();
- begin
- glPushMatrix();
- glScalef(0.03, 0.03, 0.03);
-
- glRotatef(cubeRot.x, 1.0, 0.0, 0.0);
- glRotatef(cubeRot.y, 0.0, 1.0, 0.0);
- glRotatef(cubeRot.z, 0.0, 0.0, 1.0);
-
- glBegin(GL_QUADS);
- // Front Face
- glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
- glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
- glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0);
- glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
- // Back Face
- glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
- glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
- glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
- glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
- // Top Face
- glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
- glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0);
- glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 1.0);
- glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
- // Bottom Face
- glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
- glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0);
- glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
- glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
- // Right face
- glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
- glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
- glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, 1.0);
- glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
- // Left Face
- glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
- glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
- glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
- glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
- glEnd();
- glPopMatrix(1);
- end;
- procedure ShadowDemo();
- begin
- cubeRot.y := cubeRot.y + 0.8;
-
- //draw the actual cube
- glPushMatrix();
- glTranslatef(0.0, 0.4, -0.4); //draw the cube up in the air
- TransformCube();
- glBindTexture(GL_TEXTURE_2D, texture[1]);
- EmitCube();
- glPopMatrix(1);
-
- //draw the shadow:
- begin
- //draw the cube shadow on the ground
- glPushMatrix();
- glTranslatef(0.0, 0.0, -0.4);
- TransformCube();
-
- //use no texture. set shadow color: we'll use green just to show that it is possible
- glBindTexture(0, 0);
- glColor(RGB15(0, 8, 0));
-
- //1st shadow pass
- //be sure to use opaque here
- glPolyFmt(POLY_SHADOW or POLY_CULL_FRONT or POLY_ALPHA(31));
- EmitCube();
-
- //2nd shadow pass
- //be sure to use a different polyID here (shadow with polyID 0 can't be cast on surface with polyID 0)
- //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.
- glPolyFmt(POLY_SHADOW or POLY_CULL_BACK or POLY_ALPHA(15) or POLY_ID(1) or POLY_FOG);
- EmitCube();
-
- //reset poly attribute
- glPolyFmt(POLY_ALPHA(31) or POLY_CULL_NONE or POLY_FORMAT_LIGHT0 or POLY_FOG);
-
- glPopMatrix(1);
- end;
- end;
- var
- thisXY: touchPosition;
- lastXY: touchPosition;
- dx, dy: cint16;
- i: integer;
- held: integer;
- begin
- MyFile := pchar(@World_txt);
- // Setup the Main screen for 3D
- videoSetMode(MODE_0_3D);
- vramSetBankA(VRAM_A_TEXTURE); //NEW must set up some memory for textures
- consoleDemoInit();
- // initialize the geometry engine
- glInit();
- // enable textures
- glEnable(GL_TEXTURE_2D);
- // enable antialiasing
- glEnable(GL_ANTIALIAS);
- // enable alpha blending for shadow demo
- glEnable(GL_BLEND);
- // setup the rear plane
- glClearColor(0,0,0,31); // BG must be opaque for AA to work
- glClearPolyID(63); // BG must have a unique polygon ID for AA to work
- glClearDepth($7FFF);
- // Set our viewport to be the same size as the screen
- glViewport(0,0,255,191);
- LoadGLTextures();
- SetupWorld();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(70, 256.0 / 192.0, 0.1, 100);
- glLight(0, RGB15(31,31,31) , 0, floattov10(-1.0), 0);
- //need to set up some material properties since DS does not have them set by default
- glMaterialf(GL_AMBIENT, RGB15(16,16,16));
- glMaterialf(GL_DIFFUSE, RGB15(16,16,16));
- glMaterialf(GL_SPECULAR, BIT(15) or RGB15(8,8,8));
- glMaterialf(GL_EMISSION, RGB15(16,16,16));
- //ds uses a table for shinyness..this generates a half-ass one
- glMaterialShinyness();
- //ds specific, several attributes can be set here
- glPolyFmt(POLY_ALPHA(31) or POLY_CULL_NONE or POLY_FORMAT_LIGHT0 or POLY_FOG);
- // Set the current matrix to be the model matrix
- glMatrixMode(GL_MODELVIEW);
- //setup demo fog parameters
- //these parameters are somewhat arbitrary, and designed to illustrate fog in just this one case.
- //you will certainly need to tweak them for your own use.
- //be sure to have set the POLY_FOG bit on any material you want to be fogged.
- glEnable(GL_FOG);
- glFogShift(2);
- glFogColor(0, 0, 0, 0);
- for i := 0 to 31 do
- glFogDensity(i, i * 4);
- glFogDensity(31, 127);
- glFogOffset($6000);
- while true do
- begin
- //these little button functions are pretty handy
- scanKeys();
- held := keysHeld();
- if (held and KEY_A) <> 0 then lookupdown := lookupdown - 1.0;
- if (held and KEY_B) <> 0 then lookupdown := lookupdown + 1.0;
- if (held and KEY_LEFT) <> 0 then
- begin
- heading := heading + 1.0;
- yrot := heading;
- end;
- if (held and KEY_RIGHT) <> 0 then
- begin
- heading := heading - 1.0;
- yrot := heading;
- end;
- if (held and KEY_DOWN) <> 0 then
- begin
- xpos := xpos + (tsin(heading)) * 0.05;
- zpos := zpos + (tcos(heading)) * 0.05;
- if (walkbiasangle >= 359.0) then
- walkbiasangle := 0.0
- else
- walkbiasangle:= walkbiasangle+10;
- walkbias := tsin(walkbiasangle) / 20.0;
- end;
- if (held and KEY_UP) <> 0 then
- begin
- xpos := xpos - (tsin(heading)) * 0.05;
- zpos := zpos - (tcos(heading)) * 0.05;
- if (walkbiasangle <= 1.0) then
- walkbiasangle := 359.0
- else
- walkbiasangle := walkbiasangle- 10;
- walkbias := tsin(walkbiasangle) / 20.0;
- end;
- glColor3f(1,1,1);
- DrawGLScene();
- // flush to screen
- glFlush(0);
- // wait for the screen to refresh
- swiWaitForVBlank();
-
- if (held and KEY_START) <> 0 then break;
- end;
- end.
|