removed all other model import/exporting except for md2
This commit is contained in:
parent
3b29691ce7
commit
b5b9558432
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -7,4 +7,4 @@ Debug/
|
||||||
Release/
|
Release/
|
||||||
ipch/
|
ipch/
|
||||||
*.suo
|
*.suo
|
||||||
meshconverter
|
md2tomesh
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
# this Makefile is based on the ones from devkitPro
|
# this Makefile is based on the ones from devkitPro
|
||||||
# TODO: probably should simplify it a bunch (mainly the rules at the bottom)
|
# TODO: probably should simplify it a bunch (mainly the rules at the bottom)
|
||||||
|
|
||||||
TARGET := meshconverter
|
TARGET := md2tomesh
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -7,44 +7,6 @@ void WriteFileHeader(FILE *fp)
|
||||||
fwrite(&version, 1, 1, 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)
|
void WriteChunk(TexCoordsChunk *chunk, FILE *fp)
|
||||||
{
|
{
|
||||||
uint32_t size = chunk->GetSize();
|
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)
|
void WriteChunk(KeyFramesChunk *chunk, FILE *fp)
|
||||||
{
|
{
|
||||||
uint32_t size = chunk->GetSize();
|
uint32_t size = chunk->GetSize();
|
||||||
|
@ -219,3 +105,4 @@ void WriteChunk(AnimationsChunk *chunk, FILE *fp)
|
||||||
fwrite(&a->end, 4, 1, fp);
|
fwrite(&a->end, 4, 1, fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
// 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 "texcoords.h"
|
||||||
#include "materials.h"
|
|
||||||
#include "triangles.h"
|
|
||||||
#include "keyframes.h"
|
#include "keyframes.h"
|
||||||
#include "keyframetriangles.h"
|
#include "keyframetriangles.h"
|
||||||
#include "animations.h"
|
#include "animations.h"
|
||||||
|
|
||||||
void WriteChunk(VerticesChunk *chunk, FILE *fp);
|
|
||||||
void WriteChunk(NormalsChunk *chunk, FILE *fp);
|
|
||||||
void WriteChunk(TexCoordsChunk *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(KeyFramesChunk *chunk, FILE *fp);
|
||||||
void WriteChunk(KeyFrameTrianglesChunk *chunk, FILE *fp);
|
void WriteChunk(KeyFrameTrianglesChunk *chunk, FILE *fp);
|
||||||
void WriteChunk(AnimationsChunk *chunk, FILE *fp);
|
void WriteChunk(AnimationsChunk *chunk, FILE *fp);
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
@ -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
|
|
|
@ -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
|
|
80
src/main.cpp
80
src/main.cpp
|
@ -3,18 +3,14 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
#include "md2/md2.h"
|
#include "md2/md2.h"
|
||||||
#include "obj/obj.h"
|
|
||||||
#include "sm/sm.h"
|
|
||||||
#include "ms3d/ms3d.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
printf("MESH Converter\n");
|
printf("MD2-to-MESH Converter\n");
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
{
|
{
|
||||||
printf("No input file specified.\n");
|
printf("Usage: md2tomesh.exe [inputfile]\n\n");
|
||||||
printf("Usage: meshconverter.exe [inputfile]\n\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,73 +36,15 @@ int main(int argc, char **argv)
|
||||||
meshFile.append(".mesh");
|
meshFile.append(".mesh");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extension == ".obj")
|
Md2 *md2 = new Md2();
|
||||||
|
if (!md2->Load(file))
|
||||||
{
|
{
|
||||||
printf("Using OBJ converter.\n");
|
printf("Error loading MD2 file.\n\n");
|
||||||
|
return 1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (extension == ".md2")
|
if (!md2->ConvertToMesh(meshFile))
|
||||||
{
|
{
|
||||||
printf("Using MD2 converter.\n");
|
printf("Error converting MD2 to MESH.\n\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");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,4 +52,4 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
146
src/ms3d/ms3d.h
146
src/ms3d/ms3d.h
|
@ -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
|
|
496
src/obj/obj.cpp
496
src/obj/obj.cpp
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
259
src/sm/sm.cpp
259
src/sm/sm.cpp
|
@ -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;
|
|
||||||
}
|
|
73
src/sm/sm.h
73
src/sm/sm.h
|
@ -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
|
|
Reference in a new issue