removed all other model import/exporting except for md2

This commit is contained in:
gered 2011-06-07 12:09:19 -04:00
parent 3b29691ce7
commit b5b9558432
20 changed files with 12 additions and 3467 deletions

2
.gitignore vendored
View file

@ -7,4 +7,4 @@ Debug/
Release/
ipch/
*.suo
meshconverter
md2tomesh

View file

@ -1,7 +1,7 @@
# this Makefile is based on the ones from devkitPro
# TODO: probably should simplify it a bunch (mainly the rules at the bottom)
TARGET := meshconverter
TARGET := md2tomesh

View file

@ -1,80 +0,0 @@
#ifndef __ASSETS_COLOR_H_INCLUDED__
#define __ASSETS_COLOR_H_INCLUDED__
#include "../common.h"
#define COLOR_ALPHA_TRANSPARENT 0.0f
#define COLOR_ALPHA_OPAQUE 1.0f
class Color
{
public:
Color()
{
r = 0.0f;
g = 0.0f;
b = 0.0f;
a = COLOR_ALPHA_OPAQUE;
}
Color(float red, float green, float blue)
{
r = red;
g = green;
b = blue;
a = COLOR_ALPHA_OPAQUE;
}
Color(float red, float green, float blue, float alpha)
{
r = red;
g = green;
b = blue;
a = alpha;
}
uint32_t ToInt()
{
return ((uint32_t)(a * 255) << 24) | ((uint32_t)(r * 255) << 16) | ((uint32_t)(g * 255) << 8) | (uint32_t)(b * 255);
}
static uint32_t ToInt(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
return (a << 24) | (r << 16) | (g << 8) | b;
}
static uint32_t ToInt(float r, float g, float b, float a)
{
return ((int)(a * 255) << 24) | ((int)(r * 255) << 16) | ((int)(g * 255) << 8) | (int)(b * 255);
}
static void FromInt(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *a)
{
*a = (color & 0xff000000) >> 24;
*r = (color & 0x00ff0000) >> 16;
*g = (color & 0x0000ff00) >> 8;
*b = (color & 0x000000ff);
}
static void FromInt(uint32_t color, float *r, float *g, float *b, float *a)
{
*a = ((float)((color & 0xff000000) >> 24)) / 255;
*r = ((float)((color & 0x00ff0000) >> 16)) / 255;
*g = ((float)((color & 0x0000ff00) >> 8)) / 255;
*b = ((float)((color & 0x000000ff))) / 255;
}
static Color FromInt(uint32_t color)
{
Color out;
FromInt(color, &out.r, &out.g, &out.b, &out.a);
return out;
}
float r;
float g;
float b;
float a;
};
#endif

View file

@ -1,26 +0,0 @@
#ifndef __ASSETS_MATERIAL_H_INCLUDED__
#define __ASSETS_MATERIAL_H_INCLUDED__
#include "../common.h"
#include <string>
#include "color.h"
#define RGB_32(r, g, b, a) ((b)|((g) << 8)|((r) << 16)|((a) << 24))
#define RGB_24(r, g, b) ((b)|((g) << 8)|((r) << 16))
#define RGB_32_f(r, g, b, a) RGB_32((int)((r) * 255), (int)((g) * 255), (int)((b) * 255), (int)((a) * 255))
#define RGB_24_f(r, g, b) RGB_24((int)((r) * 255), (int)((g) * 255), (int)((b) * 255))
class Material
{
public:
std::string name;
std::string textureFile;
Color ambient;
Color diffuse;
Color specular;
Color emissive;
float shininess;
float opacity;
};
#endif

View file

@ -7,44 +7,6 @@ void WriteFileHeader(FILE *fp)
fwrite(&version, 1, 1, fp);
}
void WriteChunk(VerticesChunk *chunk, FILE *fp)
{
uint32_t size = chunk->GetSize();
if (size == 0)
return;
fputs("VTX", fp);
fwrite(&size, 4, 1, fp);
uint32_t count = chunk->GetCount();
fwrite(&count, 4, 1, fp);
for (uint32_t i = 0; i < count; ++i)
{
fwrite(&chunk->vertices[i].x, sizeof(float), 1, fp);
fwrite(&chunk->vertices[i].y, sizeof(float), 1, fp);
fwrite(&chunk->vertices[i].z, sizeof(float), 1, fp);
}
}
void WriteChunk(NormalsChunk *chunk, FILE *fp)
{
uint32_t size = chunk->GetSize();
if (size == 0)
return;
fputs("NRL", fp);
fwrite(&size, 4, 1, fp);
uint32_t count = chunk->GetCount();
fwrite(&count, 4, 1, fp);
for (uint32_t i = 0; i < count; ++i)
{
fwrite(&chunk->normals[i].x, sizeof(float), 1, fp);
fwrite(&chunk->normals[i].y, sizeof(float), 1, fp);
fwrite(&chunk->normals[i].z, sizeof(float), 1, fp);
}
}
void WriteChunk(TexCoordsChunk *chunk, FILE *fp)
{
uint32_t size = chunk->GetSize();
@ -63,82 +25,6 @@ void WriteChunk(TexCoordsChunk *chunk, FILE *fp)
}
}
void WriteChunk(MaterialsChunk *chunk, FILE *fp)
{
uint32_t size = chunk->GetSize();
if (size == 0)
return;
fputs("MTL", fp);
fwrite(&size, 4, 1, fp);
uint32_t count = chunk->GetCount();
fwrite(&count, 4, 1, fp);
for (uint32_t i = 0; i < count; ++i)
{
Material *m = &chunk->materials[i];
fwrite(m->name.c_str(), m->name.length(), 1, fp);
char ch = '\0';
fwrite(&ch, 1, 1, fp);
fwrite(&m->ambient.r, sizeof(float), 1, fp);
fwrite(&m->ambient.g, sizeof(float), 1, fp);
fwrite(&m->ambient.b, sizeof(float), 1, fp);
fwrite(&m->ambient.a, sizeof(float), 1, fp);
fwrite(&m->diffuse.r, sizeof(float), 1, fp);
fwrite(&m->diffuse.g, sizeof(float), 1, fp);
fwrite(&m->diffuse.b, sizeof(float), 1, fp);
fwrite(&m->diffuse.a, sizeof(float), 1, fp);
fwrite(&m->specular.r, sizeof(float), 1, fp);
fwrite(&m->specular.g, sizeof(float), 1, fp);
fwrite(&m->specular.b, sizeof(float), 1, fp);
fwrite(&m->specular.a, sizeof(float), 1, fp);
fwrite(&m->emissive.r, sizeof(float), 1, fp);
fwrite(&m->emissive.g, sizeof(float), 1, fp);
fwrite(&m->emissive.b, sizeof(float), 1, fp);
fwrite(&m->emissive.a, sizeof(float), 1, fp);
fwrite(&m->shininess, sizeof(float), 1, fp);
fwrite(&m->opacity, sizeof(float), 1, fp);
}
}
void WriteChunk(TrianglesChunk *chunk, FILE *fp)
{
uint32_t size = chunk->GetSize();
if (size == 0)
return;
fputs("TRI", fp);
fwrite(&size, 4, 1, fp);
uint32_t count = chunk->GetCount();
fwrite(&count, 4, 1, fp);
for (uint32_t i = 0; i < count; ++i)
{
Triangle *t = &chunk->triangles[i];
fwrite(&t->vertices[0], 4, 1, fp);
fwrite(&t->vertices[1], 4, 1, fp);
fwrite(&t->vertices[2], 4, 1, fp);
fwrite(&t->normals[0], 4, 1, fp);
fwrite(&t->normals[1], 4, 1, fp);
fwrite(&t->normals[2], 4, 1, fp);
fwrite(&t->texCoords[0], 4, 1, fp);
fwrite(&t->texCoords[1], 4, 1, fp);
fwrite(&t->texCoords[2], 4, 1, fp);
fwrite(&t->materialIndex, 4, 1, fp);
}
}
void WriteChunk(KeyFramesChunk *chunk, FILE *fp)
{
uint32_t size = chunk->GetSize();
@ -219,3 +105,4 @@ void WriteChunk(AnimationsChunk *chunk, FILE *fp)
fwrite(&a->end, 4, 1, fp);
}
}

View file

@ -8,20 +8,12 @@ void WriteFileHeader(FILE *fp);
// to be perfectly honest, i don't care to come up with a really elegant solution for this converter tool :p
#include "vertices.h"
#include "normals.h"
#include "texcoords.h"
#include "materials.h"
#include "triangles.h"
#include "keyframes.h"
#include "keyframetriangles.h"
#include "animations.h"
void WriteChunk(VerticesChunk *chunk, FILE *fp);
void WriteChunk(NormalsChunk *chunk, FILE *fp);
void WriteChunk(TexCoordsChunk *chunk, FILE *fp);
void WriteChunk(MaterialsChunk *chunk, FILE *fp);
void WriteChunk(TrianglesChunk *chunk, FILE *fp);
void WriteChunk(KeyFramesChunk *chunk, FILE *fp);
void WriteChunk(KeyFrameTrianglesChunk *chunk, FILE *fp);
void WriteChunk(AnimationsChunk *chunk, FILE *fp);

View file

@ -1,38 +0,0 @@
#ifndef __CHUNK_MATERIALS_H_INCLUDED__
#define __CHUNK_MATERIALS_H_INCLUDED__
#include "../common.h"
#include "../assets/material.h"
#include <vector>
struct MaterialsChunk
{
std::vector<Material> materials;
uint32_t GetCount()
{
return materials.size();
}
uint32_t GetSize()
{
if (materials.size() == 0)
return 0;
uint32_t size = 4; // count
for (uint32_t i = 0; i < materials.size(); ++i)
{
size += materials[i].name.length() + 1; // include null terminator
size += sizeof(float) * 4; // ambient
size += sizeof(float) * 4; // diffuse
size += sizeof(float) * 4; // specular
size += sizeof(float) * 4; // emissive
size += sizeof(float); // shininess
size += sizeof(float); // opacity
}
return size;
}
};
#endif

View file

@ -1,31 +0,0 @@
#ifndef __CHUNKS_NORMALS_H_INCLUDED__
#define __CHUNKS_NORMALS_H_INCLUDED__
#include "../common.h"
#include "../geometry/vector3.h"
#include <vector>
struct NormalsChunk
{
std::vector<Vector3> normals;
uint32_t GetCount()
{
return normals.size();
}
uint32_t GetSize()
{
if (normals.size() == 0)
return 0;
uint32_t size = 4; // count
size +=
(sizeof(float) * 3) // x, y, z
* normals.size();
return size;
}
};
#endif

View file

@ -1,35 +0,0 @@
#ifndef __CHUNKS_TRIANGLES_H_INCLUDED__
#define __CHUNKS_TRIANGLES_H_INCLUDED__
#include "../common.h"
#include "../geometry/triangle.h"
#include <vector>
struct TrianglesChunk
{
std::vector<Triangle> triangles;
uint32_t GetCount()
{
return triangles.size();
}
uint32_t GetSize()
{
if (triangles.size() == 0)
return 0;
uint32_t size = 4; // count
size +=
(
(4 * 3) // vertex indices
+ (4 * 3) // normal indices
+ (4 * 3) // texcoord indices
+ 4 // material index
) * triangles.size();
return size;
}
};
#endif

View file

@ -1,31 +0,0 @@
#ifndef __CHUNKS_VERTICES_H_INCLUDED__
#define __CHUNKS_VERTICES_H_INCLUDED__
#include "../common.h"
#include "../geometry/vector3.h"
#include <vector>
struct VerticesChunk
{
std::vector<Vector3> vertices;
uint32_t GetCount()
{
return vertices.size();
}
uint32_t GetSize()
{
if (vertices.size() == 0)
return 0;
uint32_t size = 4; // count
size +=
(sizeof(float) * 3) // x, y, z
* vertices.size();
return size;
}
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,491 +0,0 @@
#ifndef __GEOMETRY_QUATERNION_H_INCLUDED__
#define __GEOMETRY_QUATERNION_H_INCLUDED__
#include <math.h>
#include "common.h"
#include "vector3.h"
#include "matrix4x4.h"
/**
* Represents a quaternion to store an orientation or angular
* displacement and provides methods for conversion/manipulation
* <p>Referenced/based on code from:</p>
* <ul>
* <li>3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)</li>
* <li>More OpenGL Game Programming (Dave Astle, 2006)</li>
* <li>http://www.dhpoware.com/source/mathlib.html</li>
* </ul>
* @author Gered
*/
class Quaternion
{
public:
Quaternion() {}
Quaternion(float w, float x, float y, float z)
{
this->w = w;
this->x = x;
this->y = y;
this->z = z;
}
Quaternion(float w, const Vector3 &v)
{
this->w = w;
this->x = v.x;
this->y = v.y;
this->z = v.z;
}
Quaternion(const float *q)
{
w = q[0];
x = q[1];
y = q[2];
z = q[3];
}
~Quaternion() {}
void Set(float w, float x, float y, float z);
Matrix4x4 ToMatrix() const;
Vector3 GetVector() const;
static Quaternion Cross(const Quaternion &a, const Quaternion &b);
static float Dot(const Quaternion &a, const Quaternion &b);
static float Length(const Quaternion &q);
static float LengthSquared(const Quaternion &q);
static Quaternion Normalize(const Quaternion &q);
static Quaternion Conjugate(const Quaternion &q);
static Quaternion Inverse(const Quaternion &q);
static Quaternion CreateFromEulerAngles(float x, float y, float z);
static Quaternion CreateFromAxisAngle(float angle, const Vector3 &axis);
static Quaternion CreateFromRotationMatrix(const Matrix4x4 &matrix);
static void ExtractAxisAngle(const Quaternion &q, float *angle, Vector3 *axis);
static Quaternion Lerp(const Quaternion &a, const Quaternion &b, float interpolation);
static Quaternion Slerp(const Quaternion &a, const Quaternion &b, float interpolation);
float w;
float x;
float y;
float z;
};
Quaternion operator+(const Quaternion &left, const Quaternion &right);
Quaternion &operator+=(Quaternion &left, const Quaternion &right);
Quaternion operator-(const Quaternion &left, const Quaternion &right);
Quaternion &operator-=(Quaternion &left, const Quaternion &right);
Quaternion operator*(const Quaternion &left, float right);
Quaternion &operator*=(Quaternion &left, float right);
Quaternion operator*(const Quaternion &left, const Quaternion &right);
Quaternion &operator*=(Quaternion &left, const Quaternion &right);
Quaternion operator/(const Quaternion &left, float right);
Quaternion &operator/=(Quaternion &left, float right);
Vector3 operator*(const Vector3 &left, const Quaternion &right);
#define IDENTITY_QUATERNION Quaternion(1.0f, 0.0f, 0.0f, 0.0f)
inline void Quaternion::Set(float w, float x, float y, float z)
{
this->w = w;
this->x = x;
this->y = y;
this->z = z;
}
/**
* Converts a quaternion to a rotation matrix
* @return Matrix4x4
*/
inline Matrix4x4 Quaternion::ToMatrix() const
{
Matrix4x4 output;
output.m[_11] = 1.0f - (2.0f * ((y * y) + (z * z)));
output.m[_21] = 2.0f * ((x * y) + (z * w));
output.m[_31] = 2.0f * ((z * x) - (y * w));
output.m[_41] = 0.0f;
output.m[_12] = 2.0f * ((x * y) - (z * w));
output.m[_22] = 1.0f - (2.0f * ((z * z) + (x * x)));
output.m[_32] = 2.0f * ((y * z) + (x * w));
output.m[_42] = 0.0f;
output.m[_13] = 2.0f * ((z * x) + (y * w));
output.m[_23] = 2.0f * ((y * z) - (x * w));
output.m[_33] = 1.0f - (2.0f * ((y * y) + (x * x)));
output.m[_43] = 0.0f;
output.m[_14] = 0.0f;
output.m[_24] = 0.0f;
output.m[_34] = 0.0f;
output.m[_44] = 1.0f;
return output;
}
/**
* @return Vector3 the vector component of the quaternion.
*/
inline Vector3 Quaternion::GetVector() const
{
return Vector3(x, y, z);
}
/**
* Computes the cross product of two quaternions
* @param a first quaternion
* @param b second quaternion
* @return Quaternion the cross product
*/
inline Quaternion Quaternion::Cross(const Quaternion &a, const Quaternion &b)
{
return a * b;
}
/**
* Computes the dot product of 2 quaternions.
* @param a first quaternion
* @param b second quaternion
* @return float the dot product
*/
inline float Quaternion::Dot(const Quaternion &a, const Quaternion &b)
{
return (a.w * b.w) + (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
}
/**
* Computes the length (magnitude) of a quaternion.
* @param q quaternion to retrieve the length of
* @return float the length
*/
inline float Quaternion::Length(const Quaternion &q)
{
return sqrtf((q.w * q.w) + (q.x * q.x) + (q.y * q.y) + (q.z * q.z));
}
/**
* Computes the squared length of a quaternion (the length minus the
* sqrt call).
* @param q quaternion to retrieve the squared length of
* @return float the squared length
*/
inline float Quaternion::LengthSquared(const Quaternion &q)
{
return (q.w * q.w) + (q.x * q.x) + (q.y * q.y) + (q.z * q.z);
}
/**
* Normalizes a quaternion (only if necessary)
* @param q quaternion to be normalized
* @return Quaternion normalized quaternion
*/
inline Quaternion Quaternion::Normalize(const Quaternion &q)
{
float inverseLength = 1.0f / Length(q);
return Quaternion(
q.w * inverseLength,
q.x * inverseLength,
q.y * inverseLength,
q.z * inverseLength
);
}
/**
* Computes the conjugate of a quaternion. If the quaternion
* is unit length, this also returns the inverse.
* @param q quaternion to retrieve the conjugate of
* @return Quaternion conjugate
*/
inline Quaternion Quaternion::Conjugate(const Quaternion &q)
{
return Quaternion(q.w, -q.x, -q.y, -q.z);
}
/**
* Computes the inverse of a given quaternion
* @param q quaternion to retrieve the inverse of
* @return Quaternion inverse of the quaternion
*/
inline Quaternion Quaternion::Inverse(const Quaternion &q)
{
float inverseSquaredLength = 1.0f / LengthSquared(q);
return Quaternion(
q.w * inverseSquaredLength,
-q.x * inverseSquaredLength,
-q.y * inverseSquaredLength,
-q.z * inverseSquaredLength
);
}
/**
* Converts euler angles to a quaternion
* @param x x angle of rotation (specified in radians)
* @param y y angle of rotation (specified in radians)
* @param z z angle of rotation (specified in radians)
* @return Quaternion quaternion equivalent to the euler angle
* orientation
*/
inline Quaternion Quaternion::CreateFromEulerAngles(float x, float y, float z)
{
Quaternion qx(cosf(x / 2.0f), sinf(x / 2.0f), 0.0f, 0.0f);
Quaternion qy(cosf(y / 2.0f), 0.0f, sinf(y / 2.0f), 0.0f);
Quaternion qz(cosf(z / 2.0f), 0.0f, 0.0f, sinf(z / 2.0f));
return Normalize(qz * qy * qx);
}
/**
* Converts an axis angle to a quaternion
* @param angle the angle to rotate be (specified in radians)
* @param axis the axis being rotated about
* @return Quaternion quaternion equivalent to the axis angle
* orientation
*/
inline Quaternion Quaternion::CreateFromAxisAngle(float angle, const Vector3 &axis)
{
Quaternion result;
float c = cosf(angle / 2.0f);
float s = sinf(angle / 2.0f);
result.w = c;
result.x = axis.x * s;
result.y = axis.y * s;
result.z = axis.z * s;
return Normalize(result);
}
/**
* Converts a rotation matrix to a quaternion
* @param matrix matrix to be converted
* @return Quaternion quaternion equivalent of the rotation
* matrix
*/
inline Quaternion Quaternion::CreateFromRotationMatrix(const Matrix4x4 &matrix)
{
Quaternion result;
float n = matrix.m[_11] + matrix.m[_22] + matrix.m[_33];
if (n > 0.0f)
{
float a = sqrtf(n + 1.0f);
result.w = a / 2.0f;
a = 0.5f / a;
result.x = (matrix.m[_32] - matrix.m[_23]) * a;
result.y = (matrix.m[_13] - matrix.m[_31]) * a;
result.z = (matrix.m[_21] - matrix.m[_12]) * a;
}
else if ((matrix.m[_11] >= matrix.m[_22]) && (matrix.m[_11] >= matrix.m[_33]))
{
float a = sqrtf(1.0f + matrix.m[_11] - matrix.m[_22] - matrix.m[_33]);
float b = 0.5f / a;
result.x = 0.5f * a;
result.y = (matrix.m[_21] + matrix.m[_12]) * b;
result.z = (matrix.m[_31] + matrix.m[_13]) * b;
result.w = (matrix.m[_32] - matrix.m[_23]) * b;
}
else if (matrix.m[_22] > matrix.m[_33])
{
float a = sqrtf(1.0f + matrix.m[_22] - matrix.m[_11] - matrix.m[_33]);
float b = 0.5f / a;
result.x = (matrix.m[_12] + matrix.m[_21]) * b;
result.y = 0.5f * a;
result.z = (matrix.m[_23] + matrix.m[_32]) * b;
result.w = (matrix.m[_13] - matrix.m[_31]) * b;
}
else
{
float a = sqrtf(1.0f + matrix.m[_33] - matrix.m[_11] - matrix.m[_22]);
float b = 0.5f / a;
result.x = (matrix.m[_13] + matrix.m[_31]) * b;
result.y = (matrix.m[_23] + matrix.m[_32]) * b;
result.z = 0.5f * a;
result.w = (matrix.m[_21] - matrix.m[_12]) * b;
}
return Normalize(result);
}
/**
* Converts a quaternion to an axis-angle representation.
* @param q the normalized quaternion to convert
* @param angle the angle (in radians)
* @param axis a vector that will contain the axis
*/
inline void Quaternion::ExtractAxisAngle(const Quaternion &q, float *angle, Vector3 *axis)
{
*angle = 2.0f * acosf(q.w);
float n = sqrtf(1.0f - (q.w * q.w));
if (n > 0.0001f)
*axis = q.GetVector() / n;
else
*axis = X_AXIS;
}
/**
* Linearly interpolates between two quaternions.
* @param a the first quaternion
* @param b the second quaternion
* @param interpolation the amount to interpolate
* @return Quaternion the interpolated quaternion
*/
inline Quaternion Quaternion::Lerp(const Quaternion &a, const Quaternion &b, float interpolation)
{
return (a * (1.0f - interpolation)) + (b * interpolation);
}
/**
* Interpolates between two quaternions using spherical
* interpolation.
* @param a the first quaternion
* @param b the second quaternion
* @param interpolation the amount to interpolate
* @return Quaternion the interpolated quaternion
*/
inline Quaternion Quaternion::Slerp(const Quaternion &a, const Quaternion &b, float interpolation)
{
if (LengthSquared(a) == 0.0f)
{
if (LengthSquared(b) == 0.0f)
return IDENTITY_QUATERNION;
else
return b;
}
else if (LengthSquared(b) == 0.0f)
return a;
Quaternion q1 = a;
Quaternion q2 = b;
float cosHalfAngle = q1.w * q2.w + Vector3::Dot(q1.GetVector(), q2.GetVector());
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
return q1;
else if (cosHalfAngle < 0.0f)
{
q2.x = -q2.x;
q2.y = -q2.y;
q2.z = -q2.z;
q2.w = -q2.w;
cosHalfAngle = -cosHalfAngle;
}
float blendA;
float blendB;
if (cosHalfAngle < 0.99f)
{
float halfAngle = acosf(cosHalfAngle);
float sinHalfAngle = sinf(halfAngle);
float oneOverSinHalfAngle = 1.0f / sinHalfAngle;
blendA = sinf(halfAngle * (1.0f - interpolation)) * oneOverSinHalfAngle;
blendB = sinf(halfAngle * interpolation) * oneOverSinHalfAngle;
}
else
{
blendA = 1.0f - interpolation;
blendB = interpolation;
}
Quaternion result(q1.w * blendA + q2.w * blendB, q1.GetVector() * blendA + q2.GetVector() * blendB);
if (LengthSquared(result) > 0.0f)
return Normalize(result);
else
return IDENTITY_QUATERNION;
}
inline Quaternion operator+(const Quaternion &left, const Quaternion &right)
{
return Quaternion(
left.w + right.w,
left.x + right.x,
left.y + right.y,
left.z + right.z
);
}
inline Quaternion &operator+=(Quaternion &left, const Quaternion &right)
{
left = left + right;
return left;
}
inline Quaternion operator-(const Quaternion &left, const Quaternion &right)
{
return Quaternion(
left.w - right.w,
left.x - right.x,
left.y - right.y,
left.z - right.z
);
}
inline Quaternion &operator-=(Quaternion &left, const Quaternion &right)
{
left = left - right;
return left;
}
inline Quaternion operator*(const Quaternion &left, float right)
{
return Quaternion(
left.w * right,
left.x * right,
left.y * right,
left.z * right
);
}
inline Quaternion &operator*=(Quaternion &left, float right)
{
left = left * right;
return left;
}
inline Quaternion operator*(const Quaternion &left, const Quaternion &right)
{
return Quaternion(
(left.w * right.w) - (left.x * right.x) - (left.y * right.y) - (left.z * right.z),
(left.w * right.x) + (left.x * right.w) + (left.y * right.z) - (left.z * right.y),
(left.w * right.y) + (left.y * right.w) + (left.z * right.x) - (left.x * right.z),
(left.w * right.z) + (left.z * right.w) + (left.x * right.y) - (left.y * right.x)
);
}
inline Quaternion &operator*=(Quaternion &left, const Quaternion &right)
{
left = left * right;
return left;
}
inline Quaternion operator/(const Quaternion &left, float right)
{
return Quaternion(
left.w / right,
left.x / right,
left.y / right,
left.z / right
);
}
inline Quaternion &operator/=(Quaternion &left, float right)
{
left = left / right;
return left;
}
inline Vector3 operator*(const Vector3 &left, const Quaternion &right)
{
return Vector3(
((left.x * ((1.0f - (right.y * (right.y + right.y))) - (right.z * (right.z + right.z)))) + (left.y * ((right.x * (right.y + right.y)) - (right.w * (right.z + right.z))))) + (left.z * ((right.x * (right.z + right.z)) + (right.w * (right.y + right.y)))),
((left.x * ((right.x * (right.y + right.y)) + (right.w * (right.z + right.z)))) + (left.y * ((1.0f - (right.x * (right.x + right.x))) - (right.z * (right.z + right.z))))) + (left.z * ((right.y * (right.z + right.z)) - (right.w * (right.x + right.x)))),
((left.x * ((right.x * (right.z + right.z)) - (right.w * (right.y + right.y)))) + (left.y * ((right.y * (right.z + right.z)) + (right.w * (right.x + right.x))))) + (left.z * ((1.0f - (right.x * (right.x + right.x))) - (right.y * (right.y + right.y))))
);
}
#endif

View file

@ -1,15 +0,0 @@
#ifndef __GEOMETRY_TRIANGLE_H_INCLUDED__
#define __GEOMETRY_TRIANGLE_H_INCLUDED__
#include "../common.h"
class Triangle
{
public:
uint32_t vertices[3];
uint32_t normals[3];
uint32_t texCoords[3];
uint32_t materialIndex;
};
#endif

View file

@ -3,18 +3,14 @@
#include <exception>
#include "md2/md2.h"
#include "obj/obj.h"
#include "sm/sm.h"
#include "ms3d/ms3d.h"
int main(int argc, char **argv)
{
printf("MESH Converter\n");
printf("MD2-to-MESH Converter\n");
if (argc == 1)
{
printf("No input file specified.\n");
printf("Usage: meshconverter.exe [inputfile]\n\n");
printf("Usage: md2tomesh.exe [inputfile]\n\n");
return 1;
}
@ -40,73 +36,15 @@ int main(int argc, char **argv)
meshFile.append(".mesh");
}
if (extension == ".obj")
Md2 *md2 = new Md2();
if (!md2->Load(file))
{
printf("Using OBJ converter.\n");
Obj *obj = new Obj();
if (!obj->Load(file, "./"))
{
printf("Error loading OBJ file.\n\n");
return 1;
}
if (!obj->ConvertToMesh(meshFile))
{
printf("Error converting OBJ to MESH.\n\n");
return 1;
}
printf("Error loading MD2 file.\n\n");
return 1;
}
else if (extension == ".md2")
if (!md2->ConvertToMesh(meshFile))
{
printf("Using MD2 converter.\n");
Md2 *md2 = new Md2();
if (!md2->Load(file))
{
printf("Error loading MD2 file.\n\n");
return 1;
}
if (!md2->ConvertToMesh(meshFile))
{
printf("Error converting MD2 to MESH.\n\n");
return 1;
}
}
else if (extension == ".sm")
{
printf("Using SM converter.\n");
StaticModel *sm = new StaticModel();
if (!sm->Load(file))
{
printf("Error loading SM file.\n\n");
return 1;
}
if (!sm->ConvertToMesh(meshFile))
{
printf("Error converting SM to MESH.\n\n");
return 1;
}
}
else if (extension == ".ms3d")
{
printf("Using MS3D converter.\n");
Ms3d *ms3d = new Ms3d();
if (!ms3d->Load(file))
{
printf("Error loading MS3D file.\n\n");
return 1;
}
if (!ms3d->ConvertToMesh(meshFile))
{
printf("Error converting MS3D to MESH.\n\n");
return 1;
}
}
else
{
printf("Unrecognized file type.\n\n");
printf("Error converting MD2 to MESH.\n\n");
return 1;
}

View file

@ -1,437 +0,0 @@
#include "ms3d.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../util/files.h"
Ms3d::Ms3d()
{
m_numVertices = 0;
m_numTriangles = 0;
m_numMeshes = 0;
m_numMaterials = 0;
m_numJoints = 0;
m_vertices = NULL;
m_triangles = NULL;
m_meshes = NULL;
m_materials = NULL;
m_joints = NULL;
}
void Ms3d::Release()
{
delete[] m_vertices;
delete[] m_triangles;
delete[] m_meshes;
delete[] m_materials;
delete[] m_joints;
m_numVertices = 0;
m_numTriangles = 0;
m_numMeshes = 0;
m_numMaterials = 0;
m_numJoints = 0;
}
bool Ms3d::Load(const std::string &file)
{
FILE *fp;
Ms3dHeader header;
fp = fopen(file.c_str(), "rb");
if (!fp)
return false;
// filetype verification
fread(&header.id, 10, 1, fp);
if (strncmp(header.id, "MS3D000000", 10) != 0)
{
fclose(fp);
return false;
}
fread(&header.version, 4, 1, fp);
if (header.version != 4)
{
fclose(fp);
return false;
}
// read vertices
fread(&m_numVertices, 2, 1, fp);
m_vertices = new Ms3dVertex[m_numVertices];
for (int i = 0; i < m_numVertices; ++i)
{
Ms3dVertex *vertex = &m_vertices[i];
fread(&vertex->editorFlags, 1, 1, fp);
fread(&vertex->vertex.x, 4, 1, fp);
fread(&vertex->vertex.y, 4, 1, fp);
fread(&vertex->vertex.z, 4, 1, fp);
fread(&vertex->jointIndex, 1, 1, fp);
fread(&vertex->unused, 1, 1, fp);
}
// read triangle definitions
fread(&m_numTriangles, 2, 1, fp);
m_triangles = new Ms3dTriangle[m_numTriangles];
for (int i = 0; i < m_numTriangles; ++i)
{
Ms3dTriangle *triangle = &m_triangles[i];
fread(&triangle->editorFlags, 2, 1, fp);
for (int j = 0; j < 3; ++j)
fread(&triangle->vertices[j], 2, 1, fp);
for (int j = 0; j < 3; ++j)
{
fread(&triangle->normals[j].x, 4, 1, fp);
fread(&triangle->normals[j].y, 4, 1, fp);
fread(&triangle->normals[j].z, 4, 1, fp);
}
for (int j = 0; j < 3; ++j)
fread(&triangle->texCoords[j].x, 4, 1, fp);
for (int j = 0; j < 3; ++j)
fread(&triangle->texCoords[j].y, 4, 1, fp);
fread(&triangle->smoothingGroup, 1, 1, fp);
fread(&triangle->meshIndex, 1, 1, fp);
}
// read mesh information
fread(&m_numMeshes, 2, 1, fp);
m_meshes = new Ms3dMesh[m_numMeshes];
for (int i = 0; i < m_numMeshes; ++i)
{
Ms3dMesh *mesh = &m_meshes[i];
fread(&mesh->editorFlags, 1, 1, fp);
ReadString(fp, mesh->name, 32);
fread(&mesh->numTriangles, 2, 1, fp);
mesh->triangles = new unsigned short[mesh->numTriangles];
for (int j = 0; j < mesh->numTriangles; ++j)
fread(&mesh->triangles[j], 2, 1, fp);
fread(&mesh->materialIndex, 1, 1, fp);
}
// read material information
fread(&m_numMaterials, 2, 1, fp);
if (m_numMaterials > 0)
{
m_materials = new Ms3dMaterial[m_numMaterials];
for (int i = 0; i < m_numMaterials; ++i)
{
Ms3dMaterial *material = &m_materials[i];
ReadString(fp, material->name, 32);
for (int j = 0; j < 4; ++j)
fread(&material->ambient[j], 4, 1, fp);
for (int j = 0; j < 4; ++j)
fread(&material->diffuse[j], 4, 1, fp);
for (int j = 0; j < 4; ++j)
fread(&material->specular[j], 4, 1, fp);
for (int j = 0; j < 4; ++j)
fread(&material->emissive[j], 4, 1, fp);
fread(&material->shininess, 4, 1, fp);
fread(&material->transparency, 4, 1, fp);
fread(&material->mode, 1, 1, fp);
ReadString(fp, material->texture, 128);
ReadString(fp, material->alpha, 128);
}
}
// read joints
fread(&m_animationFps, 4, 1, fp);
fread(&m_editorAnimationTime, 4, 1, fp);
fread(&m_numFrames, 4, 1, fp);
fread(&m_numJoints, 2, 1, fp);
if (m_numJoints > 0)
{
m_joints = new Ms3dJoint[m_numJoints];
for (int i = 0; i < m_numJoints; ++i)
{
Ms3dJoint *joint = &m_joints[i];
fread(&joint->editorFlags, 1, 1, fp);
ReadString(fp, joint->name, 32);
ReadString(fp, joint->parentName, 32);
fread(&joint->rotation.x, 4, 1, fp);
fread(&joint->rotation.y, 4, 1, fp);
fread(&joint->rotation.z, 4, 1, fp);
fread(&joint->position.x, 4, 1, fp);
fread(&joint->position.y, 4, 1, fp);
fread(&joint->position.z, 4, 1, fp);
fread(&joint->numRotationFrames, 2, 1, fp);
fread(&joint->numTranslationFrames, 2, 1, fp);
joint->rotationFrames = new Ms3dKeyFrame[joint->numRotationFrames];
for (int j = 0; j < joint->numRotationFrames; ++j)
{
Ms3dKeyFrame *frame = &joint->rotationFrames[j];
fread(&frame->time, 4, 1, fp);
fread(&frame->param.x, 4, 1, fp);
fread(&frame->param.y, 4, 1, fp);
fread(&frame->param.z, 4, 1, fp);
}
joint->translationFrames = new Ms3dKeyFrame[joint->numTranslationFrames];
for (int j = 0; j < joint->numTranslationFrames; ++j)
{
Ms3dKeyFrame *frame = &joint->translationFrames[j];
fread(&frame->time, 4, 1, fp);
fread(&frame->param.x, 4, 1, fp);
fread(&frame->param.y, 4, 1, fp);
fread(&frame->param.z, 4, 1, fp);
}
}
}
fclose(fp);
// check for an animation definition file
std::string animationFile = file;
animationFile.erase(animationFile.find_last_of('.', std::string::npos));
animationFile.append(".animations");
fp = fopen(animationFile.c_str(), "r");
if (fp != NULL)
{
char *buffer = new char[80];
std::string line;
std::string name;
std::string temp;
int start;
int end;
while (!feof(fp))
{
fgets(buffer, 80, fp);
line = buffer;
if (strlen(buffer) > 5) // minimum length for a viable frame definition
{
// get animation name
int nameEnd = line.find_first_of(',');
if (nameEnd == std::string::npos)
continue;
name = line.substr(0, nameEnd);
// get start frame index
int startEnd = line.find_first_of(',', nameEnd + 1);
if (startEnd == std::string::npos)
continue;
temp = line.substr(nameEnd + 1, startEnd);
start = atoi(temp.c_str());
// get end frame index
temp = line.substr(startEnd + 1, std::string::npos);
end = atoi(temp.c_str());
Ms3dAnimation *animation = new Ms3dAnimation();
animation->name = name;
animation->startFrame = start;
animation->endFrame = end;
m_animations.push_back(*animation);
}
}
delete[] buffer;
fclose(fp);
}
return true;
}
bool Ms3d::ConvertToMesh(const std::string &file)
{
FILE *fp = fopen(file.c_str(), "wb");
if (fp == NULL)
return false;
fputs("MESH", fp);
unsigned char version = 1;
fwrite(&version, 1, 1, fp);
// vertices chunk
fputs("VTX", fp);
long numVertices = m_numVertices;
long sizeOfVertices = ((sizeof(float) * 3)) * numVertices + sizeof(long);
fwrite(&sizeOfVertices, sizeof(long), 1, fp);
fwrite(&numVertices, sizeof(long), 1, fp);
for (long i = 0; i < numVertices; ++i)
{
Ms3dVertex *vertex = &m_vertices[i];
fwrite(&vertex->vertex.x, sizeof(float), 1, fp);
fwrite(&vertex->vertex.y, sizeof(float), 1, fp);
fwrite(&vertex->vertex.z, sizeof(float), 1, fp);
}
// triangles chunk
fputs("TRI", fp);
long numTriangles = m_numTriangles;
long sizeOfTriangles = (sizeof(int) * 4 + (sizeof(float) * 3) * 3 + (sizeof(float) * 2) * 3) * numTriangles + sizeof(long);
fwrite(&sizeOfTriangles, sizeof(long), 1, fp);
fwrite(&numTriangles, sizeof(long), 1, fp);
for (long i = 0; i < numTriangles; ++i)
{
Ms3dTriangle *triangle = &m_triangles[i];
int index = triangle->vertices[0];
fwrite(&index, sizeof(int), 1, fp);
index = triangle->vertices[1];
fwrite(&index, sizeof(int), 1, fp);
index = triangle->vertices[2];
fwrite(&index, sizeof(int), 1, fp);
index = triangle->meshIndex;
fwrite(&index, sizeof(int), 1, fp);
for (int j = 0; j < 3; ++j)
{
fwrite(&triangle->normals[j].x, sizeof(float), 1, fp);
fwrite(&triangle->normals[j].y, sizeof(float), 1, fp);
fwrite(&triangle->normals[j].z, sizeof(float), 1, fp);
}
for (int j = 0; j < 3; ++j)
{
fwrite(&triangle->texCoords[j].x, sizeof(float), 1, fp);
fwrite(&triangle->texCoords[j].y, sizeof(float), 1, fp);
}
}
// sub-meshes / groups chunk
fputs("GRP", fp);
long numGroups = m_numMeshes;
long sizeOfGroupNames = 0;
for (long i = 0; i < numGroups; ++i)
sizeOfGroupNames += (m_meshes[i].name.length() + 1);
long sizeOfGroups = sizeOfGroupNames + (sizeof(int)) * numGroups + sizeof(long);
fwrite(&sizeOfGroups, sizeof(long), 1, fp);
fwrite(&numGroups, sizeof(long), 1, fp);
for (long i = 0; i < numGroups; ++i)
{
Ms3dMesh *mesh = &m_meshes[i];
fwrite(mesh->name.c_str(), mesh->name.length(), 1, fp);
char c = '\0';
fwrite(&c, 1, 1, fp);
int numTriangles = mesh->numTriangles;
fwrite(&numTriangles, sizeof(int), 1, fp);
}
// joints chunk
fputs("JNT", fp);
long numJoints = m_numJoints;
long sizeOfJointNames = 0;
for (long i = 0; i < numJoints; ++i)
sizeOfJointNames += (m_joints[i].name.length() + 1);
long sizeOfJoints = sizeOfJointNames + (sizeof(int) + sizeof(float) * 3 + sizeof(float) * 3) * numJoints + sizeof(long);
fwrite(&sizeOfJoints, sizeof(long), 1, fp);
fwrite(&numJoints, sizeof(long), 1, fp);
for (long i = 0; i < numJoints; ++i)
{
Ms3dJoint *joint = &m_joints[i];
fwrite(joint->name.c_str(), joint->name.length(), 1, fp);
char c = '\0';
fwrite(&c, 1, 1, fp);
int parentIndex = FindIndexOfJoint(joint->parentName);
fwrite(&parentIndex, sizeof(int), 1, fp);
fwrite(&joint->position.x, sizeof(float), 1, fp);
fwrite(&joint->position.y, sizeof(float), 1, fp);
fwrite(&joint->position.z, sizeof(float), 1, fp);
fwrite(&joint->rotation.x, sizeof(float), 1, fp);
fwrite(&joint->rotation.y, sizeof(float), 1, fp);
fwrite(&joint->rotation.z, sizeof(float), 1, fp);
}
// joints to vertices mapping chunk
fputs("JTV", fp);
long numMappings = numVertices;
long sizeOfJointMappings = (sizeof(int) + sizeof(float)) * numMappings + sizeof(long);
fwrite(&sizeOfJointMappings, sizeof(long), 1, fp);
fwrite(&numMappings, sizeof(long), 1, fp);
for (long i = 0; i < numMappings; ++i)
{
Ms3dVertex *vertex = &m_vertices[i];
int jointIndex = vertex->jointIndex;
fwrite(&jointIndex, sizeof(int), 1, fp);
float weight = 1.0f;
fwrite(&weight, sizeof(float), 1, fp);
}
// joint animation keyframes
fputs("JKF", fp);
long numFrames = m_numFrames;
long sizeOfJointFrames = ((6 * sizeof(float)) * m_numJoints) * numFrames + sizeof(long);
fwrite(&sizeOfJointFrames, sizeof(long), 1, fp);
fwrite(&numFrames, sizeof(long), 1, fp);
for (long i = 0; i < numFrames; ++i)
{
for (int j = 0; j < m_numJoints; ++j)
{
Ms3dJoint *joint = &m_joints[j];
Ms3dKeyFrame *position;
Ms3dKeyFrame *rotation;
if (i >= joint->numTranslationFrames)
position = &joint->translationFrames[0];
else
position = &joint->translationFrames[i];
if (i >= joint->numRotationFrames)
rotation = &joint->rotationFrames[0];
else
rotation = &joint->rotationFrames[i];
fwrite(&position->param.x, sizeof(float), 1, fp);
fwrite(&position->param.y, sizeof(float), 1, fp);
fwrite(&position->param.z, sizeof(float), 1, fp);
fwrite(&rotation->param.x, sizeof(float), 1, fp);
fwrite(&rotation->param.y, sizeof(float), 1, fp);
fwrite(&rotation->param.z, sizeof(float), 1, fp);
}
}
if (m_animations.size() > 0)
{
// figure out the size of all the animation name strings
long sizeofNames = 0;
for (int i = 0; i < m_animations.size(); ++i)
sizeofNames += m_animations[i].name.length() + 1;
// animations chunk
fputs("ANI", fp);
long numAnimations = m_animations.size();
long sizeofAnimations = (sizeof(long) * 2) * numAnimations + sizeofNames + sizeof(long);
fwrite(&sizeofAnimations, sizeof(long), 1, fp);
fwrite(&numAnimations, sizeof(long), 1, fp);
for (long i = 0; i < numAnimations; ++i)
{
long data;
const Ms3dAnimation *animation = &m_animations[i];
//fputs(animation->name.c_str(), fp);
fputs(animation->name.c_str(), fp);
fwrite("\0", 1, 1, fp);
data = animation->startFrame;
fwrite(&data, sizeof(long), 1, fp);
data = animation->endFrame;
fwrite(&data, sizeof(long), 1, fp);
}
}
fclose(fp);
return true;
}
int Ms3d::FindIndexOfJoint(const std::string &jointName)
{
if (jointName.length() == 0)
return -1;
for (int i = 0; i < m_numJoints; ++i)
{
Ms3dJoint *joint = &m_joints[i];
if (joint->name == jointName)
return i;
}
return -1;
}

View file

@ -1,146 +0,0 @@
#ifndef __MS3D_H_INCLUDED__
#define __MS3D_H_INCLUDED__
#include <string>
#include "../geometry/vector3.h"
#include "../geometry/vector2.h"
#include <vector>
struct Ms3dHeader
{
char id[10];
long version;
};
struct Ms3dVertex
{
unsigned char editorFlags;
Vector3 vertex;
char jointIndex;
unsigned char unused;
};
struct Ms3dTriangle
{
unsigned short editorFlags;
unsigned short vertices[3];
Vector3 normals[3];
Vector2 texCoords[3];
unsigned char smoothingGroup;
unsigned char meshIndex;
};
struct Ms3dMesh
{
unsigned char editorFlags;
std::string name;
unsigned short numTriangles;
unsigned short *triangles;
char materialIndex;
Ms3dMesh()
{
triangles = NULL;
}
~Ms3dMesh()
{
delete[] triangles;
}
};
struct Ms3dMaterial
{
std::string name;
float ambient[4];
float diffuse[4];
float specular[4];
float emissive[4];
float shininess;
float transparency;
char mode;
std::string texture;
std::string alpha;
};
struct Ms3dKeyFrame
{
float time;
Vector3 param;
};
struct Ms3dJoint
{
unsigned char editorFlags;
std::string name;
std::string parentName;
Vector3 rotation;
Vector3 position;
unsigned short numRotationFrames;
unsigned short numTranslationFrames;
Ms3dKeyFrame *rotationFrames;
Ms3dKeyFrame *translationFrames;
Ms3dJoint()
{
rotationFrames = NULL;
translationFrames = NULL;
}
~Ms3dJoint()
{
delete[] rotationFrames;
delete[] translationFrames;
}
};
struct Ms3dAnimation
{
std::string name;
unsigned int startFrame;
unsigned int endFrame;
};
class Ms3d
{
public:
Ms3d();
virtual ~Ms3d() { Release(); }
void Release();
bool Load(const std::string &file);
bool ConvertToMesh(const std::string &file);
unsigned short GetNumVertices() { return m_numVertices; }
unsigned short GetNumTriangles() { return m_numTriangles; }
unsigned short GetNumMeshes() { return m_numMeshes; }
unsigned short GetNumMaterials() { return m_numMaterials; }
unsigned short GetNumJoints() { return m_numJoints; }
float GetAnimationFps() { return m_animationFps; }
int GetNumFrames() { return m_numFrames; }
Ms3dVertex* GetVertices() { return m_vertices; }
Ms3dTriangle* GetTriangles() { return m_triangles; }
Ms3dMesh* GetMeshes() { return m_meshes; }
Ms3dMaterial* GetMaterials() { return m_materials; }
Ms3dJoint* GetJoints() { return m_joints; }
private:
int FindIndexOfJoint(const std::string &jointName);
unsigned short m_numVertices;
unsigned short m_numTriangles;
unsigned short m_numMeshes;
unsigned short m_numMaterials;
unsigned short m_numJoints;
float m_animationFps;
float m_editorAnimationTime;
int m_numFrames;
Ms3dVertex *m_vertices;
Ms3dTriangle *m_triangles;
Ms3dMesh *m_meshes;
Ms3dMaterial *m_materials;
Ms3dJoint *m_joints;
std::vector<Ms3dAnimation> m_animations;
};
#endif

View file

@ -1,496 +0,0 @@
#include "obj.h"
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <sstream>
Obj::Obj()
{
m_vertices = NULL;
m_normals = NULL;
m_texCoords = NULL;
m_materials = NULL;
m_numVertices = 0;
m_numNormals = 0;
m_numTexCoords = 0;
m_numMaterials = 0;
}
void Obj::Release()
{
delete[] m_vertices;
delete[] m_normals;
delete[] m_texCoords;
delete[] m_materials;
m_vertices = NULL;
m_normals = NULL;
m_texCoords = NULL;
m_materials = NULL;
m_numVertices = 0;
m_numNormals = 0;
m_numTexCoords = 0;
m_numMaterials = 0;
}
bool Obj::Load(const std::string &file, const std::string &texturePath)
{
std::ifstream input;
std::string line;
std::string op;
std::string path;
std::string tempName;
Vector3 vertex;
Vector3 normal;
ObjMaterial *currentMaterial = NULL;
int currentVertex = 0;
int currentNormal = 0;
int currentTexCoord = 0;
int numGroups = 0;
// Get pathname from filename given (if present)
// Need this as we assume any .mtl files specified are in the same path as this .obj file
if (file.find_last_of('/') != std::string::npos)
path = file.substr(0, file.find_last_of('/') + 1);
if (!FindAndLoadMaterials(path, texturePath, file))
return false;
if (!GetDataSizes(file))
return false;
input.open(file.c_str());
if (input.fail())
return false;
// Extract name of model from the filename given (basically, chop off the extension and path)
//if (file.find_last_of('.') != std::string::npos)
// model->name = file.substr(path.length(), file.find_last_of('.') - path.length());
// Begin reading in model data
while (!input.eof())
{
if (numGroups > 1)
break;
std::getline(input, line, '\n');
op = line.substr(0, line.find(' '));
// Comments
if (op == "#")
{
}
// Vertex
else if (op == "v")
{
sscanf(line.c_str(), "v %f %f %f", &m_vertices[currentVertex].x, &m_vertices[currentVertex].y, &m_vertices[currentVertex].z);
++currentVertex;
}
// Texture coordinate
else if (op == "vt")
{
sscanf(line.c_str(), "vt %f %f", &m_texCoords[currentTexCoord].x, &m_texCoords[currentTexCoord].y);
m_texCoords[currentTexCoord].x = -m_texCoords[currentTexCoord].y;
++currentTexCoord;
}
// Vertex normal
else if (op == "vn")
{
sscanf(line.c_str(), "vn %f %f %f", &m_normals[currentNormal].x, &m_normals[currentNormal].y, &m_normals[currentNormal].z);
++currentNormal;
}
// Face definition
else if (op == "f")
{
ParseFaceDefinition(line, currentMaterial);
}
// Group name
else if (op == "g")
{
++numGroups;
}
// Object name
else if (op == "o")
{
}
// Material
else if (op == "usemtl")
{
tempName = line.substr(line.find(' ') + 1);
currentMaterial = NULL;
// Find the named material and set it as current
for (unsigned int i = 0; i < m_numMaterials; ++i)
{
if (m_materials[i].name == tempName)
{
currentMaterial = &m_materials[i];
break;
}
}
//ASSERT(currentMaterial != NULL);
}
// Material file
else if (op == "mtllib")
{
// Already would have been loaded
}
}
input.close();
return true;
}
void Obj::ParseFaceDefinition(const std::string &faceDefinition, ObjMaterial *currentMaterial)
{
static int numFaceVertices = 0;
static OBJ_FACE_VERTEX_TYPE vertexType;
std::string def;
int pos;
int n = 0;
// Just get the vertex index part of the line (can be variable length, and we dont want the newline at the end)
pos = faceDefinition.find(' ') + 1;
def = faceDefinition.substr(pos);
// Few different face formats, and variable amount of vertices per face possible
// How many vertices are there in this face definition? (only calc this once)
// Also calc the vertex format
if (!numFaceVertices)
{
pos = 0;
while (def.length() > 0 && def[def.length() - 1] == ' ')
def = def.substr(0, def.length() - 1);
//ASSERT(def.length() > 0);
while (pos != std::string::npos)
{
++pos;
++numFaceVertices;
pos = def.find(' ', pos);
}
std::string tempVertex = def.substr(0, def.find(' '));
if (tempVertex.find("//") != std::string::npos)
vertexType = OBJ_VERTEX_NORMAL;
else
{
pos = 0;
while (pos != std::string::npos)
{
++pos;
++n;
pos = tempVertex.find('/', pos);
}
if (n == 1)
vertexType = OBJ_VERTEX_TEXCOORD;
else
vertexType = OBJ_VERTEX_FULL;
}
}
// Parse out vertices in this face
// We also store only triangles. Since OBJ file face definitions can have any number
// of vertices per face, we need to split it up into triangles here for easy rendering
// This is done as follows:
// - first 3 vertices = first triangle for face
// - for each additional 1 vertex, take the first vertex read for this face + the previously
// read vertex for this face and combine to make a new triangle
std::istringstream parser;
std::string currentVertex;
int thisVertex[3];
int firstVertex[3];
int lastReadVertex[3];
int thisTriangle[3][3];
ObjFace face;
memset(&firstVertex, 0, sizeof(int) * 3);
memset(&lastReadVertex, 0, sizeof(int) * 3);
memset(&thisTriangle, 0, sizeof(int) * (3 * 3));
parser.clear();
parser.str(def);
for (int i = 0; i < numFaceVertices; ++i)
{
// Get current vertex for this face
parser >> currentVertex;
// Add vertex/texcoord/normal indexes to the data arrays
// (OBJ file indexes are NOT zero based. We fix that here)
memset(&thisVertex, 0, sizeof(int) * 3);
switch (vertexType)
{
case OBJ_VERTEX_FULL: // v/vt/vn
sscanf(currentVertex.c_str(), "%d/%d/%d", &thisVertex[0], &thisVertex[1], &thisVertex[2]);
break;
case OBJ_VERTEX_NORMAL: // v//vn
sscanf(currentVertex.c_str(), "%d//%d", &thisVertex[0], &thisVertex[2]);
break;
case OBJ_VERTEX_TEXCOORD: // v/vt
sscanf(currentVertex.c_str(), "%d/%d", &thisVertex[0], &thisVertex[1]);
break;
}
// Save the first vertex read for a face
if (i == 0)
memcpy(&firstVertex, &thisVertex, sizeof(int) * 3);
// First 3 vertices simply form a triangle
if (i <= 2)
{
face.vertices[i] = thisVertex[0] - 1;
face.texcoords[i] = thisVertex[1] - 1;
face.normals[i] = thisVertex[2] - 1;
}
// Store the first triangle
if (i == 2)
{
//ASSERT(currentMaterial != NULL);
currentMaterial->faces[currentMaterial->lastFaceIndex] = face;
++currentMaterial->lastFaceIndex;
}
// Combine vertices to form additional triangles
if (i > 2)
{
//ASSERT(currentMaterial != NULL);
face.vertices[0] = firstVertex[0] - 1; face.texcoords[0] = firstVertex[1] - 1; face.normals[0] = firstVertex[2] - 1;
face.vertices[1] = lastReadVertex[0] - 1; face.texcoords[1] = lastReadVertex[1] - 1; face.normals[1] = lastReadVertex[2] - 1;
face.vertices[2] = thisVertex[0] - 1; face.texcoords[2] = thisVertex[1] - 1; face.normals[2] = thisVertex[2] - 1;
currentMaterial->faces[currentMaterial->lastFaceIndex] = face;
++currentMaterial->lastFaceIndex;
}
// Save as "previously read vertex"
memcpy(&lastReadVertex, &thisVertex, sizeof(int) * 3);
}
}
bool Obj::GetDataSizes(const std::string &file)
{
std::ifstream input;
std::string line;
std::string op;
int countVertices = 0;
int countNormals = 0;
int countTexCoords = 0;
int numGroups = 0;
std::string useMtlName;
ObjMaterial *currentMaterial;
input.open(file.c_str());
if (input.fail())
return false;
while (!input.eof())
{
if (numGroups > 1)
break;
std::getline(input, line, '\n');
op = line.substr(0, line.find(' '));
if (op == "g")
++numGroups;
else if (op == "v")
++countVertices;
else if (op == "vt")
++countTexCoords;
else if (op == "vn")
++countNormals;
else if (op == "f")
// TODO: count number of vertices per face definition, and adjust the ++ operation accordingly (i.e. for 4 vertices per face, needs to be "+= 2")
++currentMaterial->numFaces;
else if (op == "usemtl")
{
std::string useMtlName = line.substr(line.find(' ') + 1);
currentMaterial = NULL;
// Find the named material and set it as current
for (unsigned int i = 0; i < m_numMaterials; ++i)
{
if (m_materials[i].name == useMtlName)
{
currentMaterial = &m_materials[i];
break;
}
}
//ASSERT(currentMaterial != NULL);
}
}
input.close();
m_numVertices = countVertices;
m_numTexCoords = countTexCoords;
m_numNormals = countNormals;
m_vertices = new Vector3[m_numVertices];
m_texCoords = new Vector2[m_numTexCoords];
m_normals = new Vector3[m_numNormals];
for (unsigned int i = 0; i < m_numMaterials; ++i)
{
m_materials[i].faces = new ObjFace[m_materials[i].numFaces];
}
return true;
}
bool Obj::LoadMaterialLibrary(const std::string &file, const std::string &texturePath)
{
std::ifstream input;
std::string line;
std::string op;
int currentMaterial = -1;
float r, g, b;
if (!CountDefinedMaterials(file))
return false;
m_materials = new ObjMaterial[m_numMaterials];
input.open(file.c_str());
if (input.fail())
return false;
while (!input.eof())
{
std::getline(input, line, '\n');
op = line.substr(0, line.find(' '));
// New material definition (possibility of multiple per .mtl file)
if (op == "newmtl")
{
++currentMaterial;
m_materials[currentMaterial].name = line.substr(op.length() + 1);
}
// Ambient color
else if (op == "Ka")
{
//ASSERT(currentMaterial >= 0);
sscanf(line.c_str(), "Ka %f %f %f", &r, &g, &b);
m_materials[currentMaterial].material->ambient = Color::FromInt(RGB_24_f(r, g, b));
}
// Diffuse color
else if (op == "Kd")
{
//ASSERT(currentMaterial >= 0);
sscanf(line.c_str(), "Kd %f %f %f", &r, &g, &b);
m_materials[currentMaterial].material->diffuse = Color::FromInt(RGB_24_f(r, g, b));
}
// Specular color
else if (op == "Ks")
{
//ASSERT(currentMaterial >= 0);
sscanf(line.c_str(), "Ks %f %f %f", &r, &g, &b);
m_materials[currentMaterial].material->specular = Color::FromInt(RGB_24_f(r, g, b));
}
// Alpha value
else if (op == "d" || op == "Tr")
{
//ASSERT(currentMaterial >= 0);
}
// Shininess
else if (op == "Ns")
{
//ASSERT(currentMaterial >= 0);
}
// Illumination model
else if (op == "illum")
{
//ASSERT(currentMaterial >= 0);
}
// Texture
else if (op == "map_Ka" || op == "map_Kd")
{
//ASSERT(currentMaterial >= 0);
m_materials[currentMaterial].material->textureFile = texturePath + line.substr(op.length() + 1);
}
}
input.close();
return true;
}
bool Obj::CountDefinedMaterials(const std::string &file)
{
std::ifstream input;
std::string line;
std::string op;
input.open(file.c_str());
if (input.fail())
return false;
while (!input.eof())
{
std::getline(input, line, '\n');
op = line.substr(0, line.find(' '));
if (op == "newmtl")
++m_numMaterials;
}
input.close();
return true;
}
bool Obj::FindAndLoadMaterials(const std::string &materialPath, const std::string &texturePath, const std::string &file)
{
std::ifstream input;
std::string line;
std::string op;
input.open(file.c_str());
if (input.fail())
return false;
while (!input.eof())
{
std::getline(input, line, '\n');
op = line.substr(0, line.find(' '));
if (op == "mtllib")
{
LoadMaterialLibrary(materialPath + line.substr(line.find(' ') + 1), texturePath);
break;
}
}
input.close();
return true;
}
bool Obj::ConvertToMesh(const std::string &file)
{
return false;
}

View file

@ -1,84 +0,0 @@
#ifndef __OBJ_H_INCLUDED__
#define __OBJ_H_INCLUDED__
#include "../geometry/vector3.h"
#include "../geometry/vector2.h"
#include "../assets/material.h"
#include <string>
enum OBJ_FACE_VERTEX_TYPE
{
OBJ_VERTEX_TEXCOORD,
OBJ_VERTEX_NORMAL,
OBJ_VERTEX_FULL
};
struct ObjFace
{
unsigned int vertices[3];
unsigned int texcoords[3];
unsigned int normals[3];
};
struct ObjMaterial
{
std::string name;
Material *material;
ObjFace *faces;
unsigned int numFaces;
unsigned int lastFaceIndex;
ObjMaterial()
{
material = new Material();
faces = NULL;
numFaces = 0;
lastFaceIndex = 0;
}
~ObjMaterial()
{
delete material;
delete[] faces;
}
};
class Obj
{
public:
Obj();
virtual ~Obj() { Release(); }
void Release();
bool Load(const std::string &file, const std::string &texturePath);
bool ConvertToMesh(const std::string &file);
int GetNumVertices() { return m_numVertices; }
int GetNumNormals() { return m_numNormals; }
int GetNumTexCoords() { return m_numTexCoords; }
int GetNumMaterials() { return m_numMaterials; }
Vector3* GetVertices() { return m_vertices; }
Vector3* GetNormals() { return m_normals; }
Vector2* GetTexCoords() { return m_texCoords; }
ObjMaterial* GetMaterials() { return m_materials; }
private:
bool GetDataSizes(const std::string &file);
bool LoadMaterialLibrary(const std::string &file, const std::string &texturePath);
bool CountDefinedMaterials(const std::string &file);
bool FindAndLoadMaterials(const std::string &materialPath, const std::string &texturePath, const std::string &file);
void ParseFaceDefinition(const std::string &faceDefinition, ObjMaterial *currentMaterial);
Vector3 *m_vertices;
Vector3 *m_normals;
Vector2 *m_texCoords;
ObjMaterial *m_materials;
unsigned int m_numVertices;
unsigned int m_numNormals;
unsigned int m_numTexCoords;
unsigned int m_numMaterials;
};
#endif

View file

@ -1,259 +0,0 @@
#include "sm.h"
#include <stdio.h>
#include "../util/files.h"
#include "../chunks/chunks.h"
StaticModel::StaticModel()
{
m_numMaterials = 0;
m_numPolygons = 0;
m_numVertices = 0;
m_numNormals = 0;
m_numTexCoords = 0;
m_hasNormals = false;
m_hasTexCoords = false;
m_hasColors = false;
m_materials = NULL;
m_polygons = NULL;
m_texCoords = NULL;
m_vertices = NULL;
m_normals = NULL;
}
void StaticModel::Release()
{
delete[] m_materials;
delete[] m_polygons;
delete[] m_texCoords;
delete[] m_vertices;
delete[] m_normals;
}
bool StaticModel::Load(const std::string &file)
{
FILE *fp;
unsigned short numMaterials;
unsigned int numPolys, numVertices, numNormals, numTexCoords;
unsigned int ambient, diffuse, specular, emission;
unsigned int n;
int currentMaterial;
float x, y, z;
unsigned char header[2];
std::string texture;
fp = fopen(file.c_str(), "rb");
if (!fp)
return false;
// Simple file type validation
fread(&header[0], 2, 1, fp);
if (header[0] != 'S' || header[1] != 'M')
return false;
fread(&numMaterials, 2, 1, fp);
fread(&numPolys, 4, 1, fp);
fread(&numVertices, 4, 1, fp);
fread(&numNormals, 4, 1, fp);
fread(&numTexCoords, 4, 1, fp);
m_materials = new SmMaterial[numMaterials];
m_polygons = new SmPolygon[numPolys];
m_texCoords = new Vector2[numTexCoords];
m_vertices = new Vector3[numVertices];
m_normals = new Vector3[numNormals];
//ASSERT(m_materials != NULL);
//ASSERT(m_polygons != NULL);
//ASSERT(m_texCoords != NULL);
//ASSERT(m_vertices != NULL);
//ASSERT(m_normals != NULL);
m_numMaterials = numMaterials;
m_numPolygons = numPolys;
m_numVertices = numVertices;
m_numNormals = numNormals;
m_numTexCoords = numTexCoords;
// Read in material definitions
for (int i = 0; i < m_numMaterials; ++i)
{
fread(&ambient, 4, 1, fp);
fread(&diffuse, 4, 1, fp);
fread(&specular, 4, 1, fp);
fread(&emission, 4, 1, fp);
m_materials[i].material->ambient = Color::FromInt(ambient);
m_materials[i].material->diffuse = Color::FromInt(diffuse);
m_materials[i].material->specular = Color::FromInt(specular);
m_materials[i].material->emissive = Color::FromInt(emission);
m_materials[i].material->shininess = 0.0f;
m_materials[i].material->opacity = COLOR_ALPHA_OPAQUE;
ReadString(fp, m_materials[i].material->name);
}
// Read in triangle definitions (all are indexes into raw data following)
currentMaterial = NO_MATERIAL;
for (unsigned int i = 0; i < m_numPolygons; ++i)
{
// Vertices
for (int j = 0; j < 3; ++j)
{
fread(&n, 4, 1, fp);
m_polygons[i].vertices[j] = n;
}
// Normals
for (int j = 0; j < 3; ++j)
{
fread(&n, 4, 1, fp);
m_polygons[i].normals[j] = n;
}
// TexCoords
for (int j = 0; j < 3; ++j)
{
fread(&n, 4, 1, fp);
m_polygons[i].texcoords[j] = n;
}
// Vertex colors
for (int j = 0; j < 3; ++j)
{
fread(&n, 2, 1, fp);
m_polygons[i].colors[j] = n;
}
// Material index
fread(&m_polygons[i].material, 2, 1, fp);
// Record start/end indices for the different materials
// This way rendering can be done per material while still only looping
// over all of this model's polygons once per frame
if (m_polygons[i].material != currentMaterial)
{
if (currentMaterial > NO_MATERIAL)
m_materials[currentMaterial].polyEnd = i;
currentMaterial = m_polygons[i].material;
m_materials[currentMaterial].polyStart = i;
}
// If any of the normals, texcoords, or colors are non-zero, we need to flag that such
// information exists in this model
if (m_polygons[i].colors[0] != 0 || m_polygons[i].colors[1] != 0 || m_polygons[i].colors[2] != 0)
m_hasColors = true;
}
// Will always include the last polygon due to the way the .SM exporter sorts
m_materials[currentMaterial].polyEnd = numPolys;
// Vertices
for (unsigned int i = 0; i < m_numVertices; ++i)
{
fread(&x, 4, 1, fp);
fread(&y, 4, 1, fp);
fread(&z, 4, 1, fp);
m_vertices[i].x = x / 2;
m_vertices[i].y = y / 2;
m_vertices[i].z = z / 2;
}
// Normals
for (unsigned int i = 0; i < m_numNormals; ++i)
{
fread(&x, 4, 1, fp);
fread(&y, 4, 1, fp);
fread(&z, 4, 1, fp);
//ASSERT(!((x >= 1.0f || x <= -1.0f) ||
// (y >= 1.0f || y <= -1.0f) ||
// (z >= 1.0f || z <= -1.0f)));
m_normals[i].x = x;
m_normals[i].y = y;
m_normals[i].z = z;
if (m_normals[i].x != 0 || m_normals[i].y != 0 || m_normals[i].z != 0)
m_hasNormals = true;
}
// Texture coordinates
for (unsigned int i = 0; i < m_numTexCoords; ++i)
{
fread(&x, 4, 1, fp);
fread(&y, 4, 1, fp);
//ASSERT(!((x >= 2048.0f || x <= -2048.0f) ||
// (y >= 2048.0f || y <= -2048.0f)));
// TODO: revisit this, seems a bit hack-ish and probably only correct
// for the shitty models I made
m_texCoords[i].x = x;
m_texCoords[i].y = -y;
if (m_texCoords[i].x != 0 || m_texCoords[i].y != 0)
m_hasTexCoords = true;
}
fclose(fp);
return true;
}
bool StaticModel::ConvertToMesh(const std::string &file)
{
FILE *fp = fopen(file.c_str(), "wb");
if (fp == NULL)
return false;
WriteFileHeader(fp);
VerticesChunk *verticesChunk = new VerticesChunk();
for (long i = 0; i < m_numVertices; ++i)
verticesChunk->vertices.push_back(m_vertices[i]);
WriteChunk(verticesChunk, fp);
SAFE_DELETE(verticesChunk);
NormalsChunk *normalsChunk = new NormalsChunk();
for (long i = 0; i < m_numNormals; ++i)
normalsChunk->normals.push_back(m_normals[i]);
WriteChunk(normalsChunk, fp);
SAFE_DELETE(normalsChunk);
TexCoordsChunk *texCoordsChunk = new TexCoordsChunk();
for (long i = 0; i < m_numTexCoords; ++i)
texCoordsChunk->texCoords.push_back(m_texCoords[i]);
WriteChunk(texCoordsChunk, fp);
SAFE_DELETE(texCoordsChunk);
MaterialsChunk *materialsChunk = new MaterialsChunk();
for (long i = 0; i < m_numMaterials; ++i)
materialsChunk->materials.push_back(*m_materials[i].material);
WriteChunk(materialsChunk, fp);
SAFE_DELETE(materialsChunk);
TrianglesChunk *trianglesChunk = new TrianglesChunk();
for (long i = 0; i < m_numPolygons; ++i)
{
Triangle t;
t.vertices[0] = m_polygons[i].vertices[0];
t.vertices[1] = m_polygons[i].vertices[1];
t.vertices[2] = m_polygons[i].vertices[2];
t.normals[0] = m_polygons[i].normals[0];
t.normals[1] = m_polygons[i].normals[1];
t.normals[2] = m_polygons[i].normals[2];
t.texCoords[0] = m_polygons[i].texcoords[0];
t.texCoords[1] = m_polygons[i].texcoords[1];
t.texCoords[2] = m_polygons[i].texcoords[2];
t.materialIndex = m_polygons[i].material;
trianglesChunk->triangles.push_back(t);
}
WriteChunk(trianglesChunk, fp);
fclose(fp);
return true;
}

View file

@ -1,73 +0,0 @@
#ifndef __SM_H_INCLUDED__
#define __SM_H_INCLUDED__
#include "../assets/material.h"
#include "../geometry/vector3.h"
#include "../geometry/vector2.h"
#include <string>
struct SmPolygon
{
unsigned int vertices[3];
unsigned int normals[3];
unsigned int texcoords[3];
unsigned short colors[3];
short material;
};
struct SmMaterial
{
Material *material;
unsigned int polyStart;
unsigned int polyEnd;
SmMaterial()
{
material = new Material();
polyStart = 0;
polyEnd = 0;
};
~SmMaterial()
{
delete material;
}
};
#define NO_MATERIAL -1
class StaticModel
{
public:
StaticModel();
virtual ~StaticModel() { Release(); }
void Release();
bool Load(const std::string &file);
bool ConvertToMesh(const std::string &file);
SmMaterial* GetMaterial(unsigned short index) { return &m_materials[index]; }
SmPolygon* GetPolygon(unsigned int index) { return &m_polygons[index]; }
Vector3* GetVertex(unsigned int index) { return &m_vertices[index]; }
unsigned int GetNumMaterials() { return (unsigned int)m_numMaterials; }
unsigned int GetNumPolygons() { return m_numPolygons; }
unsigned int GetNumVertices() { return m_numVertices; }
private:
SmMaterial *m_materials;
SmPolygon *m_polygons;
Vector3 *m_vertices;
Vector3 *m_normals;
Vector2 *m_texCoords;
int m_numMaterials;
unsigned int m_numPolygons;
unsigned int m_numVertices;
unsigned int m_numNormals;
unsigned int m_numTexCoords;
bool m_hasNormals;
bool m_hasTexCoords;
bool m_hasColors;
};
#endif