summaryrefslogtreecommitdiffstats
path: root/matchblox/engine/C_3DObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'matchblox/engine/C_3DObject.cpp')
-rw-r--r--matchblox/engine/C_3DObject.cpp336
1 files changed, 336 insertions, 0 deletions
diff --git a/matchblox/engine/C_3DObject.cpp b/matchblox/engine/C_3DObject.cpp
new file mode 100644
index 0000000..3cb00b1
--- /dev/null
+++ b/matchblox/engine/C_3DObject.cpp
@@ -0,0 +1,336 @@
+#include <GL/glut.h>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include "typedefs.h"
+#include "C_3DObject.h"
+
+#include "bitmap.h"
+
+C_3DObject::C_3DObject()
+ : m_Pos(0.0, 0.0, 0.0), m_Rot(0.0, 0.0, 0.0),
+ m_Scale(1.0, 1.0, 1.0),
+ m_bOwnTexture(false),
+ m_bDispListValid(false)
+{
+ std::cout << "C_3DObject:: default constructor\n";
+}
+
+
+C_3DObject::C_3DObject(const char* f_strFileName,
+ char* f_strColorTexName,
+ MatProps_t f_Material)
+ : m_Pos(0.0, 0.0, 0.0), m_Rot(0.0, 0.0, 0.0),
+ m_Scale(1.0, 1.0, 1.0),
+ m_bOwnTexture(false),
+ m_bDispListValid(false),
+ m_Mat(f_Material)
+{
+ BitmapStruct l_bmp;
+
+ //load 3d model
+ m_bDispListValid = CreateObject(f_strFileName);
+
+ //load textures
+ if (m_bDispListValid)
+ {
+ if (f_strColorTexName != NULL)
+ {
+ std::cout << "Loading " << f_strColorTexName << std::endl;
+ l_bmp = BitmapLoad(f_strColorTexName);
+ m_uiColorTex = (GLuint)l_bmp.m_iImageId;
+ m_bOwnTexture = true;
+ }
+ }
+}
+
+C_3DObject::C_3DObject(const char* f_strFileName,
+ GLuint f_uiTexture,
+ MatProps_t f_Material)
+ : m_Pos(0.0, 0.0, 0.0), m_Rot(0.0, 0.0, 0.0),
+ m_Scale(1.0, 1.0, 1.0),
+ m_bOwnTexture(false),
+ m_bDispListValid(false),
+ m_uiColorTex(f_uiTexture),
+ m_Mat(f_Material)
+{
+ //load 3d model
+ m_bDispListValid = CreateObject(f_strFileName);
+
+}
+
+C_3DObject::~C_3DObject()
+{
+ if (glIsList(m_uiListIndex))
+ glDeleteLists(m_uiListIndex, 1);
+
+ if (glIsTexture(m_uiColorTex) && m_bOwnTexture)
+ glDeleteTextures(1, &m_uiColorTex);
+}
+
+void C_3DObject::TransRotateScale()
+{
+ glScaled(m_Scale.x, m_Scale.y, m_Scale.z);
+ glTranslated(m_Pos.x, m_Pos.y, m_Pos.z);
+ glRotated(m_Rot.z, 0.0, 0.0, 1.0);
+ glRotated(m_Rot.x, 1.0, 0.0, 0.0);
+ glRotated(m_Rot.y, 0.0, 1.0, 0.0);
+}
+
+void C_3DObject::Render()
+{
+ //apply OpenGL settings for rendering this Object
+ glPushAttrib(GL_TEXTURE_BIT);
+ glEnable(GL_TEXTURE_2D);
+ //modulate the texture color with the computed material
+ //colors
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBindTexture(GL_TEXTURE_2D, m_uiColorTex);
+
+ //set material properties
+ glMaterialfv(GL_FRONT, GL_AMBIENT, m_Mat.m_fAmb);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, m_Mat.m_fDif);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, m_Mat.m_fSpec);
+ glMaterialfv(GL_FRONT, GL_EMISSION, m_Mat.m_fEmi);
+ glMaterialf(GL_FRONT, GL_SHININESS, m_Mat.m_fShin);
+
+/*
+ //scale translate and rotate
+ glPushMatrix();
+
+ glScaled(m_Scale.x, m_Scale.y, m_Scale.z);
+ glTranslated(m_Pos.x, m_Pos.y, m_Pos.z);
+ glRotated(m_Rot.z, 0.0, 0.0, 1.0);
+ glRotated(m_Rot.x, 1.0, 0.0, 0.0);
+ glRotated(m_Rot.y, 0.0, 1.0, 0.0);
+*/
+
+ //render by calling the display list
+ if(m_bDispListValid)
+ {
+ glCallList(m_uiListIndex);
+ }
+ else
+ {
+ //or render a LARGE cube when we failed to load the
+ //geometry
+ glutSolidCube(10.0);
+ }
+
+// glPopMatrix();
+
+ glPopAttrib();
+}
+
+
+
+bool C_3DObject::CreateObject(const char *f_pFilePath)
+{
+ Geometry_t l_Geom;
+ bool l_bParseOk;
+ Vect3D_t l_DummyVect;
+
+ //the triangle indices are 1-based so we insert dummy Vect3D_t
+ //to fill the 0 positions in the vertex, normals and texcoords
+ //vector containers.
+ l_Geom.m_verts.push_back(l_DummyVect);
+ l_Geom.m_norms.push_back(l_DummyVect);
+ l_Geom.m_texs.push_back(l_DummyVect);
+
+ l_bParseOk = LoadGeometryData(f_pFilePath, l_Geom);
+
+ //output statistics
+ std::cout << "C_3DObject: file " << f_pFilePath
+ << "\nParse: " << (l_bParseOk? "SUCCESS" : "FAILURE")
+ << "\nVertices: " << l_Geom.m_verts.size()-1
+ << "\nNormals: " << l_Geom.m_norms.size()-1
+ << "\nTexCrds: " << l_Geom.m_texs.size()-1
+ << "\nTriangles: " << l_Geom.m_triangles.size()
+ << "\nBoundBox: x(" << m_BBox.m_dLeft << "," << m_BBox.m_dRight << ")"
+ << "\n y(" << m_BBox.m_dBottom << "," << m_BBox.m_dTop << ")"
+ << "\n z(" << m_BBox.m_dFront << "," << m_BBox.m_dBack << ")"
+ << std::endl;
+
+ if(!l_bParseOk)
+ {
+ std::cout << "C_3DObject Error: failed to parse file "
+ << f_pFilePath << std::endl;
+
+ return false;
+ }
+
+ //create display list
+ m_uiListIndex = glGenLists(1);
+ glNewList(m_uiListIndex, GL_COMPILE);
+
+ glBegin(GL_TRIANGLES);
+
+ //iterate through the triangles
+ std::vector<Triangle_t>::iterator it = l_Geom.m_triangles.begin();
+ for(; it != l_Geom.m_triangles.end(); it++)
+ {
+ //vertex1
+ Vect3D_t v = l_Geom.m_verts[it->v1],
+ t = l_Geom.m_texs[it->t1],
+ n = l_Geom.m_norms[it->n1];
+
+ glNormal3d(n.x, n.y, n.z);
+ glTexCoord3d(t.x, t.y, t.z);
+ glVertex3d(v.x, v.y, v.z);
+
+ //vertex2
+ v = l_Geom.m_verts[it->v2],
+ t = l_Geom.m_texs[it->t2],
+ n = l_Geom.m_norms[it->n2];
+
+ glNormal3d(n.x, n.y, n.z);
+ glTexCoord3d(t.x, t.y, t.z);
+ glVertex3d(v.x, v.y, v.z);
+
+ //vertex3
+ v = l_Geom.m_verts[it->v3],
+ t = l_Geom.m_texs[it->t3],
+ n = l_Geom.m_norms[it->n3];
+
+ glNormal3d(n.x, n.y, n.z);
+ glTexCoord3d(t.x, t.y, t.z);
+ glVertex3d(v.x, v.y, v.z);}
+
+ glEnd();
+
+ glEndList();
+
+ return true;
+}
+
+bool C_3DObject::LoadGeometryData(const char *f_pFilePath, Geometry_t &f_Geom)
+{
+ std::ifstream l_infile(f_pFilePath);
+ char l_inbuffer[256];
+ bool l_bParseOk = true;
+ Vect3D_t l_v3;
+ Triangle_t l_tri;
+
+ if (l_infile.fail())
+ {
+ std::cout << "C_3DObject Error: could not open file "
+ << f_pFilePath << std::endl;
+
+ return false;
+ }
+
+
+ //load data
+ while(!l_infile.eof() && l_bParseOk)
+ {
+ //read the next line
+ l_infile.getline(l_inbuffer, 256);
+
+ //check if reading succeeded
+ if (l_infile.eof() || l_infile.fail() || l_infile.bad())
+ {
+ break;
+ }
+
+ //try to parse the first string of the line as one of the keywords:
+ //v -> vertex coordinate
+ //vt -> texture coordinate
+ //vn -> vertex normal
+ //f -> face record
+ switch (l_inbuffer[0])
+ {
+ case 'v' :
+ //posibilities 'v' 'vt' 'vn'
+ switch (l_inbuffer[1])
+ {
+ case ' ':
+ //vertex
+ if (l_bParseOk = ParseVect3D(&l_inbuffer[2], l_v3))
+ {
+ f_Geom.m_verts.push_back(l_v3);
+ //update boundingbox
+ UpdBBox(m_BBox, l_v3);
+ }
+ break;
+
+ case 't':
+ if (l_inbuffer[2] == ' ')
+ {
+ //texture coordinates
+ if (l_bParseOk = ParseVect3D(&l_inbuffer[3], l_v3))
+ {
+ f_Geom.m_texs.push_back(l_v3);
+ }
+ }
+ break;
+
+ case 'n':
+ if (l_inbuffer[2] == ' ')
+ {
+ //normal
+ if (l_bParseOk = ParseVect3D(&l_inbuffer[3], l_v3))
+ {
+ f_Geom.m_norms.push_back(l_v3);
+ }
+ }
+ break;
+ }
+ break;
+
+ case 'f':
+ if (l_inbuffer[1] == ' ')
+ {
+ //face (triangle)
+ if (l_bParseOk = ParseTriangle(&l_inbuffer[2], l_tri))
+ {
+ f_Geom.m_triangles.push_back(l_tri);
+ }
+ }
+ break;
+
+ case 'm' : // 'mtllib'?
+ break;
+
+ case 'u' : // 'usemtl' ?
+ break;
+ }
+ }
+
+ l_infile.close();
+
+ if (!l_bParseOk)
+ {
+ std::cout << "Parse error in: \"" << l_inbuffer << "\"\n";
+ }
+
+ return l_bParseOk;
+}
+
+bool C_3DObject::ParseVect3D(const char *f_pInBuffer, Vect3D_t &f_V3)
+{
+ //format: " x y z "
+ std::stringstream l_inbuffer(f_pInBuffer);
+
+ l_inbuffer >> std::skipws >> f_V3.x >> f_V3.y >> f_V3.z;
+
+ //std::cout << "Read values: " << f_V3.x << ", " << f_V3.y << ", " << f_V3.z << "\n";
+
+ return !l_inbuffer.fail();
+}
+
+bool C_3DObject::ParseTriangle(const char *f_pInBuffer, Triangle_t &f_triangle)
+{
+ //format v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3
+ std::stringstream l_inbuffer(f_pInBuffer);
+
+ char l_slash;
+
+ l_inbuffer >> std::skipws >> f_triangle.v1 >> l_slash >> f_triangle.t1 >> l_slash >> f_triangle.n1;
+ l_inbuffer >> std::skipws >> f_triangle.v2 >> l_slash >> f_triangle.t2 >> l_slash >> f_triangle.n2;
+ l_inbuffer >> std::skipws >> f_triangle.v3 >> l_slash >> f_triangle.t3 >> l_slash >> f_triangle.n3;
+
+ return !l_inbuffer.fail();
+}
+