#include "MeshObject.h" #include "FileIO.h" //#include "Init.h" //#include "Extensions.h" using namespace exh; MeshMaterial::MeshMaterial(void) { material_name = ""; texture_name = ""; ambient.r = diffuse.r = specular.r = 1.0f; ambient.g = diffuse.g = specular.g = 1.0f; ambient.b = diffuse.b = specular.b = 1.0f; shininess = 0; transparency = 0; texture_id = material_id = 0; } MeshMaterial::~MeshMaterial(void) { } MeshFacePoint::MeshFacePoint(void) { vertex = NULL; tex_coord = NULL; } MeshFaceTriangle::MeshFaceTriangle(void) { material = NULL; normal = NULL; } MeshFaceTriangle::~MeshFaceTriangle(void) { if (normal) { delete [] normal; } } MeshSubObject::MeshSubObject(void) { faceTriangle = NULL; vertex = NULL; tex_coord = NULL; useTexCoord = false; face_size = vertex_size = tex_coord_size = vboVertexID = vboTexCoordID = 0; name = ""; pivot = Vector(0.0f, 0.0f, 0.0f); } MeshSubObject::~MeshSubObject(void) { if (faceTriangle) { delete [] faceTriangle; } if (vertex) { delete [] vertex; } if (tex_coord) { delete [] tex_coord; } } bool MeshSubObject::hasTexCoord(void) { return useTexCoord; } void MeshSubObject::setFaceTriangleSize(unsigned int size) { if (faceTriangle) { delete [] faceTriangle; } if (size > 0) { face_size = size; faceTriangle = new MeshFaceTriangle[size]; } } void MeshSubObject::setVertexSize(unsigned int size) { if (vertex) { delete [] vertex; } if (size > 0) { vertex_size = size; vertex = new Vector[size]; } } void MeshSubObject::setTexCoordSize(unsigned int size) { if (tex_coord) { delete [] tex_coord; } if (size > 0) { useTexCoord = true; tex_coord_size = size; tex_coord = new uv_coord[size]; } else { useTexCoord = false; } } void MeshSubObject::buildSubObject(void) { unsigned int i, j; //Generate vertex array glGenBuffersARB(1, &vboVertexID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboVertexID); exh::Vector *vertex_array = new exh::Vector[face_size*3]; for(i = 0, j = 0; i < face_size; i++, j += 3) { vertex_array[j] = *faceTriangle[i].v1.vertex; vertex_array[j+1] = *faceTriangle[i].v2.vertex; vertex_array[j+2] = *faceTriangle[i].v3.vertex; } glBufferDataARB(GL_ARRAY_BUFFER_ARB, face_size*3*3*sizeof(float), vertex_array, GL_STATIC_DRAW_ARB); delete [] vertex_array; //Generate texture coordinate array if (hasTexCoord()) { glGenBuffersARB(1, &vboTexCoordID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboTexCoordID); exh::uv_coord *tex_coord_array = new exh::uv_coord[face_size*3]; for(i = 0, j = 0; i < face_size; i++, j += 3) { tex_coord_array[j] = *faceTriangle[i].v1.tex_coord; tex_coord_array[j+1] = *faceTriangle[i].v2.tex_coord; tex_coord_array[j+2] = *faceTriangle[i].v3.tex_coord; } glBufferDataARB(GL_ARRAY_BUFFER_ARB, face_size*3*2*sizeof(float), tex_coord_array, GL_STATIC_DRAW_ARB); delete [] tex_coord_array; } } Vector MeshObject::getNormal(const Vector& v1, const Vector& v2, const Vector& v3) { Vector t1, t2; t1.x = v1.x - v2.x; t1.y = v1.y - v2.y; t1.z = v1.z - v2.z; t2.x = v2.x - v3.x; t2.y = v2.y - v3.y; t2.z = v2.z - v3.z; t1 = t1.crossProduct(t2); return t1.normalize(); } unsigned int MeshObject::getMaterialOrder(MeshMaterial *mat) { for(unsigned int i = 0; i < material_size; i++) { if (&material[i] == mat) { return i; } } return 0; } unsigned int MeshObject::getVertexOrder(unsigned int obj, exh::Vector *vertex) { for(unsigned int i = 0; i < object[obj].vertex_size; i++) { if (&object[obj].vertex[i] == vertex) { return i; } } return 0; } unsigned int MeshObject::getTexCoordOrder(unsigned int obj, exh::uv_coord *tex_coord) { for(unsigned int i = 0; i < object[obj].tex_coord_size; i++) { if (&object[obj].tex_coord[i] == tex_coord) { return i; } } return 0; } MeshObject::MeshObject(void) { material = NULL; object = NULL; object_size = material_size = 0; name = ""; } MeshObject::~MeshObject(void) { if (material) { delete [] this->material; this->material = NULL; } if (object) { delete [] this->object; this->object = NULL; } } void MeshObject::setObjectSize(unsigned int size) { if (this->object) { delete [] this->object; } if (size > 0) { this->object_size = size; this->object = new MeshSubObject[size]; } } void MeshObject::setMaterialSize(unsigned int size) { if (this->material) { delete [] this->material; } if (size > 0) { this->material_size = size; this->material = new MeshMaterial[size]; } } void MeshObject::buildObject(void) { calculateNormals(); } void MeshObject::calculateNormals(void) { for(unsigned int i = 0; i < object_size; i++) { calculateNormals(i); } } void MeshObject::calculateNormals(unsigned int object_num) { for(unsigned int i = 0; i < object[object_num].face_size; i++) { Vector normal = getNormal( *object[object_num].faceTriangle[i].v1.vertex, *object[object_num].faceTriangle[i].v2.vertex, *object[object_num].faceTriangle[i].v3.vertex ); object[object_num].faceTriangle[i].normal = new Vector(normal); } } void MeshObject::drawObject(unsigned int begin, unsigned int end) { for(unsigned int i = 0; i < object_size; i++) { drawSubObject(i, begin, end); } } void MeshObject::drawSubObject(unsigned int object_num, unsigned int begin, unsigned int end) { if (end == 0) { end = object[object_num].face_size; } else { end %= object[object_num].face_size; } glPushMatrix(); glBegin(GL_TRIANGLES); if (object[object_num].hasTexCoord()) { for(unsigned int i = begin; i < end; i++) { glNormal3f( object[object_num].faceTriangle[i].normal[0].x, object[object_num].faceTriangle[i].normal[0].y, object[object_num].faceTriangle[i].normal[0].z ); glTexCoord2f( object[object_num].faceTriangle[i].v1.tex_coord->v, object[object_num].faceTriangle[i].v1.tex_coord->u ); glVertex3f( object[object_num].faceTriangle[i].v1.vertex->x, object[object_num].faceTriangle[i].v1.vertex->y, object[object_num].faceTriangle[i].v1.vertex->z ); glTexCoord2f( object[object_num].faceTriangle[i].v2.tex_coord->v, object[object_num].faceTriangle[i].v2.tex_coord->u ); glVertex3f( object[object_num].faceTriangle[i].v2.vertex->x, object[object_num].faceTriangle[i].v2.vertex->y, object[object_num].faceTriangle[i].v2.vertex->z ); glTexCoord2f( object[object_num].faceTriangle[i].v3.tex_coord->v, object[object_num].faceTriangle[i].v3.tex_coord->u ); glVertex3f( object[object_num].faceTriangle[i].v3.vertex->x, object[object_num].faceTriangle[i].v3.vertex->y, object[object_num].faceTriangle[i].v3.vertex->z ); } } else { for(unsigned int i = 0; i < object[object_num].face_size; i++) { glNormal3f( object[object_num].faceTriangle[i].normal[0].x, object[object_num].faceTriangle[i].normal[0].y, object[object_num].faceTriangle[i].normal[0].z ); glVertex3f( object[object_num].faceTriangle[i].v1.vertex->x, object[object_num].faceTriangle[i].v1.vertex->y, object[object_num].faceTriangle[i].v1.vertex->z ); glVertex3f( object[object_num].faceTriangle[i].v2.vertex->x, object[object_num].faceTriangle[i].v2.vertex->y, object[object_num].faceTriangle[i].v2.vertex->z ); glVertex3f( object[object_num].faceTriangle[i].v3.vertex->x, object[object_num].faceTriangle[i].v3.vertex->y, object[object_num].faceTriangle[i].v3.vertex->z ); } } glEnd(); glPopMatrix(); } /* ExHouse MeshObject file format main data UChar 0xA0 UChar version CStr name materials UChar 0xA1 Uint32 chunk_size Uint16 material_size CStr material_name CStr texture_name UChar color_size UChar color_type [0x01 ambient, 0x02 diffuse, 0x03 specular] float r, g, b Uint32 shininess float transparency objects UChar 0xA2 Uint32 chunk_size Uint16 object_size CStr object_name Vector pivot Uint32 vertex_size Vector vertex Uint32 tex_coord_size float u, v UChar face_type [0x01 triangle, 0x02 quad] Uint32 face_size Uint16 material_num //v1 Uint32 vertex_num Uint32 tex_coord_num //v2 Uint32 vertex_num Uint32 tex_coord_num //v3 Uint32 vertex_num Uint32 tex_coord_num */ void MeshObject::readFile(const char *filename) { FileIO reader; if (reader.open(filename, std::ios::in | std::ios::binary)) { reader.readUChar(); //header reader.readUChar(); //version name = reader.readCStr(); #ifdef __DEBUG printf("\nMeshObject::readFile(\"%s\")\n", filename); printf("\tobject name: \"%s\"\n", name.c_str()); #endif reader.readUChar(); //materials chunk 0xA1 reader.readUInt32(); //chunksize unsigned int material_size = reader.readUInt16(); setMaterialSize(material_size); for(unsigned int i = 0; i < material_size; i++) { material[i].material_name = reader.readCStr(); material[i].texture_name = reader.readCStr(); #ifdef __DEBUG printf("\n\tMaterial %d\n", i); printf("\tmaterial name: \"%s\"\n", material[i].material_name.c_str()); printf("\ttexture name: \"%s\"\n", material[i].texture_name.c_str()); #endif unsigned char color_size = reader.readUChar(); for(unsigned char j = 0; j < color_size; j++) { unsigned char color_type = reader.readUChar(); exh::color tmpColor; tmpColor.r = reader.readFloat(); tmpColor.g = reader.readFloat(); tmpColor.b = reader.readFloat(); switch(color_type) { case 0x01: #ifdef __DEBUG printf("\tambient color: %.02f %.02f %.02f\n", tmpColor.r, tmpColor.g, tmpColor.b); #endif material[i].ambient = tmpColor; break; case 0x02: #ifdef __DEBUG printf("\tdiffuse color: %.02f %.02f %.02f\n", tmpColor.r, tmpColor.g, tmpColor.b); #endif material[i].diffuse = tmpColor; break; case 0x03: #ifdef __DEBUG printf("\tspecular color: %.02f %.02f %.02f\n", tmpColor.r, tmpColor.g, tmpColor.b); #endif material[i].specular = tmpColor; break; } } material[i].shininess = reader.readUInt32(); material[i].transparency = reader.readFloat(); #ifdef __DEBUG printf("\tshininess: %d\n", material[i].shininess); printf("\ttransparency: %.02f\n", material[i].transparency); #endif } reader.readUChar(); //objects chunk 0xA2 reader.readUInt32(); //chunk_size unsigned int object_size = reader.readUInt16(); setObjectSize(object_size); for(unsigned int i = 0; i < object_size; i++) { unsigned j; object[i].name = reader.readCStr(); object[i].pivot = reader.readVector(); #ifdef __DEBUG printf("\n\tObject %d\n", i); printf("\tname: \"%s\"\n", object[i].name.c_str()); printf( "\tpivot: %.02f %.02f %.02f\n", object[i].pivot.x, object[i].pivot.y, object[i].pivot.z ); #endif unsigned int vertex_size = reader.readUInt32(); #ifdef __DEBUG printf("\tvertex size: %d\n", vertex_size); #endif object[i].setVertexSize(vertex_size); for(j = 0; j < vertex_size; j++) { object[i].vertex[j] = reader.readVector(); } unsigned int tex_coord_size = reader.readUInt32(); #ifdef __DEBUG printf("\ttex coordinate size: %d\n", tex_coord_size); #endif object[i].setTexCoordSize(tex_coord_size); for(j = 0; j < tex_coord_size; j++) { object[i].tex_coord[j].u = reader.readFloat(); object[i].tex_coord[j].v = reader.readFloat(); } reader.readUChar(); //face_type (triangle, quad) unsigned int face_size = reader.readUInt32(); #ifdef __DEBUG printf("\tface size: %d\n", face_size); #endif object[i].setFaceTriangleSize(face_size); for(j = 0; j < face_size; j++) { object[i].faceTriangle[j].material = &material[reader.readUInt16()]; object[i].faceTriangle[j].v1.vertex = &object[i].vertex[reader.readUInt16()]; object[i].faceTriangle[j].v1.tex_coord = &object[i].tex_coord[reader.readUInt16()]; object[i].faceTriangle[j].v2.vertex = &object[i].vertex[reader.readUInt16()]; object[i].faceTriangle[j].v2.tex_coord = &object[i].tex_coord[reader.readUInt16()]; object[i].faceTriangle[j].v3.vertex = &object[i].vertex[reader.readUInt16()]; object[i].faceTriangle[j].v3.tex_coord = &object[i].tex_coord[reader.readUInt16()]; } } reader.close(); } #ifdef __DEBUG else { fprintf(stderr, "MeshObject::readFile(%s): Unable to open file for reading!\n", filename); } #endif } void MeshObject::writeFile(const char *filename) { FileIO writer; unsigned int i; if (writer.open(exh::init.getDataPath(filename), std::ios::out | std::ios::binary)) { //main writer.writeUChar(0xA0); writer.writeUChar(0x01); writer.writeCStr(name.c_str()); //materials writer.writeUChar(0xA1); writer.writeUInt32((Uint32)0); writer.writeUInt16((Uint16)material_size); for(i = 0; i < material_size; i++) { writer.writeCStr(material[i].material_name.c_str()); writer.writeCStr(material[i].texture_name.c_str()); writer.writeUChar(3); //ambient writer.writeUChar(0x01); writer.writeFloat(material[i].ambient.r); writer.writeFloat(material[i].ambient.g); writer.writeFloat(material[i].ambient.b); //diffuse writer.writeUChar(0x02); writer.writeFloat(material[i].diffuse.r); writer.writeFloat(material[i].diffuse.g); writer.writeFloat(material[i].diffuse.b); //specular writer.writeUChar(0x03); writer.writeFloat(material[i].specular.r); writer.writeFloat(material[i].specular.g); writer.writeFloat(material[i].specular.b); writer.writeUInt32((Uint32)material[i].shininess); writer.writeFloat(material[i].transparency); } //objects writer.writeUChar(0xA2); writer.writeUInt32((Uint32)0); writer.writeUInt16((Uint16)object_size); for(i = 0; i < object_size; i++) { unsigned int j; writer.writeCStr(object[i].name.c_str()); writer.writeVector(object[i].pivot); writer.writeUInt32((Uint32)object[i].vertex_size); for(j = 0; j < object[i].vertex_size; j++) { writer.writeVector(object[i].vertex[j]); } writer.writeUInt32((Uint32)object[i].tex_coord_size); for(j = 0; j < object[i].tex_coord_size; j++) { writer.writeFloat(object[i].tex_coord[j].u); writer.writeFloat(object[i].tex_coord[j].v); } writer.writeUChar(0x01); writer.writeUInt32((Uint32)object[i].face_size); for(j = 0; j < object[i].face_size; j++) { writer.writeUInt16( (Uint16)getMaterialOrder( object[i].faceTriangle[j].material ) ); writer.writeUInt16( (Uint16)getVertexOrder( i, object[i].faceTriangle[j].v1.vertex ) ); writer.writeUInt16( (Uint16)getTexCoordOrder( i, object[i].faceTriangle[j].v1.tex_coord ) ); writer.writeUInt16( (Uint16)getVertexOrder( i, object[i].faceTriangle[j].v2.vertex ) ); writer.writeUInt16( (Uint16)getTexCoordOrder( i, object[i].faceTriangle[j].v2.tex_coord ) ); writer.writeUInt16( (Uint16)getVertexOrder( i, object[i].faceTriangle[j].v3.vertex ) ); writer.writeUInt16( (Uint16)getTexCoordOrder( i, object[i].faceTriangle[j].v3.tex_coord ) ); } } writer.close(); } }