libnds

Graphics/3D/nehe/lesson10/source/nehe10.cpp

/****************************************
 *      NDS NeHe Lesson 10              *
 *      Author: Dovoto                  *
 ****************************************/

// include your ndslib
#include <nds.h>
#include <malloc.h>
#include <stdio.h>

//needed to load pcx files
#include <nds/arm9/image.h>
#include <nds/arm9/trig_lut.h>


#include "Mud_pcx.h"
#include "World_txt.h"
#include "drunkenlogo_pcx.h"


int DrawGLScene();

const float piover180 = 0.0174532925f;
float heading;
float xpos;
float zpos;

float yrot = 0;
float walkbias = 0;
float walkbiasangle = 0;
float lookupdown = 0.0f;

int texture[2];

typedef struct tagVERTEX
{
    float x, y, z;
    float u, v;
} VERTEX;

typedef struct tagTRIANGLE
{
    VERTEX vertex[3];
} TRIANGLE;

typedef struct tagSECTOR
{
    int numtriangles;
    TRIANGLE* triangle;
} SECTOR;

  SECTOR sector1;               // Our Model Goes Here:


float sin(float angle)
{
    int32 s = sinLerp((short)(angle * DEGREES_IN_CIRCLE / 360));

    return f32tofloat(s);
}

float cos(float angle)
{
    int32 c = cosLerp((short)(angle * DEGREES_IN_CIRCLE / 360));

    return f32tofloat(c);
}
 u8* file = (u8*)World_txt;

 void myGetStr(char* buff, int size)
{
    *buff = *file++;

    while( (*buff != '\n') && (*buff != 0xD))
    {
        buff++;
        *buff = *file++;
    }
    
    buff[0] = '\n'; 
    buff[1] = 0;
    
}


void readstr(char *string)
{
    do
    {
        myGetStr(string, 255);
    } while ((string[0] == '/') || (string[0] == '\n' ));
    return;
}

void SetupWorld()
{
    float x, y, z, u, v;
    int numtriangles;
    char oneline[255];

    readstr(oneline);
    sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles);

    sector1.triangle = (TRIANGLE*)malloc(numtriangles*sizeof(TRIANGLE));
    sector1.numtriangles = numtriangles;

    for (int loop = 0; loop < numtriangles; loop++)
    {
        for (int vert = 0; vert < 3; vert++)
        {
            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;
        }
    }
    return;
}
int LoadGLTextures()                                    // Load PCX files And Convert To Textures
{
    sImage pcx;                

    glGenTextures(2, &texture[0]);
    
    //load our texture
    loadPCX((u8*)Mud_pcx, &pcx);
    image8to16(&pcx);

    glBindTexture(0, texture[0]);
    glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_128 , TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD | GL_TEXTURE_WRAP_S | GL_TEXTURE_WRAP_T, pcx.image.data8);
    
    imageDestroy(&pcx);

    loadPCX((u8*)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);
    
    return TRUE;
}

struct CubeRot
{
    float x,y,z;
    CubeRot()
        : x(0), y(0), z(0)
    {
    }
} cubeRot;

void TransformCube()
{
    glRotatef(cubeRot.x,1.0f,0.0f,0.0f);
    glRotatef(cubeRot.y,0.0f,1.0f,0.0f);
    glRotatef(cubeRot.z,0.0f,0.0f,1.0f);
}

void EmitCube()
{
    glPushMatrix();
    glScalef(0.03f,0.03f,0.03f);    
    
    glRotatef(cubeRot.x,1.0f,0.0f,0.0f);
    glRotatef(cubeRot.y,0.0f,1.0f,0.0f);
    glRotatef(cubeRot.z,0.0f,0.0f,1.0f);
        
    glBegin(GL_QUADS);
        // Front Face
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
        // Back Face
        glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
        // Top Face
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
        // Bottom Face
        glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
        // Right face
        glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
        // Left Face
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
    glEnd();
    glPopMatrix(1);
}

void ShadowDemo()
{
    cubeRot.y+=0.8f;
    
    //draw the actual cube
    glPushMatrix();
    glTranslatef(0.0f,0.4f,-0.4f); //draw the cube up in the air
    TransformCube();
    glBindTexture(GL_TEXTURE_2D, texture[1]);
    EmitCube();
    glPopMatrix(1);

    //draw the shadow:
    {
        //draw the cube shadow on the ground
        glPushMatrix();
        glTranslatef(0.0f,0.0f,-0.4f);
        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 | POLY_CULL_FRONT | 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 | POLY_CULL_BACK | POLY_ALPHA(15) | POLY_ID(1) | POLY_FOG);
        EmitCube();
        
        //reset poly attribute
        glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_FORMAT_LIGHT0 | POLY_FOG);
        
        glPopMatrix(1);
    }
}

int main() {

    // 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(0x7FFF);
    
    // 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) | 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) | POLY_CULL_NONE | POLY_FORMAT_LIGHT0 | 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(int i=0;i<32;i++)
        glFogDensity(i,i*4);
    glFogDensity(31,127);
    glFogOffset(0x6000);

    while (1)
    {
        //these little button functions are pretty handy
        scanKeys();
                
    
        if (keysHeld() & KEY_A)
        {
            lookupdown -= 1.0f;
        }
        if (keysHeld() & KEY_B)
        {
            lookupdown += 1.0f;
        }
        if (keysHeld() & KEY_LEFT)
        {
            heading += 1.0f;    
            yrot = heading;
        }
        if (keysHeld() & KEY_RIGHT)
        {
            heading -= 1.0f;
            yrot = heading;
        }
        if (keysHeld() & KEY_DOWN)
        {
            
            xpos += (float)sin(heading) * 0.05f;
            zpos += (float)cos(heading) * 0.05f;

            if (walkbiasangle >= 359.0f)
            {
                walkbiasangle = 0.0f;
            }
            else
            {
                walkbiasangle+= 10;
            }
            
            walkbias = (float)sin(walkbiasangle)/20.0f;
        }
        if (keysHeld() & KEY_UP)
        {
            xpos -= (float)sin(heading) * 0.05f;
            zpos -= (float)cos(heading) * 0.05f;
            if (walkbiasangle <= 1.0f)
            {
                walkbiasangle = 359.0f;
            }
            else
            {
                walkbiasangle-= 10;
            }
            walkbias = (float)sin(walkbiasangle)/20.0f;
        }

        glColor3f(1,1,1);
        
        DrawGLScene();
        
        // flush to screen  
        glFlush(0);
        
        // wait for the screen to refresh
        swiWaitForVBlank();
    }
    
    return 0;
}

int DrawGLScene()                                           // Here's Where We Do All The Drawing
{
                                            // Reset The View

    float x_m, y_m, z_m, u_m, v_m;
    float xtrans = -xpos;
    float ztrans = -zpos;
    float ytrans = -walkbias-0.25f;
    float sceneroty = 360.0f - yrot;
    
    glLoadIdentity();
    
    int numtriangles;

    glRotatef(lookupdown,1.0f,0,0);
    glRotatef(sceneroty,0,1.0f,0);
    
    glTranslatef(xtrans, ytrans, ztrans);
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    
    numtriangles = sector1.numtriangles;
    
    
    // Process Each Triangle
    for (int loop_m = 0; loop_m < numtriangles; loop_m++)
    {
        glBegin(GL_TRIANGLES);
            glNormal3f( 0.0f, 0.0f, 1.0f);
            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();
    }

    ShadowDemo();
    
    return TRUE;                                        // Everything Went OK

}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines