diff --git a/Driver.cpp b/Driver.cpp new file mode 100644 index 0000000..b4e6a9d --- /dev/null +++ b/Driver.cpp @@ -0,0 +1,45 @@ +#ifdef _WIN32 +#include +#endif +#include +#include +#include "Model.h" +#include "Obj.h" + +void usage(){ + std::cout << "Please specify paths to models" << std::endl; +} + +void draw(Model::Model* model){ + glEnable(GL_TEXTURE_2D); + // glBindTexture(GL_TEXTURE_2D, texturen[0]); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, model->normals); + + glTexCoordPointer(2,GL_FLOAT,0, model->textures ); + glVertexPointer(3,GL_FLOAT, 0,model->triangles); + glDrawArrays(GL_TRIANGLES, 0, model->totalConnectedTriangles); + + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glDisable(GL_TEXTURE_2D); +} + +void main(int argc, char** argv){ + /* + //TODO, parse argv + if(argc < 1){ + usage(); + return; + } + */ + + Model::Model* m = new Model::Obj(); + m->load("cube.obj"); + +} \ No newline at end of file diff --git a/Md2.cpp b/Md2.cpp new file mode 100644 index 0000000..3ebbf3e --- /dev/null +++ b/Md2.cpp @@ -0,0 +1,708 @@ +/* + * Just the class to load Quake 2 .MD2 and PCX files in OpenGL/GLUT. + * + * + * Needs A LOT OF refactoring and cleaning! + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + + +class Model_MD2 +{ + public: + void LoadPCX(char* textureFilename); + int Load(char *filename, char* textureFilename); + void Draw(); + void Play(int animation); + + void Stand(); + void Run(); + void Attack(); + void Pain1(); + void Pain2(); + void Pain3(); + void Jump(); + void Flip(); + void Salute(); // 10 + void Taunt(); // 16 + void Wave(); // 10 + void Point(); //11 + void Crstnd(); // 18 + void Crwalk(); // 5 + void Crattack(); // 8 + void Crpain(); // 3 + void Crdeath(); // 4 + void Death1(); // 5 + void Death2(); // 5 + void Death3(); // 7 + + Model_MD2(); + + float Points[1000000]; + float Faces_Triangles[512][14096]; + float Normals[1000000]; + float Faces_Textures[512][14096]; + + float TextureCoords[120048]; + + int TotalConnectedPoints; + int TotalConnectedTriangles; + + int Scale; + int AngleX, AngleY, AngleZ; + + private: + + typedef struct _MD2_Header + { + int ident; // identifies as quake II header (IDP2) + int version; // mine is 8 + int skinwidth; // width of texture + int skinheight; // height of texture + int framesize; // number of bytes per frame + int numSkins; // number of textures + int numXYZ; // number of points + int numST; // number of texture + int numTris; // number of triangles + int numGLcmds; + int numFrames; // total number of frames + int offsetSkins; // offset to skin names (64 bytes each) + int offsetST; // offset of texture s-t values + int offsetTris; // offset of triangle mesh + int offsetFrames; // offset of frame data (points) + int offsetGLcmds; + int offsetEnd; // end of file + } MD2_Header; + + typedef struct _framePoint + { + unsigned char v[3]; // the vertex + unsigned char lightNormalIndex; + } framePoint; + + typedef struct _frame + { + float scale[3]; // vetex scaling + float translate[3]; // vertex translation + char name[16]; // name of this model + framePoint fp[1]; // start of a list of framePoints + } frame; + + typedef struct _mesh + { + unsigned short meshIndex[3]; // indices to triangle vertices + unsigned short stIndex[3]; // indices to texture coordinates + } mesh; + + int framenr; + int updatecounter; + frame *frm; + + int frame_length[3]; + int frame_start[3]; + int animation; + + int texWidth; + int texHeight; + int imgWidth; + int imgHeight; + unsigned char* texture; + unsigned int texturen[1]; +}; + + +typedef struct _pcxHeader +{ + short id[2]; + short offset[2]; + short size[2]; +} pcxHeader; + +struct Mesh_UV + { + unsigned short s; + unsigned short t; + }; + + +float* calculateNormal( float *coord1, float *coord2, float *coord3 ) +{ + /* calculate Vector1 and Vector2 */ + float va[3], vb[3], vr[3], val; + va[0] = coord1[0] - coord2[0]; + va[1] = coord1[1] - coord2[1]; + va[2] = coord1[2] - coord2[2]; + + vb[0] = coord1[0] - coord3[0]; + vb[1] = coord1[1] - coord3[1]; + vb[2] = coord1[2] - coord3[2]; + + /* cross product */ + vr[0] = va[1] * vb[2] - vb[1] * va[2]; + vr[1] = vb[0] * va[2] - va[0] * vb[2]; + vr[2] = va[0] * vb[1] - vb[0] * va[1]; + + /* normalization factor */ + val = sqrt( vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2] ); + + // glNormal3f( vr[0]/val, vr[1]/val, vr[2]/val ); + float norm[3]; + norm[0] = vr[0]/val; + norm[1] = vr[1]/val; + norm[2] = vr[2]/val; + + + return norm; +} + + +Model_MD2::Model_MD2() +{ + this->Scale = 1; + framenr = 0; + updatecounter = 0; + + frame_length[0] = 39; // stand + frame_length[1] = 5; // run + frame_length[2] = 7; // attack + frame_length[3] = 3; // "pain1" + frame_length[4] = 3; // "pain2" 3 + frame_length[5] = 3; // "pain3" 3 + frame_length[6] = 5; // "jump" 5 + frame_length[7] = 11; // "flip" 11 + frame_length[8] = 10; // "salute" 10 + frame_length[9] = 16; // "taunt" 16 + frame_length[10] = 10; // "wave" 10 + + + frame_start[0] = 0; // stand + frame_start[1] = 39; // run + frame_start[2] = 46; // shoot + frame_start[3] = 50; // pain1 + frame_start[4] = 39 + 5+ 7 + 3; + frame_start[5] = frame_length[0] + frame_length[1] + frame_length[2] + frame_length[3] + frame_length[4]; + + + animation = 0; +} + + + +void Model_MD2::LoadPCX(char* textureFilename) +{ + // Load texture + FILE* texFile = fopen(textureFilename,"rb"); + + if (texFile) + { + int imgWidth, imgHeight, texFileLen, imgBufferPtr, i; + pcxHeader *pcxPtr; + unsigned char *imgBuffer, *texBuffer, *pcxBufferPtr, *paletteBuffer; + + /* find length of file */ + fseek( texFile, 0, SEEK_END ); + texFileLen = ftell( texFile ); + fseek( texFile, 0, SEEK_SET ); + + /* read in file */ + texBuffer = (unsigned char*) malloc( texFileLen+1 ); + fread( texBuffer, sizeof( char ), texFileLen, texFile ); + + /* get the image dimensions */ + pcxPtr = (pcxHeader *)texBuffer; + imgWidth = pcxPtr->size[0] - pcxPtr->offset[0] + 1; + imgHeight = pcxPtr->size[1] - pcxPtr->offset[1] + 1; + + this->imgWidth = imgWidth; + this->imgHeight = imgHeight; + + /* image starts at 128 from the beginning of the buffer */ + imgBuffer = (unsigned char*) malloc( imgWidth * imgHeight ); + imgBufferPtr = 0; + pcxBufferPtr = &texBuffer[128]; + /* decode the pcx image */ + while( imgBufferPtr < (imgWidth * imgHeight) ) + { + if( *pcxBufferPtr > 0xbf ) + { + int repeat = *pcxBufferPtr++ & 0x3f; + for( i=0; itexWidth = pow( 2, (double) i ); + i = 0; + while( imageHeight ) + { + imageHeight /= 2; + i++; + } + this->texHeight = pow( 2, (double) i ); + } + /* now create the OpenGL texture */ + { + int i, j; + this->texture = (unsigned char*) malloc( this->texWidth * this->texHeight * 3 ); + for (j = 0; j < imgHeight; j++) + { + for (i = 0; i < imgWidth; i++) + { + this->texture[3*(j * this->texWidth + i)+0] + = paletteBuffer[ 3*imgBuffer[j*imgWidth+i]+0 ]; + this->texture[3*(j * this->texWidth + i)+1] + = paletteBuffer[ 3*imgBuffer[j*imgWidth+i]+1 ]; + this->texture[3*(j * this->texWidth + i)+2] + = paletteBuffer[ 3*imgBuffer[j*imgWidth+i]+2 ]; + } + } + } + + + /* cleanup */ + free( paletteBuffer ); + free( imgBuffer ); + + + + /* + glGenTextures( 1, &texturen[0] ); + glBindTexture( GL_TEXTURE_2D, texturen[0] ); + + //Generate The Texture + glTexImage2D( GL_TEXTURE_2D, 0, 3, this->texWidth, + this->texHeight, 0, GL_RGB, + GL_UNSIGNED_BYTE, this->texture ); + + printf(" %i %i ", this->texWidth, this->texHeight); + // Linear Filtering + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + */ + } + +} + +int Model_MD2::Load(char* filename, char* textureFilename) +{ + + LoadPCX(textureFilename); + // Load model + MD2_Header *mdh; + + mesh* m; + + for (int i = 0; i < TotalConnectedTriangles; i++){ Faces_Triangles[0][i] = 0x00; } + this->AngleX = 0; + this->AngleY = 0; + this->AngleZ = 0; + this->Scale = 1; + this->TotalConnectedTriangles = 0; + + char* pch = strstr(filename,".md2"); + + if (pch != NULL) + { + FILE* file = fopen(filename,"r"); + + if (file) + { + + // get size of file + fseek( file, 0, SEEK_END ); + size_t fileSize = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // read in entire file + char* buffer; + buffer = (char*) malloc( fileSize+1 ); + fread( buffer, sizeof( char ), fileSize, file ); + + + // start analyzing the buffer + mdh = (MD2_Header *)buffer; + + printf("mdh framesize %i \n", mdh->framesize); + + for (int z = 0; z< mdh->numFrames; z++) + { + frm = (frame *)&buffer[ mdh->offsetFrames + z*mdh->framesize ]; + m = (mesh *)&buffer[mdh->offsetTris]; + int ti = 0; + int point_index = 0; + + /* offset to points of frame */ + for(int i=0; inumXYZ; i++ ) + { + this->Points[point_index] = frm->scale[0] * frm->fp[i].v[0] + frm->translate[0]; // X + this->Points[point_index+1] = frm->scale[1] * frm->fp[i].v[1] + frm->translate[1]; // Y + this->Points[point_index+2] = frm->scale[2] * frm->fp[i].v[2] + frm->translate[2]; // Z + point_index += 3; + } + this->TotalConnectedTriangles = mdh->numTris * 3; + int n = 0; + + //------------------------------------------------------------- + //-- create texture coordinate list --------------------------- + + ti = 0; + + for(int i=0; inumST; i++ ) + { + Mesh_UV* mUV = (Mesh_UV *)&buffer[mdh->offsetST + i*4 ]; + + this->TextureCoords[ti] = (float) mUV->s / this->texWidth; + this->TextureCoords[ti+1] = (float) mUV->t / this->texHeight; + // printf(" (%i %i) ", mUV->s, mUV->t); + // printf(" %f %f \n ", this->TextureCoords[ti], this->TextureCoords[ti+1]); + ti+=2; + } + + + //--- + m = (mesh *)&buffer[mdh->offsetTris]; + + n = 0; + ti = 0; + + + for(int i=0; inumTris; i++ ) + { + + + this->Faces_Triangles[z][n] = Points[ 3*m[i].meshIndex[0] ]; + this->Faces_Triangles[z][n+1] = Points[ 3*m[i].meshIndex[0]+1 ]; + this->Faces_Triangles[z][n+2] = Points[ 3*m[i].meshIndex[0]+2 ]; + + this->Faces_Textures[z][ti] = this->TextureCoords[ 2*m[i].stIndex[0] ]; + this->Faces_Textures[z][ti+1] = this->TextureCoords[ 2*m[i].stIndex[0]+1 ]; + + n+=3; + ti += 2; + + this->Faces_Triangles[z][n] = Points[ 3*m[i].meshIndex[1] ]; + this->Faces_Triangles[z][n+1] = Points[3* m[i].meshIndex[1]+1 ]; + this->Faces_Triangles[z][n+2] = Points[3* m[i].meshIndex[1]+2 ]; + + this->Faces_Textures[z][ti] = TextureCoords[ 2*m[i].stIndex[1] ]; + this->Faces_Textures[z][ti+1] = TextureCoords[ 2*m[i].stIndex[1] + 1 ]; + + n+=3; + ti += 2; + + this->Faces_Triangles[z][n] = Points[3* m[i].meshIndex[2] ]; + this->Faces_Triangles[z][n+1] = Points[3* m[i].meshIndex[2]+1 ]; + this->Faces_Triangles[z][n+2] = Points[3* m[i].meshIndex[2]+2 ]; + + this->Faces_Textures[z][ti] = TextureCoords[ 2*m[i].stIndex[2] ]; + this->Faces_Textures[z][ti+1] = TextureCoords[ 2*m[i].stIndex[2] + 1 ]; + + n+=3; + ti += 2; + + + + // m = (mesh *)&buffer[mdh->offsetTris + 12*i ]; + } + } + //mdh->offsetST + + printf("\n"); + + mdh = (MD2_Header *)buffer; + + for (int i = 0; i< 10; i+=2) + { + printf(" %f %f \n", this->Faces_Textures[0][i], this->Faces_Textures[0][i+1]); + } + + int normal_index = 0; + for (int triangle_index = 0; triangle_index < TotalConnectedTriangles*9; triangle_index += 9) + { + float coord1[3] = { Faces_Triangles[0][triangle_index], Faces_Triangles[0][triangle_index+1],Faces_Triangles[0][triangle_index+2]}; + float coord2[3] = {Faces_Triangles[0][triangle_index+3],Faces_Triangles[0][triangle_index+4],Faces_Triangles[0][triangle_index+5]}; + float coord3[3] = {Faces_Triangles[0][triangle_index+6],Faces_Triangles[0][triangle_index+7],Faces_Triangles[0][triangle_index+8]}; + float *norm = calculateNormal( coord1, coord2, coord3 ); + + printf("\nnormal %f %f %f \n", norm[0],norm[1],norm[2]); + + Normals[normal_index] = norm[0]; + Normals[normal_index+1] = norm[1]; + Normals[normal_index+2] = norm[2]; + + Normals[normal_index+3] = norm[0]; + Normals[normal_index+4] = norm[1]; + Normals[normal_index+5] = norm[2]; + + Normals[normal_index+6] = norm[0]; + Normals[normal_index+7] = norm[1]; + Normals[normal_index+8] = norm[2]; + + normal_index += 9; + } + + + } + else { printf("File can't be opened\n"); } + } else { + printf("File does not have a .MD2 extension. "); + } + + return 0; +} + +void Model_MD2::Play(int animation) +{ + updatecounter++; + if (updatecounter > 10) + { + //if (framenr == frame_length[animation]) + // framenr = 0; + //else + //{ + //if (framenr < frame_length[animation]) framenr++; + //} + framenr++; + printf("%i \n", framenr); + //framenr++; + updatecounter = 0; + } + + this->animation = animation; +} + + +void Model_MD2::Crstnd() +{ + updatecounter++; + if (updatecounter > 10) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 147) framenr = 147; + if (framenr < 147+5) framenr++; else framenr = 147; + + updatecounter = 0; + } +} + +void Model_MD2::Point() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 121) framenr = 121; + if (framenr < 121+11) framenr++; else framenr = 121; + + updatecounter = 0; + } +} + +void Model_MD2::Wave() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 111) framenr = 111; + if (framenr < 111+10) framenr++; else framenr = 111; + + updatecounter = 0; + } +} + +void Model_MD2::Taunt() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 91) framenr = 91; + if (framenr < 91+20) framenr++; else framenr = 91; + + updatecounter = 0; + } +} + +void Model_MD2::Salute() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 81) framenr = 81; + if (framenr < 81+10) framenr++; else framenr = 81; + + updatecounter = 0; + } +} + +void Model_MD2::Flip() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 69) framenr = 69; + if (framenr < 69+11) framenr++; else framenr = 69; + + updatecounter = 0; + } +} + +void Model_MD2::Jump() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 64) framenr = 64; + if (framenr < 64+5) framenr++; else framenr = 64; + + updatecounter = 0; + } +} + +void Model_MD2::Pain3() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 59) framenr = 59; + if (framenr < 59+3) framenr++; else framenr = 59; + + updatecounter = 0; + } +} + +void Model_MD2::Pain2() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 56) framenr = 56; + if (framenr < 56+3) framenr++; else framenr = 56; + + updatecounter = 0; + } + +} + +void Model_MD2::Pain1() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 53) framenr = 53; + if (framenr < 53+3) framenr++; else framenr = 53; + + updatecounter = 0; + } + + this->animation = 1; +} + +void Model_MD2::Attack() +{ + updatecounter++; + if (updatecounter > 20) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 46) framenr = 46; + if (framenr < 46+7) framenr++; else framenr = 46; + + updatecounter = 0; + } + + this->animation = 1; +} + +void Model_MD2::Run() +{ + updatecounter++; + if (updatecounter > 1) + { + //if (framenr == (framenr+frame_length[animation]) ) framenr = 0; else framenr++; + if (framenr < 40) framenr = 40; + if (framenr < 40+5) framenr++; else framenr = 40; + + updatecounter = 0; + } + + this->animation = 1; + +} + + +void Model_MD2::Stand() +{ + updatecounter++; + if (updatecounter > 1) + { + if (framenr > 28) framenr = 0; else framenr++; + updatecounter = 0; + } + + this->animation = 0; + +} + +/* +void Model_MD2::Draw() +{ + /* + glRasterPos2i(0,0); + glDrawPixels(this->texWidth , this->texHeight, GL_RGB, GL_UNSIGNED_BYTE, this->texture); +*/ +/* + + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texturen[0]); + + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, Normals); + + glTexCoordPointer(2,GL_FLOAT,0, this->Faces_Textures[ framenr] ); + glVertexPointer(3,GL_FLOAT, 0,Faces_Triangles[ framenr ]); + glDrawArrays(GL_TRIANGLES, 0, TotalConnectedTriangles); + + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glDisable(GL_TEXTURE_2D); +}*/ \ No newline at end of file diff --git a/Model.cpp b/Model.cpp new file mode 100644 index 0000000..92f1ba7 --- /dev/null +++ b/Model.cpp @@ -0,0 +1,34 @@ +#include "Model.h" +namespace Model { + Model::Model(){ + totalConnectedTriangles = 0; + totalConnectedPoints = 0; + } + + float* Model::calculateNormal(float* coord1, float* coord2, float* coord3){ + /* calculate Vector1 and Vector2 */ + float va[3], vb[3], vr[3], val; + va[0] = coord1[0] - coord2[0]; + va[1] = coord1[1] - coord2[1]; + va[2] = coord1[2] - coord2[2]; + + vb[0] = coord1[0] - coord3[0]; + vb[1] = coord1[1] - coord3[1]; + vb[2] = coord1[2] - coord3[2]; + + /* cross product */ + vr[0] = va[1] * vb[2] - vb[1] * va[2]; + vr[1] = vb[0] * va[2] - va[0] * vb[2]; + vr[2] = va[0] * vb[1] - vb[0] * va[1]; + + /* normalization factor */ + val = sqrt( vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2] ); + + float norm[3]; + norm[0] = vr[0]/val; + norm[1] = vr[1]/val; + norm[2] = vr[2]/val; + + return norm; + } +} diff --git a/Model.h b/Model.h new file mode 100644 index 0000000..3edc7d9 --- /dev/null +++ b/Model.h @@ -0,0 +1,35 @@ +#ifndef Model_h__ +#define Model_h__ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace Model { +#define POINTS_PER_VERTEX 3 +#define TOTAL_FLOATS_IN_TRIANGLE 9 +#define KEY_ESCAPE 27 + class Model { + public: + Model(); + float* Model::calculateNormal(float* coord1,float* coord2,float* coord3 ); + virtual bool Model::load(char *filename) = 0; + virtual void Model::release() = 0; + + float* normals; + float* triangles; + float* vertices; + float* textures; + long totalConnectedPoints; + long totalConnectedTriangles; + }; +} + +#endif // Model_h__ diff --git a/Obj.cpp b/Obj.cpp new file mode 100644 index 0000000..8e87eaf --- /dev/null +++ b/Obj.cpp @@ -0,0 +1,98 @@ +#include "Obj.h" + +namespace Model { + bool Obj::load(char* filename) { + std::string line; + std::ifstream objFile (filename); + if (objFile.is_open() == false) // we could not open the file + return false; + + objFile.seekg (0, std::ios::end); // Go to end of the file, + long fileSize = objFile.tellg(); // get file size + objFile.seekg (0, std::ios::beg); // we'll use this to register memory for our 3d model + + vertices = new float[fileSize]; // Allocate memory for the vertices + triangles = new float[fileSize]; // Allocate memory for the triangles + normals = new float[fileSize]; // Allocate memory for the normals + + int triangle_index = 0; // Set triangle index to zero + int normal_index = 0; // Set normal index to zero + + while (! objFile.eof() ) // Start reading file data + { + getline (objFile,line); // Get line from file + + if (line.c_str()[0] == 'v') // The first character is a v: on this line is a vertex stored. + { + line[0] = ' '; // Set first character to 0. This will allow us to use sscanf + + sscanf(line.c_str(),"%f %f %f ", // Read floats from the line: v X Y Z + &vertices[totalConnectedPoints], + &vertices[totalConnectedPoints+1], + &vertices[totalConnectedPoints+2]); + + totalConnectedPoints += POINTS_PER_VERTEX; // Add 3 to the total connected points + } + else if (line.c_str()[0] == 'f') // The first character is an 'f': on this line is a point stored + { + line[0] = ' '; // Set first character to 0. This will allow us to use sscanf + + int vertexNumber[4] = { 0, 0, 0 }; + sscanf(line.c_str(),"%i%i%i", // Read integers from the line: f 1 2 3 + &vertexNumber[0], // First point of our triangle. This is an + &vertexNumber[1], // pointer to our vertices list + &vertexNumber[2] ); // each point represents an X,Y,Z. + + vertexNumber[0] -= 1; // OBJ file starts counting from 1 + vertexNumber[1] -= 1; // OBJ file starts counting from 1 + vertexNumber[2] -= 1; // OBJ file starts counting from 1 + + + /******************************************************************** + * Create triangles (f 1 2 3) from points: (v X Y Z) (v X Y Z) (v X Y Z). + * The vertices contains all verteces + * The triangles will be created using the verteces we read previously + */ + + int tCounter = 0; + for (int i = 0; i < POINTS_PER_VERTEX; i++) { + triangles[triangle_index + tCounter ] = vertices[3*vertexNumber[i] ]; + triangles[triangle_index + tCounter +1 ] = vertices[3*vertexNumber[i]+1 ]; + triangles[triangle_index + tCounter +2 ] = vertices[3*vertexNumber[i]+2 ]; + tCounter += POINTS_PER_VERTEX; + } + + /********************************************************************* + * Calculate all normals, used for lighting + */ + float coord1[3] = { triangles[triangle_index], triangles[triangle_index+1],triangles[triangle_index+2]}; + float coord2[3] = {triangles[triangle_index+3],triangles[triangle_index+4],triangles[triangle_index+5]}; + float coord3[3] = {triangles[triangle_index+6],triangles[triangle_index+7],triangles[triangle_index+8]}; + float *norm = calculateNormal( coord1, coord2, coord3 ); + + tCounter = 0; + for (int i = 0; i < POINTS_PER_VERTEX; i++) { + normals[normal_index + tCounter ] = norm[0]; + normals[normal_index + tCounter +1] = norm[1]; + normals[normal_index + tCounter +2] = norm[2]; + tCounter += POINTS_PER_VERTEX; + } + + triangle_index += TOTAL_FLOATS_IN_TRIANGLE; + normal_index += TOTAL_FLOATS_IN_TRIANGLE; + totalConnectedTriangles += TOTAL_FLOATS_IN_TRIANGLE; + } else { + std::cout << "Unhandled line: " << line << std::endl; + } + } + objFile.close(); // Close OBJ file + + return true; + } + + void Obj::release() { + delete[] triangles; + delete[] normals; + delete[] vertices; + } +} \ No newline at end of file diff --git a/Obj.h b/Obj.h new file mode 100644 index 0000000..1540e53 --- /dev/null +++ b/Obj.h @@ -0,0 +1,23 @@ +/* +* +* Demonstrates how to load and display an Wavefront OBJ file. +* Using triangles and normals as static object. No texture mapping. +* +* OBJ files must be triangulated!!! +* Non triangulated objects wont work! +* You can use Blender to triangulate +* +*/ + +#include "Model.h" + +namespace Model { + class Obj : public Model { + public: + bool Obj::load(char *filename); // Loads the model + void Obj::release(); // Release the model + }; +} + +#define POINTS_PER_VERTEX 3 +#define TOTAL_FLOATS_IN_TRIANGLE 9 diff --git a/Ply.cpp b/Ply.cpp new file mode 100644 index 0000000..ab02f1f --- /dev/null +++ b/Ply.cpp @@ -0,0 +1,158 @@ +/* Demonstrates how to load Ply files +* Needs some refactoring. +* +* Model needs to be triangulated +* Use blender +* +* Just the class for loading Ply files. +* +*/ + +#include "Ply.h" + +namespace Model { + Ply::Ply() { + totalConnectedQuads = 0; + totalFaces = 0; + } + + + bool Ply::load(char* filename) { + + char* pch = strstr(filename,".ply"); + + if (pch != NULL) { + FILE* file = fopen(filename,"r"); + + if(file == NULL) + return false; + + fseek(file,0,SEEK_END); + long fileSize = ftell(file); + + try { + vertices = (float*) malloc (ftell(file)); + } + catch (char* ) { + return false; + } + if (vertices == NULL) return -1; + fseek(file,0,SEEK_SET); + + triangles = (float*) malloc(fileSize*sizeof(float)); + normals = (float*) malloc(fileSize*sizeof(float)); + + int i = 0; + int temp = 0; + int quads_index = 0; + int triangle_index = 0; + int normal_index = 0; + char buffer[1000]; + + + fgets(buffer,300,file); // ply + + + // READ HEADER + // ----------------- + + // Find number of vertexes + while ( strncmp( "element vertex", buffer,strlen("element vertex")) != 0 ) + { + fgets(buffer,300,file); // format + } + strcpy(buffer, buffer+strlen("element vertex")); + sscanf(buffer,"%i", &this->totalConnectedPoints); + + + // Find number of vertexes + fseek(file,0,SEEK_SET); + while ( strncmp( "element face", buffer,strlen("element face")) != 0 ) + { + fgets(buffer,300,file); // format + } + strcpy(buffer, buffer+strlen("element face")); + sscanf(buffer,"%i", &totalFaces); + + + // go to end_header + while ( strncmp( "end_header", buffer,strlen("end_header")) != 0 ) + { + fgets(buffer,300,file); // format + } + + //---------------------- + + + // read verteces + i =0; + for (int iterator = 0; iterator < this->totalConnectedPoints; iterator++) + { + fgets(buffer,300,file); + + sscanf(buffer,"%f %f %f", &vertices[i], &vertices[i+1], &vertices[i+2]); + i += 3; + } + + // read faces + i =0; + for (int iterator = 0; iterator < totalFaces; iterator++) + { + fgets(buffer,300,file); + + if (buffer[0] == '3') + { + + int vertex1 = 0, vertex2 = 0, vertex3 = 0; + //sscanf(buffer,"%i%i%i\n", vertex1,vertex2,vertex3 ); + buffer[0] = ' '; + sscanf(buffer,"%i%i%i", &vertex1,&vertex2,&vertex3 ); + /*vertex1 -= 1; + vertex2 -= 1; + vertex3 -= 1; + */ + // vertex == punt van vertex lijst + // vertex_buffer -> xyz xyz xyz xyz + //printf("%f %f %f ", vertices[3*vertex1], vertices[3*vertex1+1], vertices[3*vertex1+2]); + + triangles[triangle_index] = vertices[3*vertex1]; + triangles[triangle_index+1] = vertices[3*vertex1+1]; + triangles[triangle_index+2] = vertices[3*vertex1+2]; + triangles[triangle_index+3] = vertices[3*vertex2]; + triangles[triangle_index+4] = vertices[3*vertex2+1]; + triangles[triangle_index+5] = vertices[3*vertex2+2]; + triangles[triangle_index+6] = vertices[3*vertex3]; + triangles[triangle_index+7] = vertices[3*vertex3+1]; + triangles[triangle_index+8] = vertices[3*vertex3+2]; + + float coord1[3] = { triangles[triangle_index], triangles[triangle_index+1],triangles[triangle_index+2]}; + float coord2[3] = {triangles[triangle_index+3],triangles[triangle_index+4],triangles[triangle_index+5]}; + float coord3[3] = {triangles[triangle_index+6],triangles[triangle_index+7],triangles[triangle_index+8]}; + float *norm = this->calculateNormal( coord1, coord2, coord3 ); + + normals[normal_index] = norm[0]; + normals[normal_index+1] = norm[1]; + normals[normal_index+2] = norm[2]; + normals[normal_index+3] = norm[0]; + normals[normal_index+4] = norm[1]; + normals[normal_index+5] = norm[2]; + normals[normal_index+6] = norm[0]; + normals[normal_index+7] = norm[1]; + normals[normal_index+8] = norm[2]; + + normal_index += 9; + + triangle_index += 9; + totalConnectedTriangles += 3; + } + + + i += 3; + } + fclose(file); + } else { + std::cerr << "File does not have a .Ply extension. " << std::endl; + } + return 0; + } +} diff --git a/Ply.h b/Ply.h new file mode 100644 index 0000000..a25176b --- /dev/null +++ b/Ply.h @@ -0,0 +1,12 @@ +#include "Model.h" +namespace Model { + class Ply : public Model { + public: + Ply(); + bool Ply::load(char *filename); + + float* quads; + int totalConnectedQuads; + int totalFaces; + }; +} diff --git a/README b/README new file mode 100644 index 0000000..f20f981 --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +OpenGL model loaders based on +http://openglsamples.sourceforge.net/projects/index.php/blog/index/ + +There were some things that bugged me that I felt compelled to improve diff --git a/Raw.cpp b/Raw.cpp new file mode 100644 index 0000000..028b83a --- /dev/null +++ b/Raw.cpp @@ -0,0 +1,116 @@ +/* + * Just the class to load Blender .RAW files in OpenGL/GLUT. + * Needs refactoring + * + * RAW files are static objects, stored in ASCII + * No animation, texture mapping or normals + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Model_RAW +{ + public: + Model_RAW(); + int Model_RAW::Load(char *filename); + void Model_RAW::Draw(); + float* Model_RAW::calculateNormal(float* coord1,float* coord2,float* coord3 ); + + float* Normals; + float* Faces_Triangles; + float* Vertex_Buffer; + long TotalConnectedPoints; + long TotalConnectedTriangles; + +}; + + +Model_RAW::Model_RAW() +{ + +} + +int Model_RAW::Load(char* filename) +{ + for (int i = 0; i < TotalConnectedTriangles; i++){ Faces_Triangles[i] = 0x00; } + this->TotalConnectedTriangles = 0; + + char* pch = strstr(filename,".raw"); + + if (pch != NULL) + { + FILE* file = fopen(filename,"r"); + + fseek(file,0,SEEK_END); + long fileSize = ftell(file); + + try + { + Vertex_Buffer = (float*) malloc (ftell(file)*3); + } + catch (char* ) + { + return -1; + } + if (Vertex_Buffer == NULL) return -1; + fseek(file,0,SEEK_SET); + + Faces_Triangles = (float*) malloc(fileSize*sizeof(float)); + Normals = (float*) malloc(fileSize*sizeof(float)); + + // start reading the data + if (file) + { + int i = 0; + int quads_index = 0; + int normal_index = 0; + char buffer[1000]; + + // read file + while (!feof(file)) + { + + fgets(buffer,1000,file); + + sscanf(buffer,"%f %f %f %f %f %f %f %f %f ", &Faces_Triangles[i], &Faces_Triangles[i+1], &Faces_Triangles[i+2], + &Faces_Triangles[i+3], &Faces_Triangles[i+4], &Faces_Triangles[i+5], + &Faces_Triangles[i+6], &Faces_Triangles[i+7], &Faces_Triangles[i+8]); + + + + float coord1[3] = { Faces_Triangles[i], Faces_Triangles[i+1],Faces_Triangles[i+2]}; + float coord2[3] = {Faces_Triangles[i+3],Faces_Triangles[i+4],Faces_Triangles[i+5]}; + float coord3[3] = {Faces_Triangles[i+6],Faces_Triangles[i+7],Faces_Triangles[i+8]}; + + i += 9; + TotalConnectedTriangles+=9; + } + printf("Opened \n"); + } + else { printf("File can't be opened\n"); } + } else { + printf("File does not have a .raw extension. "); + } + return 0; +} + +void Model_RAW::Draw() +{ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + glVertexPointer(3,GL_FLOAT, 0,Faces_Triangles); + glNormalPointer(GL_FLOAT, 0, Normals); + glDrawArrays(GL_TRIANGLES, 0, TotalConnectedTriangles); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); +} \ No newline at end of file