Initial commit
This commit is contained in:
commit
d6c7f1ae87
95 changed files with 31975 additions and 0 deletions
319
src/m3dmesh.cpp
Normal file
319
src/m3dmesh.cpp
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
#define GL_GLEXT_PROTOTYPES
|
||||
#include "SDL_opengl.h"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "tinyxml.h"
|
||||
#include "m3dmaterial.h"
|
||||
#include "m3dtexture.h"
|
||||
#include "m3dmesh.h"
|
||||
|
||||
#include "extensions.h"
|
||||
|
||||
/// Create a new empty mesh
|
||||
/**
|
||||
*/
|
||||
m3dMesh::m3dMesh()
|
||||
{
|
||||
verts = NULL;
|
||||
numVerts = 0;
|
||||
faces = NULL;
|
||||
numFaces = 0;
|
||||
materials = NULL;
|
||||
numMaterials = 0;
|
||||
textures = NULL;
|
||||
numTextures = 0;
|
||||
}
|
||||
|
||||
/// Destroy this mesh
|
||||
/**
|
||||
*/
|
||||
m3dMesh::~m3dMesh()
|
||||
{
|
||||
delete[] verts;
|
||||
delete[] faces;
|
||||
delete[] materials;
|
||||
delete[] textures;
|
||||
}
|
||||
|
||||
int m3dMesh::loadFromXML(const TiXmlElement *root)
|
||||
{
|
||||
if(string(root->Value()) != "Mesh")
|
||||
{
|
||||
fprintf(stderr, "Unknown node type: %s (required: %s)\n", root->Value(), "Mesh");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if(readTransformations(root) != 0) return -1;
|
||||
|
||||
if(root->QueryIntAttribute("numVertices", &numVerts) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryIntAttribute("numFaces", &numFaces) != TIXML_SUCCESS) return -1;
|
||||
|
||||
faces = new struct Face[numFaces];
|
||||
verts = new struct Vertex[numVerts];
|
||||
int f = 0, v = 0;
|
||||
|
||||
numMaterials = 0;
|
||||
|
||||
const TiXmlElement *element = root->FirstChildElement();
|
||||
string value;
|
||||
while(element)
|
||||
{
|
||||
value = element->Value();
|
||||
|
||||
if(value == "Vertex")
|
||||
{
|
||||
if(parseVertex(element, &verts[v]) != 0 || v >= numVerts)
|
||||
{
|
||||
fprintf(stderr, "Invalid vertex!\n");
|
||||
delete[] verts;
|
||||
delete[] faces;
|
||||
return -1;
|
||||
}
|
||||
|
||||
v++;
|
||||
} else if(value == "Face")
|
||||
{
|
||||
if(parseFace(element, &faces[f]) != 0 || f >= numFaces)
|
||||
{
|
||||
fprintf(stderr, "Invalid face!\n");
|
||||
delete[] verts;
|
||||
delete[] faces;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(faces[f].material > numMaterials-1) numMaterials = faces[f].material+1;
|
||||
if(faces[f].texture > numTextures-1) numTextures = faces[f].texture+1;
|
||||
f++;
|
||||
}
|
||||
|
||||
element = element->NextSiblingElement();
|
||||
}
|
||||
|
||||
materials = new m3dMaterial[numMaterials];
|
||||
int mat = 0;
|
||||
element = root->FirstChildElement("Material");
|
||||
while(element)
|
||||
{
|
||||
if(mat >= numMaterials)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of materials!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
materials[mat].loadFromXML(element);
|
||||
mat++;
|
||||
|
||||
element = element->NextSiblingElement("Material");
|
||||
}
|
||||
|
||||
if(mat != numMaterials)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of materials (wanted %d, got %d)!\n", numMaterials, mat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
textures = new m3dTexture[numTextures];
|
||||
mat = 0;
|
||||
|
||||
element = root->FirstChildElement("Texture");
|
||||
while(element)
|
||||
{
|
||||
if(mat >= numTextures)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of textures\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
textures[mat].loadFromXML(element);
|
||||
mat++;
|
||||
|
||||
element = element->NextSiblingElement("Texture");
|
||||
}
|
||||
|
||||
|
||||
if(mat != numTextures)
|
||||
{
|
||||
fprintf(stderr, "Invalid mesh: incorrect number of textures (wanted %d, got %d)!\n", numTextures, mat);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::sort(faces, faces+numFaces, FaceSort());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dMesh::parseVertex(const TiXmlElement *root, struct Vertex *vert)
|
||||
{
|
||||
if(string(root->Value()) != "Vertex")
|
||||
{
|
||||
fprintf(stderr, "Unknown node type: %s (required: Vertex)\n", root->Value());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(root->QueryFloatAttribute("x", &vert->co[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("y", &vert->co[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("z", &vert->co[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryFloatAttribute("nx", &vert->no[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("ny", &vert->no[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("nz", &vert->no[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dMesh::parseFace(const TiXmlElement *root, struct Face *face)
|
||||
{
|
||||
if(string(root->Value()) != "Face")
|
||||
{
|
||||
fprintf(stderr, "Unknown node type: %s (required: Face)\n", root->Value());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(root->QueryIntAttribute("smooth", &face->smooth) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryFloatAttribute("nx", &face->no[0]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("ny", &face->no[1]) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryFloatAttribute("nz", &face->no[2]) != TIXML_SUCCESS) return -1;
|
||||
|
||||
if(root->QueryIntAttribute("material", &face->material) != TIXML_SUCCESS) return -1;
|
||||
if(root->QueryIntAttribute("texture", &face->texture) != TIXML_SUCCESS) return -1;
|
||||
|
||||
const TiXmlElement *element = root->FirstChildElement("Vertex");
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
if(element == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(element->QueryIntAttribute("index", &face->verts[i]) != TIXML_SUCCESS) return -1;
|
||||
if(element->QueryFloatAttribute("u", &face->uv[i][0]) == TIXML_WRONG_TYPE) return -1;
|
||||
if(element->QueryFloatAttribute("v", &face->uv[i][1]) == TIXML_WRONG_TYPE) return -1;
|
||||
|
||||
element = element->NextSiblingElement("Vertex");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m3dMesh::loadFromXML(const char *filename)
|
||||
{
|
||||
TiXmlDocument doc;
|
||||
if(!doc.LoadFile(filename)) return -1;
|
||||
return loadFromXML(doc.RootElement());
|
||||
}
|
||||
|
||||
const m3dTexture &m3dMesh::getTexture(int n) const
|
||||
{
|
||||
return textures[n];
|
||||
}
|
||||
|
||||
void m3dMesh::setTexture(int n, const m3dTexture& tex)
|
||||
{
|
||||
textures[n] = tex;
|
||||
}
|
||||
|
||||
/// Draw the mesh
|
||||
/**
|
||||
Draws this mesh. No child objects are rendered, nor child lights are enabled.
|
||||
*/
|
||||
void m3dMesh::draw()
|
||||
{
|
||||
glPushMatrix();
|
||||
// transform();
|
||||
|
||||
int prevTexture;
|
||||
int prevMaterial;
|
||||
int numTexUnits;
|
||||
|
||||
if(faces[0].material != -1)
|
||||
{
|
||||
materials[faces[0].material].bind();
|
||||
}
|
||||
prevMaterial = faces[0].material;
|
||||
|
||||
if(faces[0].texture != -1)
|
||||
{
|
||||
textures[faces[0].texture].bind();
|
||||
numTexUnits = textures[faces[0].texture].getNumTexUnits();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
} else
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
numTexUnits = 0;
|
||||
}
|
||||
prevTexture = faces[0].texture;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for(int i = 0; i < numFaces; i++)
|
||||
{
|
||||
struct Face *face;
|
||||
face = &faces[i];
|
||||
|
||||
if(prevMaterial != face->material || prevTexture != face->texture) glEnd();
|
||||
|
||||
if(prevMaterial != face->material)
|
||||
{
|
||||
if(face->material != -1)
|
||||
{
|
||||
materials[face->material].bind();
|
||||
} else
|
||||
{
|
||||
m3dMaterial().bind();
|
||||
}
|
||||
|
||||
prevMaterial = face->material;
|
||||
|
||||
if(prevTexture == face->texture) glBegin(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
if(prevTexture != face->texture)
|
||||
{
|
||||
if(face->texture != -1)
|
||||
{
|
||||
textures[face->texture].bind();
|
||||
numTexUnits = textures[face->texture].getNumTexUnits();
|
||||
if(prevTexture == -1) glEnable(GL_TEXTURE_2D);
|
||||
} else
|
||||
{
|
||||
numTexUnits = 0;
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
prevTexture = face->texture;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
if(!face->smooth)
|
||||
{
|
||||
glNormal3fv(face->no);
|
||||
}
|
||||
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
struct Vertex *vert;
|
||||
vert = &verts[face->verts[j]];
|
||||
|
||||
#ifdef HAVE_MULTITEX
|
||||
for(int t = 0; t < numTexUnits; t++)
|
||||
{
|
||||
mglMultiTexCoord2fv(GL_TEXTURE0_ARB + t, face->uv[j]);
|
||||
}
|
||||
#else
|
||||
glTexCoord2fv(face->uv[j]);
|
||||
#endif
|
||||
|
||||
if(face->smooth) glNormal3fv(vert->no);
|
||||
glVertex3fv(vert->co);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue