From 87a60137f1135b1cefc33913ea40544c688d4603 Mon Sep 17 00:00:00 2001 From: gered Date: Tue, 7 Jun 2011 11:30:05 -0400 Subject: [PATCH] Fix CRLF --- .gitignore | 18 +- MeshConverter.sln | 40 +- MeshConverter/MeshConverter.vcxproj | 242 +- MeshConverter/src/assets/animationsequence.h | 30 +- MeshConverter/src/assets/color.h | 160 +- MeshConverter/src/assets/material.h | 48 +- MeshConverter/src/chunks/animations.h | 66 +- MeshConverter/src/chunks/chunks.cpp | 442 ++-- MeshConverter/src/chunks/chunks.h | 58 +- MeshConverter/src/chunks/keyframes.h | 110 +- MeshConverter/src/chunks/keyframetriangles.h | 66 +- MeshConverter/src/chunks/materials.h | 76 +- MeshConverter/src/chunks/normals.h | 62 +- MeshConverter/src/chunks/texcoords.h | 62 +- MeshConverter/src/chunks/triangles.h | 70 +- MeshConverter/src/chunks/vertices.h | 62 +- MeshConverter/src/common.h | 52 +- MeshConverter/src/geometry/common.h | 38 +- MeshConverter/src/geometry/keyframe.h | 56 +- MeshConverter/src/geometry/keyframetriangle.h | 26 +- MeshConverter/src/geometry/matrix4x4.h | 2060 ++++++++--------- MeshConverter/src/geometry/quaternion.h | 982 ++++---- MeshConverter/src/geometry/triangle.h | 30 +- MeshConverter/src/geometry/vector2.h | 472 ++-- MeshConverter/src/geometry/vector3.h | 682 +++--- MeshConverter/src/main.cpp | 232 +- MeshConverter/src/md2/md2.cpp | 716 +++--- MeshConverter/src/md2/md2.h | 198 +- MeshConverter/src/ms3d/ms3d.cpp | 870 +++---- MeshConverter/src/ms3d/ms3d.h | 292 +-- MeshConverter/src/obj/obj.cpp | 992 ++++---- MeshConverter/src/obj/obj.h | 166 +- MeshConverter/src/sm/sm.cpp | 522 ++--- MeshConverter/src/sm/sm.h | 144 +- MeshConverter/src/util/files.cpp | 50 +- MeshConverter/src/util/files.h | 18 +- 36 files changed, 5105 insertions(+), 5105 deletions(-) diff --git a/.gitignore b/.gitignore index 7517879..c764f33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ - -*.sdf -*.opensdf -*.user -*.vcxproj.filters -Debug/ -Release/ -ipch/ - + +*.sdf +*.opensdf +*.user +*.vcxproj.filters +Debug/ +Release/ +ipch/ + *.suo \ No newline at end of file diff --git a/MeshConverter.sln b/MeshConverter.sln index d11635a..863c888 100644 --- a/MeshConverter.sln +++ b/MeshConverter.sln @@ -1,20 +1,20 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeshConverter", "MeshConverter\MeshConverter.vcxproj", "{AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Debug|Win32.ActiveCfg = Debug|Win32 - {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Debug|Win32.Build.0 = Debug|Win32 - {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Release|Win32.ActiveCfg = Release|Win32 - {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeshConverter", "MeshConverter\MeshConverter.vcxproj", "{AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Debug|Win32.ActiveCfg = Debug|Win32 + {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Debug|Win32.Build.0 = Debug|Win32 + {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Release|Win32.ActiveCfg = Release|Win32 + {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/MeshConverter/MeshConverter.vcxproj b/MeshConverter/MeshConverter.vcxproj index ec1cf63..4e82744 100644 --- a/MeshConverter/MeshConverter.vcxproj +++ b/MeshConverter/MeshConverter.vcxproj @@ -1,122 +1,122 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C} - Win32Proj - MeshConverter - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - true - E:\assimp--2.0.863-sdk\include;$(IncludePath) - E:\assimp--2.0.863-sdk\lib\assimp_debug-dll_win32;$(LibraryPath) - - - false - E:\assimp--2.0.863-sdk\include;$(IncludePath) - E:\assimp--2.0.863-sdk\lib\assimp_release-dll_win32;$(LibraryPath) - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - Console - true - assimp.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - assimp.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + + {AADE0387-ED8A-46E2-B2DA-FC521DF7CB9C} + Win32Proj + MeshConverter + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + E:\assimp--2.0.863-sdk\include;$(IncludePath) + E:\assimp--2.0.863-sdk\lib\assimp_debug-dll_win32;$(LibraryPath) + + + false + E:\assimp--2.0.863-sdk\include;$(IncludePath) + E:\assimp--2.0.863-sdk\lib\assimp_release-dll_win32;$(LibraryPath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Console + true + assimp.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + assimp.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MeshConverter/src/assets/animationsequence.h b/MeshConverter/src/assets/animationsequence.h index e68aff3..c1ba765 100644 --- a/MeshConverter/src/assets/animationsequence.h +++ b/MeshConverter/src/assets/animationsequence.h @@ -1,15 +1,15 @@ -#ifndef __ASSETS_ANIMATIONSEQUENCE_H_INCLUDED__ -#define __ASSETS_ANIMATIONSEQUENCE_H_INCLUDED__ - -#include "../common.h" -#include - -class AnimationSequence -{ -public: - std::string name; - uint32_t start; - uint32_t end; -}; - -#endif +#ifndef __ASSETS_ANIMATIONSEQUENCE_H_INCLUDED__ +#define __ASSETS_ANIMATIONSEQUENCE_H_INCLUDED__ + +#include "../common.h" +#include + +class AnimationSequence +{ +public: + std::string name; + uint32_t start; + uint32_t end; +}; + +#endif diff --git a/MeshConverter/src/assets/color.h b/MeshConverter/src/assets/color.h index b7633da..56c51dd 100644 --- a/MeshConverter/src/assets/color.h +++ b/MeshConverter/src/assets/color.h @@ -1,80 +1,80 @@ -#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 +#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 diff --git a/MeshConverter/src/assets/material.h b/MeshConverter/src/assets/material.h index dbbe9f5..4a221b3 100644 --- a/MeshConverter/src/assets/material.h +++ b/MeshConverter/src/assets/material.h @@ -1,25 +1,25 @@ -#ifndef __ASSETS_MATERIAL_H_INCLUDED__ -#define __ASSETS_MATERIAL_H_INCLUDED__ - -#include "../common.h" -#include -#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; - Color ambient; - Color diffuse; - Color specular; - Color emissive; - float shininess; - float opacity; -}; - +#ifndef __ASSETS_MATERIAL_H_INCLUDED__ +#define __ASSETS_MATERIAL_H_INCLUDED__ + +#include "../common.h" +#include +#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; + Color ambient; + Color diffuse; + Color specular; + Color emissive; + float shininess; + float opacity; +}; + #endif \ No newline at end of file diff --git a/MeshConverter/src/chunks/animations.h b/MeshConverter/src/chunks/animations.h index 7da5d7c..75d3a90 100644 --- a/MeshConverter/src/chunks/animations.h +++ b/MeshConverter/src/chunks/animations.h @@ -1,33 +1,33 @@ -#ifndef __CHUNKS_ANIMATIONS_H_INCLUDED__ -#define __CHUNKS_ANIMATIONS_H_INCLUDED__ - -#include "../common.h" -#include "../assets/animationsequence.h" -#include - -struct AnimationsChunk -{ - std::vector animations; - - uint32_t GetCount() - { - return animations.size(); - } - - uint32_t GetSize() - { - if (animations.size() == 0) - return 0; - - uint32_t size = sizeof(uint32_t); - for (uint32_t i = 0; i < animations.size(); ++i) - { - size += animations[i].name.length() + 1; // include null terminator - size += sizeof(uint32_t) * 2; // start + end - } - - return size; - } -}; - -#endif +#ifndef __CHUNKS_ANIMATIONS_H_INCLUDED__ +#define __CHUNKS_ANIMATIONS_H_INCLUDED__ + +#include "../common.h" +#include "../assets/animationsequence.h" +#include + +struct AnimationsChunk +{ + std::vector animations; + + uint32_t GetCount() + { + return animations.size(); + } + + uint32_t GetSize() + { + if (animations.size() == 0) + return 0; + + uint32_t size = sizeof(uint32_t); + for (uint32_t i = 0; i < animations.size(); ++i) + { + size += animations[i].name.length() + 1; // include null terminator + size += sizeof(uint32_t) * 2; // start + end + } + + return size; + } +}; + +#endif diff --git a/MeshConverter/src/chunks/chunks.cpp b/MeshConverter/src/chunks/chunks.cpp index aa2df21..ee4b38f 100644 --- a/MeshConverter/src/chunks/chunks.cpp +++ b/MeshConverter/src/chunks/chunks.cpp @@ -1,221 +1,221 @@ -#include "chunks.h" - -void WriteFileHeader(FILE *fp) -{ - fputs("MESH", fp); - uint8_t version = 1; - 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(); - if (size == 0) - return; - - fputs("TXT", 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->texCoords[i].x, sizeof(float), 1, fp); - fwrite(&chunk->texCoords[i].y, sizeof(float), 1, 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(); - if (size == 0) - return; - - fputs("KFR", fp); - fwrite(&size, 4, 1, fp); - uint32_t numFrames = chunk->GetNumFrames(); - fwrite(&numFrames, 4, 1, fp); - fwrite(&chunk->numVertices, 4, 1, fp); - - for (uint32_t i = 0; i < numFrames; ++i) - { - KeyFrame *f = chunk->frames[i]; - - for (uint32_t j = 0; j < chunk->numVertices; ++j) - { - fwrite(&f->vertices->x, sizeof(float), 1, fp); - fwrite(&f->vertices->y, sizeof(float), 1, fp); - fwrite(&f->vertices->z, sizeof(float), 1, fp); - } - - for (uint32_t j = 0; j < chunk->numVertices; ++j) - { - fwrite(&f->normals->x, sizeof(float), 1, fp); - fwrite(&f->normals->y, sizeof(float), 1, fp); - fwrite(&f->normals->z, sizeof(float), 1, fp); - } - } -} - -void WriteChunk(KeyFrameTrianglesChunk *chunk, FILE *fp) -{ - uint32_t size = chunk->GetSize(); - if (size == 0) - return; - - fputs("KTR", fp); - fwrite(&size, 4, 1, fp); - uint32_t count = chunk->GetCount(); - fwrite(&count, 4, 1, fp); - - for (uint32_t i = 0; i < count; ++i) - { - KeyFrameTriangle *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->texCoords[0], 4, 1, fp); - fwrite(&t->texCoords[1], 4, 1, fp); - fwrite(&t->texCoords[2], 4, 1, fp); - } -} - -void WriteChunk(AnimationsChunk *chunk, FILE *fp) -{ - uint32_t size = chunk->GetSize(); - if (size == 0) - return; - - fputs("ANI", fp); - fwrite(&size, 4, 1, fp); - uint32_t count = chunk->GetCount(); - fwrite(&count, 4, 1, fp); - - for (uint32_t i = 0; i < count; ++i) - { - AnimationSequence *a = &chunk->animations[i]; - - fwrite(a->name.c_str(), a->name.length(), 1, fp); - char ch = '\0'; - fwrite(&ch, 1, 1, fp); - - fwrite(&a->start, 4, 1, fp); - fwrite(&a->end, 4, 1, fp); - } -} +#include "chunks.h" + +void WriteFileHeader(FILE *fp) +{ + fputs("MESH", fp); + uint8_t version = 1; + 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(); + if (size == 0) + return; + + fputs("TXT", 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->texCoords[i].x, sizeof(float), 1, fp); + fwrite(&chunk->texCoords[i].y, sizeof(float), 1, 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(); + if (size == 0) + return; + + fputs("KFR", fp); + fwrite(&size, 4, 1, fp); + uint32_t numFrames = chunk->GetNumFrames(); + fwrite(&numFrames, 4, 1, fp); + fwrite(&chunk->numVertices, 4, 1, fp); + + for (uint32_t i = 0; i < numFrames; ++i) + { + KeyFrame *f = chunk->frames[i]; + + for (uint32_t j = 0; j < chunk->numVertices; ++j) + { + fwrite(&f->vertices->x, sizeof(float), 1, fp); + fwrite(&f->vertices->y, sizeof(float), 1, fp); + fwrite(&f->vertices->z, sizeof(float), 1, fp); + } + + for (uint32_t j = 0; j < chunk->numVertices; ++j) + { + fwrite(&f->normals->x, sizeof(float), 1, fp); + fwrite(&f->normals->y, sizeof(float), 1, fp); + fwrite(&f->normals->z, sizeof(float), 1, fp); + } + } +} + +void WriteChunk(KeyFrameTrianglesChunk *chunk, FILE *fp) +{ + uint32_t size = chunk->GetSize(); + if (size == 0) + return; + + fputs("KTR", fp); + fwrite(&size, 4, 1, fp); + uint32_t count = chunk->GetCount(); + fwrite(&count, 4, 1, fp); + + for (uint32_t i = 0; i < count; ++i) + { + KeyFrameTriangle *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->texCoords[0], 4, 1, fp); + fwrite(&t->texCoords[1], 4, 1, fp); + fwrite(&t->texCoords[2], 4, 1, fp); + } +} + +void WriteChunk(AnimationsChunk *chunk, FILE *fp) +{ + uint32_t size = chunk->GetSize(); + if (size == 0) + return; + + fputs("ANI", fp); + fwrite(&size, 4, 1, fp); + uint32_t count = chunk->GetCount(); + fwrite(&count, 4, 1, fp); + + for (uint32_t i = 0; i < count; ++i) + { + AnimationSequence *a = &chunk->animations[i]; + + fwrite(a->name.c_str(), a->name.length(), 1, fp); + char ch = '\0'; + fwrite(&ch, 1, 1, fp); + + fwrite(&a->start, 4, 1, fp); + fwrite(&a->end, 4, 1, fp); + } +} diff --git a/MeshConverter/src/chunks/chunks.h b/MeshConverter/src/chunks/chunks.h index a7c1e8c..8cb4fb4 100644 --- a/MeshConverter/src/chunks/chunks.h +++ b/MeshConverter/src/chunks/chunks.h @@ -1,29 +1,29 @@ -#ifndef __CHUNKS_CHUNKS_H_INCLUDED__ -#define __CHUNKS_CHUNKS_H_INCLUDED__ - -#include "../common.h" -#include - -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); - -#endif +#ifndef __CHUNKS_CHUNKS_H_INCLUDED__ +#define __CHUNKS_CHUNKS_H_INCLUDED__ + +#include "../common.h" +#include + +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); + +#endif diff --git a/MeshConverter/src/chunks/keyframes.h b/MeshConverter/src/chunks/keyframes.h index 6cf68ad..6eb3ac0 100644 --- a/MeshConverter/src/chunks/keyframes.h +++ b/MeshConverter/src/chunks/keyframes.h @@ -1,55 +1,55 @@ -#ifndef __CHUNKS_KEYFRAMES_H_INCLUDED__ -#define __CHUNKS_KEYFRAMES_H_INCLUDED__ - -#include "../common.h" -#include "../geometry/keyframe.h" -#include - -struct KeyFramesChunk -{ - std::vector frames; - uint32_t numVertices; - - KeyFramesChunk() - { - numVertices = 0; - } - - ~KeyFramesChunk() - { - for (uint32_t i = 0; i < frames.size(); ++i) - SAFE_DELETE(frames[i]); - } - - KeyFrame* AddFrame() - { - KeyFrame *newFrame = new KeyFrame(numVertices); - frames.push_back(newFrame); - return newFrame; - } - - uint32_t GetNumFrames() - { - return frames.size(); - } - - uint32_t GetSize() - { - if (frames.size() == 0) - return 0; - - uint32_t size = 4; // count - for (uint32_t i = 0; i < frames.size(); ++i) - { - size += - ( - (sizeof(float) * 3) // vertex - + (sizeof(float) * 3) // normal - ) * frames[i]->count; - } - - return size; - } -}; - -#endif +#ifndef __CHUNKS_KEYFRAMES_H_INCLUDED__ +#define __CHUNKS_KEYFRAMES_H_INCLUDED__ + +#include "../common.h" +#include "../geometry/keyframe.h" +#include + +struct KeyFramesChunk +{ + std::vector frames; + uint32_t numVertices; + + KeyFramesChunk() + { + numVertices = 0; + } + + ~KeyFramesChunk() + { + for (uint32_t i = 0; i < frames.size(); ++i) + SAFE_DELETE(frames[i]); + } + + KeyFrame* AddFrame() + { + KeyFrame *newFrame = new KeyFrame(numVertices); + frames.push_back(newFrame); + return newFrame; + } + + uint32_t GetNumFrames() + { + return frames.size(); + } + + uint32_t GetSize() + { + if (frames.size() == 0) + return 0; + + uint32_t size = 4; // count + for (uint32_t i = 0; i < frames.size(); ++i) + { + size += + ( + (sizeof(float) * 3) // vertex + + (sizeof(float) * 3) // normal + ) * frames[i]->count; + } + + return size; + } +}; + +#endif diff --git a/MeshConverter/src/chunks/keyframetriangles.h b/MeshConverter/src/chunks/keyframetriangles.h index 4fac260..c0e1348 100644 --- a/MeshConverter/src/chunks/keyframetriangles.h +++ b/MeshConverter/src/chunks/keyframetriangles.h @@ -1,33 +1,33 @@ -#ifndef __CHUNKS_KEYFRAMETRIANGLES_H_INCLUDED__ -#define __CHUNKS_KEYFRAMETRIANGLES_H_INCLUDED__ - -#include "../common.h" -#include "../geometry/keyframetriangle.h" -#include - -struct KeyFrameTrianglesChunk -{ - std::vector triangles; - - uint32_t GetCount() - { - return triangles.size(); - } - - uint32_t GetSize() - { - if (triangles.size() == 0) - return 0; - - uint32_t size = 4; // count - size += - ( - (sizeof(uint32_t) * 3) // vertex indices - + (sizeof(uint32_t) * 3) // texcoord indices - ) * triangles.size(); - - return size; - } -}; - -#endif +#ifndef __CHUNKS_KEYFRAMETRIANGLES_H_INCLUDED__ +#define __CHUNKS_KEYFRAMETRIANGLES_H_INCLUDED__ + +#include "../common.h" +#include "../geometry/keyframetriangle.h" +#include + +struct KeyFrameTrianglesChunk +{ + std::vector triangles; + + uint32_t GetCount() + { + return triangles.size(); + } + + uint32_t GetSize() + { + if (triangles.size() == 0) + return 0; + + uint32_t size = 4; // count + size += + ( + (sizeof(uint32_t) * 3) // vertex indices + + (sizeof(uint32_t) * 3) // texcoord indices + ) * triangles.size(); + + return size; + } +}; + +#endif diff --git a/MeshConverter/src/chunks/materials.h b/MeshConverter/src/chunks/materials.h index 18521d2..cfb10c2 100644 --- a/MeshConverter/src/chunks/materials.h +++ b/MeshConverter/src/chunks/materials.h @@ -1,38 +1,38 @@ -#ifndef __CHUNK_MATERIALS_H_INCLUDED__ -#define __CHUNK_MATERIALS_H_INCLUDED__ - -#include "../common.h" -#include "../assets/material.h" -#include - -struct MaterialsChunk -{ - std::vector 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 +#ifndef __CHUNK_MATERIALS_H_INCLUDED__ +#define __CHUNK_MATERIALS_H_INCLUDED__ + +#include "../common.h" +#include "../assets/material.h" +#include + +struct MaterialsChunk +{ + std::vector 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 diff --git a/MeshConverter/src/chunks/normals.h b/MeshConverter/src/chunks/normals.h index 2e1bce6..a32fd67 100644 --- a/MeshConverter/src/chunks/normals.h +++ b/MeshConverter/src/chunks/normals.h @@ -1,31 +1,31 @@ -#ifndef __CHUNKS_NORMALS_H_INCLUDED__ -#define __CHUNKS_NORMALS_H_INCLUDED__ - -#include "../common.h" -#include "../geometry/vector3.h" -#include - -struct NormalsChunk -{ - std::vector 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 +#ifndef __CHUNKS_NORMALS_H_INCLUDED__ +#define __CHUNKS_NORMALS_H_INCLUDED__ + +#include "../common.h" +#include "../geometry/vector3.h" +#include + +struct NormalsChunk +{ + std::vector 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 diff --git a/MeshConverter/src/chunks/texcoords.h b/MeshConverter/src/chunks/texcoords.h index 01766b3..30e78ac 100644 --- a/MeshConverter/src/chunks/texcoords.h +++ b/MeshConverter/src/chunks/texcoords.h @@ -1,31 +1,31 @@ -#ifndef __CHUNKS_TEXCOORDS_H_INCLUDED__ -#define __CHUNKS_TEXCOORDS_H_INCLUDED__ - -#include "../common.h" -#include "../geometry/vector2.h" -#include - -struct TexCoordsChunk -{ - std::vector texCoords; - - uint32_t GetCount() - { - return texCoords.size(); - } - - uint32_t GetSize() - { - if (texCoords.size() == 0) - return 0; - - uint32_t size = 4; // count - size += - (sizeof(float) * 2) // u, v - * texCoords.size(); - - return size; - } -}; - -#endif +#ifndef __CHUNKS_TEXCOORDS_H_INCLUDED__ +#define __CHUNKS_TEXCOORDS_H_INCLUDED__ + +#include "../common.h" +#include "../geometry/vector2.h" +#include + +struct TexCoordsChunk +{ + std::vector texCoords; + + uint32_t GetCount() + { + return texCoords.size(); + } + + uint32_t GetSize() + { + if (texCoords.size() == 0) + return 0; + + uint32_t size = 4; // count + size += + (sizeof(float) * 2) // u, v + * texCoords.size(); + + return size; + } +}; + +#endif diff --git a/MeshConverter/src/chunks/triangles.h b/MeshConverter/src/chunks/triangles.h index 921bd5e..066af71 100644 --- a/MeshConverter/src/chunks/triangles.h +++ b/MeshConverter/src/chunks/triangles.h @@ -1,35 +1,35 @@ -#ifndef __CHUNKS_TRIANGLES_H_INCLUDED__ -#define __CHUNKS_TRIANGLES_H_INCLUDED__ - -#include "../common.h" -#include "../geometry/triangle.h" -#include - -struct TrianglesChunk -{ - std::vector 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 +#ifndef __CHUNKS_TRIANGLES_H_INCLUDED__ +#define __CHUNKS_TRIANGLES_H_INCLUDED__ + +#include "../common.h" +#include "../geometry/triangle.h" +#include + +struct TrianglesChunk +{ + std::vector 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 diff --git a/MeshConverter/src/chunks/vertices.h b/MeshConverter/src/chunks/vertices.h index c4fd1d0..9f5860a 100644 --- a/MeshConverter/src/chunks/vertices.h +++ b/MeshConverter/src/chunks/vertices.h @@ -1,31 +1,31 @@ -#ifndef __CHUNKS_VERTICES_H_INCLUDED__ -#define __CHUNKS_VERTICES_H_INCLUDED__ - -#include "../common.h" -#include "../geometry/vector3.h" -#include - -struct VerticesChunk -{ - std::vector 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 +#ifndef __CHUNKS_VERTICES_H_INCLUDED__ +#define __CHUNKS_VERTICES_H_INCLUDED__ + +#include "../common.h" +#include "../geometry/vector3.h" +#include + +struct VerticesChunk +{ + std::vector 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 diff --git a/MeshConverter/src/common.h b/MeshConverter/src/common.h index e31b704..de34812 100644 --- a/MeshConverter/src/common.h +++ b/MeshConverter/src/common.h @@ -1,27 +1,27 @@ -#ifndef __COMMON_H_INCLUDED__ -#define __COMMON_H_INCLUDED__ - -#include - -#if !defined(TRUE) && !defined(FALSE) -typedef int32_t BOOL; -const BOOL TRUE = 1; -const BOOL FALSE = 0; -#endif - -#ifndef SAFE_RELEASE -#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = NULL; } -#endif - -#ifndef SAFE_DELETE -#define SAFE_DELETE(x) if (x) { delete (x); (x) = NULL; } -#endif - -#ifndef SAFE_DELETE_ARRAY -#define SAFE_DELETE_ARRAY(x) if (x) { delete [] (x); (x) = NULL; } -#endif - -#define MAX(a, b) ( (a) > (b) ? (a) : (b) ) -#define MIN(a, b) ( (a) < (b) ? (a) : (b) ) - +#ifndef __COMMON_H_INCLUDED__ +#define __COMMON_H_INCLUDED__ + +#include + +#if !defined(TRUE) && !defined(FALSE) +typedef int32_t BOOL; +const BOOL TRUE = 1; +const BOOL FALSE = 0; +#endif + +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = NULL; } +#endif + +#ifndef SAFE_DELETE +#define SAFE_DELETE(x) if (x) { delete (x); (x) = NULL; } +#endif + +#ifndef SAFE_DELETE_ARRAY +#define SAFE_DELETE_ARRAY(x) if (x) { delete [] (x); (x) = NULL; } +#endif + +#define MAX(a, b) ( (a) > (b) ? (a) : (b) ) +#define MIN(a, b) ( (a) < (b) ? (a) : (b) ) + #endif \ No newline at end of file diff --git a/MeshConverter/src/geometry/common.h b/MeshConverter/src/geometry/common.h index d5060fa..9af4f32 100644 --- a/MeshConverter/src/geometry/common.h +++ b/MeshConverter/src/geometry/common.h @@ -1,19 +1,19 @@ -#ifndef __GEOMETRY_COMMON_H_INCLUDED__ -#define __GEOMETRY_COMMON_H_INCLUDED__ - -#include - -#define PI 3.141593f -#define PI_OVER_180 (PI / 180.0f) - -#define DEG_TO_RAD(x) ((x) * PI_OVER_180) -#define RAD_TO_DEG(x) ((x) * (1.0f / (PI_OVER_180))) - -#define TOLERANCE 0.00001f -#define IS_CLOSE_ENOUGH(a, b) (fabs((a - b) / ((b == 0.0f) ? 1.0f : b)) < EPSILON) - -#define EPSILON 0.0005f - -#define ISPOWEROF2(x) (((x) != 0) && !((x) & ((x) - 1))) - -#endif +#ifndef __GEOMETRY_COMMON_H_INCLUDED__ +#define __GEOMETRY_COMMON_H_INCLUDED__ + +#include + +#define PI 3.141593f +#define PI_OVER_180 (PI / 180.0f) + +#define DEG_TO_RAD(x) ((x) * PI_OVER_180) +#define RAD_TO_DEG(x) ((x) * (1.0f / (PI_OVER_180))) + +#define TOLERANCE 0.00001f +#define IS_CLOSE_ENOUGH(a, b) (fabs((a - b) / ((b == 0.0f) ? 1.0f : b)) < EPSILON) + +#define EPSILON 0.0005f + +#define ISPOWEROF2(x) (((x) != 0) && !((x) & ((x) - 1))) + +#endif diff --git a/MeshConverter/src/geometry/keyframe.h b/MeshConverter/src/geometry/keyframe.h index e56b229..d0edd98 100644 --- a/MeshConverter/src/geometry/keyframe.h +++ b/MeshConverter/src/geometry/keyframe.h @@ -1,28 +1,28 @@ -#ifndef __GEOMETRY_KEYFRAME_H_INCLUDED__ -#define __GEOMETRY_KEYFRAME_H_INCLUDED__ - -#include "../common.h" -#include "vector3.h" - -class KeyFrame -{ -public: - uint32_t count; - Vector3 *vertices; - Vector3 *normals; - - KeyFrame(uint32_t numVertices) - { - count = numVertices; - vertices = new Vector3[count]; - normals = new Vector3[count]; - } - - ~KeyFrame() - { - SAFE_DELETE_ARRAY(vertices); - SAFE_DELETE_ARRAY(normals); - } -}; - -#endif +#ifndef __GEOMETRY_KEYFRAME_H_INCLUDED__ +#define __GEOMETRY_KEYFRAME_H_INCLUDED__ + +#include "../common.h" +#include "vector3.h" + +class KeyFrame +{ +public: + uint32_t count; + Vector3 *vertices; + Vector3 *normals; + + KeyFrame(uint32_t numVertices) + { + count = numVertices; + vertices = new Vector3[count]; + normals = new Vector3[count]; + } + + ~KeyFrame() + { + SAFE_DELETE_ARRAY(vertices); + SAFE_DELETE_ARRAY(normals); + } +}; + +#endif diff --git a/MeshConverter/src/geometry/keyframetriangle.h b/MeshConverter/src/geometry/keyframetriangle.h index 387da8e..c9f8e8e 100644 --- a/MeshConverter/src/geometry/keyframetriangle.h +++ b/MeshConverter/src/geometry/keyframetriangle.h @@ -1,13 +1,13 @@ -#ifndef __GEOMETRY_KEYFRAMETRIANGLE_H_INCLUDED__ -#define __GEOMETRY_KEYFRAMETRIANGLE_H_INCLUDED__ - -#include "../common.h" - -class KeyFrameTriangle -{ -public: - uint32_t vertices[3]; - uint32_t texCoords[3]; -}; - -#endif +#ifndef __GEOMETRY_KEYFRAMETRIANGLE_H_INCLUDED__ +#define __GEOMETRY_KEYFRAMETRIANGLE_H_INCLUDED__ + +#include "../common.h" + +class KeyFrameTriangle +{ +public: + uint32_t vertices[3]; + uint32_t texCoords[3]; +}; + +#endif diff --git a/MeshConverter/src/geometry/matrix4x4.h b/MeshConverter/src/geometry/matrix4x4.h index b6e4a42..1f04ddf 100644 --- a/MeshConverter/src/geometry/matrix4x4.h +++ b/MeshConverter/src/geometry/matrix4x4.h @@ -1,1030 +1,1030 @@ -#ifndef __GEOMETRY_MATRIX4X4_H_INCLUDED__ -#define __GEOMETRY_MATRIX4X4_H_INCLUDED__ - -#include -#include "common.h" -#include "vector3.h" - -typedef enum -{ - _11 = 0, - _12 = 4, - _13 = 8, - _14 = 12, - _21 = 1, - _22 = 5, - _23 = 9, - _24 = 13, - _31 = 2, - _32 = 6, - _33 = 10, - _34 = 14, - _41 = 3, - _42 = 7, - _43 = 11, - _44 = 15 -} MATRIX_ELEMENTS; - -/** - * Represents a 4x4 column-major Matrix and provides common methods for - * matrix math. - *

Referenced/based on code from:

- *
    - *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • - *
  • http://www.dhpoware.com/source/mathlib.html
  • - *
  • http://www.songho.ca/opengl/gl_transform.html
  • - *
  • http://www.opengl.org/sdk/docs/man/
  • - *
- * @author Gered - */ -class Matrix4x4 -{ -public: - Matrix4x4() {} - - Matrix4x4( - float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44 - ); - - Matrix4x4(const float *mv); - - ~Matrix4x4() {} - - void Set( - float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44 - ); - float GetDeterminant() const; - Vector3 GetForward() const; - Vector3 GetBackward() const; - Vector3 GetLeft() const; - Vector3 GetRight() const; - Vector3 GetUp() const; - Vector3 GetDown() const; - Vector3 GetTranslation() const; - - static Matrix4x4 Identity(); - static Matrix4x4 CreateBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraUp, const Vector3 &cameraForward); - static Matrix4x4 CreateCylindricalBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraForward, const Vector3 &axis); - static Matrix4x4 CreateFromEulerAngles(float x, float y, float z); - static Matrix4x4 CreateLookAt(const Vector3 &cameraPosition, const Vector3 &cameraTarget, const Vector3 &cameraUp); - static Matrix4x4 CreateOrthographic(float left, float right, float bottom, float top, float near_, float far_); - static Matrix4x4 CreatePerspective(float left, float right, float bottom, float top, float near_, float far_); - static Matrix4x4 CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float near_, float far_); - static Matrix4x4 CreateRotation(float angle, const Vector3 &axis); - static Matrix4x4 CreateRotationX(float angle); - static Matrix4x4 CreateRotationY(float angle); - static Matrix4x4 CreateRotationZ(float angle); - static Matrix4x4 CreateScale(float x, float y, float z); - static Matrix4x4 CreateTranslation(float x, float y, float z); - static Matrix4x4 CreateWorld(const Vector3 &position, const Vector3 &forward, const Vector3 &up); - static Matrix4x4 Inverse(const Matrix4x4 &m); - static Matrix4x4 Transpose(const Matrix4x4 &m); - - float m[16]; -}; - -Matrix4x4 operator+(const Matrix4x4 &left, const Matrix4x4 &right); -Matrix4x4 &operator+=(Matrix4x4 &left, const Matrix4x4 &right); -Matrix4x4 operator-(const Matrix4x4 &left, const Matrix4x4 &right); -Matrix4x4 &operator-=(Matrix4x4 &left, const Matrix4x4 &right); -Matrix4x4 operator*(const Matrix4x4 &left, const Matrix4x4 &right); -Matrix4x4 &operator*=(Matrix4x4 &left, const Matrix4x4 &right); -Matrix4x4 operator*(const Matrix4x4 &left, float right); -Matrix4x4 &operator*=(Matrix4x4 &left, float right); -Vector3 operator*(const Vector3 &left, const Matrix4x4 &right); - -#define IDENTITY_MATRIX Matrix4x4::Identity() - -inline Matrix4x4::Matrix4x4( - float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44 - ) -{ - m[_11] = m11; - m[_12] = m12; - m[_13] = m13; - m[_14] = m14; - m[_21] = m21; - m[_22] = m22; - m[_23] = m23; - m[_24] = m24; - m[_31] = m31; - m[_32] = m32; - m[_33] = m33; - m[_34] = m34; - m[_41] = m41; - m[_42] = m42; - m[_43] = m43; - m[_44] = m44; -} - -inline Matrix4x4::Matrix4x4(const float *mv) -{ - m[_11] = mv[_11]; - m[_12] = mv[_12]; - m[_13] = mv[_13]; - m[_14] = mv[_14]; - m[_21] = mv[_21]; - m[_22] = mv[_22]; - m[_23] = mv[_23]; - m[_24] = mv[_24]; - m[_31] = mv[_31]; - m[_32] = mv[_32]; - m[_33] = mv[_33]; - m[_34] = mv[_34]; - m[_41] = mv[_41]; - m[_42] = mv[_42]; - m[_43] = mv[_43]; - m[_44] = mv[_44]; -} - -inline void Matrix4x4::Set( - float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44 - ) -{ - m[_11] = m11; - m[_12] = m12; - m[_13] = m13; - m[_14] = m14; - m[_21] = m21; - m[_22] = m22; - m[_23] = m23; - m[_24] = m24; - m[_31] = m31; - m[_32] = m32; - m[_33] = m33; - m[_34] = m34; - m[_41] = m41; - m[_42] = m42; - m[_43] = m43; - m[_44] = m44; -} - -/** - * Gets the determinant of the matrix. - * @return the determinant - */ -inline float Matrix4x4::GetDeterminant() const -{ - return - (m[_11] * m[_22] - m[_21] * m[_12]) * - (m[_33] * m[_44] - m[_43] * m[_34]) - - (m[_11] * m[_32] - m[_31] * m[_12]) * - (m[_23] * m[_44] - m[_43] * m[_24]) + - (m[_11] * m[_42] - m[_41] * m[_12]) * - (m[_23] * m[_34] - m[_33] * m[_24]) + - (m[_21] * m[_32] - m[_31] * m[_22]) * - (m[_13] * m[_44] - m[_43] * m[_14]) - - (m[_21] * m[_42] - m[_41] * m[_22]) * - (m[_13] * m[_34] - m[_33] * m[_14]) + - (m[_31] * m[_42] - m[_41] * m[_32]) * - (m[_13] * m[_24] - m[_23] * m[_14]); -} - -/** - * @return Vector3 the forward vector (z-axis) - */ -inline Vector3 Matrix4x4::GetForward() const -{ - return Vector3(m[_13], m[_23], m[_33]); -} - -/** - * @return Vector3 the backward vector (inverse z-axis) - */ -inline Vector3 Matrix4x4::GetBackward() const -{ - return Vector3(-m[_13], -m[_23], -m[_33]); -} - -/** - * @return Vector3 the left vector (x-axis) - */ -inline Vector3 Matrix4x4::GetLeft() const -{ - return Vector3(m[_11], m[_21], m[_31]); -} - -/** - * @return Vector3 the right vector (inverse x-axis) - */ -inline Vector3 Matrix4x4::GetRight() const -{ - return Vector3(-m[_11], -m[_21], -m[_31]); -} - -/** - * @return Vector3 the up vector (y-axis) - */ -inline Vector3 Matrix4x4::GetUp() const -{ - return Vector3(m[_12], m[_22], m[_32]); -} - -/** - * @return Vector3 the down vector (inverse y-axis) - */ -inline Vector3 Matrix4x4::GetDown() const -{ - return Vector3(-m[_12], -m[_22], -m[_32]); -} - -/** - * @return Vector3 the translation vector - */ -inline Vector3 Matrix4x4::GetTranslation() const -{ - return Vector3(m[_14], m[_24], m[_34]); -} - -/** - * @return Matrix4x4 identity matrix - */ -inline Matrix4x4 Matrix4x4::Identity() -{ - Matrix4x4 identity; - - identity.m[_11] = 1.0f; - identity.m[_12] = 0.0f; - identity.m[_13] = 0.0f; - identity.m[_14] = 0.0f; - identity.m[_21] = 0.0f; - identity.m[_22] = 1.0f; - identity.m[_23] = 0.0f; - identity.m[_24] = 0.0f; - identity.m[_31] = 0.0f; - identity.m[_32] = 0.0f; - identity.m[_33] = 1.0f; - identity.m[_34] = 0.0f; - identity.m[_41] = 0.0f; - identity.m[_42] = 0.0f; - identity.m[_43] = 0.0f; - identity.m[_44] = 1.0f; - - return identity; -} - -/** - * Constructs a point billboard (spherical billboard) transformation matrix. - * @param objectPosition the position of the billboard object - * @param cameraPosition the position of the camera viewing the billboard - * @param cameraUp the up vector of the camera - * @param cameraForward the forward vector of the camera - * @return a billboard transformation matrix - */ -inline Matrix4x4 Matrix4x4::CreateBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraUp, const Vector3 &cameraForward) -{ - Vector3 forward = objectPosition - cameraPosition; - float forwardLengthSquared = Vector3::LengthSquared(forward); - if (forwardLengthSquared < 0.0001f) - forward = -cameraForward; - else - forward = forward * (1.0f / (sqrtf(forwardLengthSquared))); - - Vector3 left = Vector3::Normalize(Vector3::Cross(cameraUp, forward)); - Vector3 up = Vector3::Cross(forward, left); - - Matrix4x4 out; - - out.m[_11] = left.x; - out.m[_21] = left.y; - out.m[_31] = left.z; - out.m[_41] = 0.0f; - - out.m[_12] = up.x; - out.m[_22] = up.y; - out.m[_32] = up.z; - out.m[_42] = 0.0f; - - out.m[_13] = forward.x; - out.m[_23] = forward.y; - out.m[_33] = forward.z; - out.m[_43] = 0.0f; - - out.m[_14] = objectPosition.x; - out.m[_24] = objectPosition.y; - out.m[_34] = objectPosition.z; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Creates a transformation matrix for a billboard that is constrained to - * rotate about an arbitrary axis. - * @param objectPosition the position of the billboard object - * @param cameraPosition the position of the camera viewing the billboard - * @param cameraForward the forward vector of the camera - * @param axis the axis that the billboard is to rotate about - * @return a billboard transformation matrix - */ -inline Matrix4x4 Matrix4x4::CreateCylindricalBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraForward, const Vector3 &axis) -{ - Vector3 temp = objectPosition - cameraPosition; - float lengthSquared = Vector3::LengthSquared(temp); - if (lengthSquared < 0.0001f) - temp = -cameraForward; - else - temp = temp * (1.0f / (sqrtf(lengthSquared))); - - Vector3 up = axis; - Vector3 forward; - Vector3 left; - - float dot = Vector3::Dot(axis, temp); - if (fabs(dot) > 0.9982547f) - { - dot = Vector3::Dot(axis, FORWARD); - if (fabs(dot) > 0.9982547f) - forward = RIGHT; - else - forward = FORWARD; - - left = Vector3::Normalize(Vector3::Cross(axis, forward)); - forward = Vector3::Normalize(Vector3::Cross(left, axis)); - } - else - { - left = Vector3::Normalize(Vector3::Cross(axis, temp)); - forward = Vector3::Normalize(Vector3::Cross(left, up)); - } - - Matrix4x4 out; - - out.m[_11] = left.x; - out.m[_21] = left.y; - out.m[_31] = left.z; - out.m[_41] = 0.0f; - - out.m[_12] = up.x; - out.m[_22] = up.y; - out.m[_32] = up.z; - out.m[_42] = 0.0f; - - out.m[_13] = forward.x; - out.m[_23] = forward.y; - out.m[_33] = forward.z; - out.m[_43] = 0.0f; - - out.m[_14] = objectPosition.x; - out.m[_24] = objectPosition.y; - out.m[_34] = objectPosition.z; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a rotation matrix from euler angles (specified in radians). - * @param x the x angle - * @param y the y angle - * @param z the z angle - * @return a rotation matrix representing the provided angles - */ -inline Matrix4x4 Matrix4x4::CreateFromEulerAngles(float x, float y, float z) -{ - Matrix4x4 rotateZ = CreateRotationZ(z); - Matrix4x4 rotateY = CreateRotationY(y); - Matrix4x4 rotateX = CreateRotationX(x); - - // "right-to-left" column-major matrix concatenation - return rotateZ * rotateY * rotateX; -} - -/** - * Constructs a modelview matrix. This constructs the same matrix as a call - * to gluLookAt. - * @param cameraPosition position of the camera (eye) - * @param cameraTarget the direction the camera is pointing (center) - * @param cameraUp the up direction relative to the camera - * @return a modelview matrix - */ -inline Matrix4x4 Matrix4x4::CreateLookAt(const Vector3 &cameraPosition, const Vector3 &cameraTarget, const Vector3 &cameraUp) -{ - Matrix4x4 out; - - // build basic lookat matrix without translation component included - Vector3 forward = Vector3::Normalize(cameraTarget - cameraPosition); - Vector3 left = Vector3::Normalize(Vector3::Cross(forward, cameraUp)); - Vector3 up = Vector3::Cross(left, forward); - - out.m[_11] = left.x; - out.m[_21] = up.x; - out.m[_31] = -forward.x; - out.m[_41] = 0.0f; - - out.m[_12] = left.y; - out.m[_22] = up.y; - out.m[_32] = -forward.y; - out.m[_42] = 0.0f; - - out.m[_13] = left.z; - out.m[_23] = up.z; - out.m[_33] = -forward.z; - out.m[_43] = 0.0f; - - out.m[_14] = 0.0f; - out.m[_24] = 0.0f; - out.m[_34] = 0.0f; - out.m[_44] = 1.0f; - - // multiply the translation into the lookat matrix - // this matrix multiplication is simplified so that we're only multiplying components that can actually affect the result - // out = Matrix4x4::CreateTranslation(-cameraPosition.x, -cameraPosition.y, -cameraPosition.z) * out; - out.m[_14] = out.m[_11] * -cameraPosition.x + out.m[_12] * -cameraPosition.y + out.m[_13] * -cameraPosition.z + out.m[_14]; - out.m[_24] = out.m[_21] * -cameraPosition.x + out.m[_22] * -cameraPosition.y + out.m[_23] * -cameraPosition.z + out.m[_24]; - out.m[_34] = out.m[_31] * -cameraPosition.x + out.m[_32] * -cameraPosition.y + out.m[_33] * -cameraPosition.z + out.m[_34]; - out.m[_44] = out.m[_41] * -cameraPosition.x + out.m[_42] * -cameraPosition.y + out.m[_43] * -cameraPosition.z + out.m[_44]; - - return out; -} - -/** - * Creates an orthogonal projection matrix. This is equivalent to a matrix - * created by using OpenGL's glOrtho() function. - * @param left coordinate of the left vertical clipping plane - * @param right coordinate of the right vertical clipping plane - * @param bottom coordinate of the bottom horizontal clipping plane - * @param top coordinate of the top horizontal clipping plane - * @param near near clipping plane distance (negative value is behind the viewer) - * @param far far clipping plane distance (negative value is behind the viewer) - * @return an orthogonal projection matrix - */ -inline Matrix4x4 Matrix4x4::CreateOrthographic(float left, float right, float bottom, float top, float near_, float far_) -{ - Matrix4x4 out; - - out.m[_11] = 2.0f / (right - left); - out.m[_12] = 0.0f; - out.m[_13] = 0.0f; - out.m[_14] = -((right + left) / (right - left)); - - out.m[_21] = 0.0f; - out.m[_22] = 2.0f / (top - bottom); - out.m[_23] = 0.0f; - out.m[_24] = -((top + bottom) / (top - bottom)); - - out.m[_31] = 0.0f; - out.m[_32] = 0.0f; - out.m[_33] = -2.0f / (far_ - near_); - out.m[_34] = -((far_ + near_) / (far_ - near_)); - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = 0.0f; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a perspective projection matrix. This is equivalent to a - * matrix created by using OpenGL's glFrustum() function. - * @param left coordinate of the left vertical clipping plane - * @param right coordinate of the right vertical clipping plane - * @param bottom coordinate of the bottom horizontal clipping plane - * @param top coordinate of the top horizontal clipping plane - * @param near near clipping plane distance - * @param far far clipping plane distance - * @return a perspective projection matrix - */ -inline Matrix4x4 Matrix4x4::CreatePerspective(float left, float right, float bottom, float top, float near_, float far_) -{ - Matrix4x4 out; - - out.m[_11] = (2.0f * near_) / (right - left); - out.m[_12] = 0.0f; - out.m[_13] = (right + left) / (right - left); - out.m[_14] = 0.0f; - - out.m[_21] = 0.0f; - out.m[_22] = (2.0f * near_) / (top - bottom); - out.m[_23] = (top + bottom) / (top - bottom); - out.m[_24] = 0.0f; - - out.m[_31] = 0.0f; - out.m[_32] = 0.0f; - out.m[_33] = -((far_ + near_)) / (far_ - near_); - out.m[_34] = -((2.0f * far_ * near_)) / (far_ - near_); - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = -1.0f; - out.m[_44] = 0.0f; - - return out; -} - -/** - * Constructs a perspective projection matrix. This is equivalent to a - * matrix created by using OpenGL's gluPerspective() function. - * @param fieldOfView the field of view in the y direction (specified in radians) - * @param aspectRatio the aspect ratio of the viewport - * @param near near clipping plane distance - * @param far far clipping plane distance - * @return a perspective projection matrix - */ -inline Matrix4x4 Matrix4x4::CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float near_, float far_) -{ - Matrix4x4 out; - - float f = 1.0f / tanf(fieldOfView / 2.0f); - - out.m[_11] = f / aspectRatio; - out.m[_12] = 0.0f; - out.m[_13] = 0.0f; - out.m[_14] = 0.0f; - - out.m[_21] = 0.0f; - out.m[_22] = f; - out.m[_23] = 0.0f; - out.m[_24] = 0.0f; - - out.m[_31] = 0.0f; - out.m[_32] = 0.0f; - out.m[_33] = (far_ + near_) / (near_ - far_); - out.m[_34] = (2.0f * far_ * near_) / (near_ - far_); - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = -1.0f; - out.m[_44] = 0.0f; - - return out; -} - -/** - * Sets up a rotation matrix about the specified axis. This returns a matrix - * equivalent to the matrix that OpenGL multiples into the modelview matrix - * whenever glRotate(angle, axis.x, axis.y, axis.z) is called. - * @param angle angle in radians to rotate - * @param axis unit vector denoting the axis for the rotation - * @return a rotation matrix representing the specific axis rotation - */ -inline Matrix4x4 Matrix4x4::CreateRotation(float angle, const Vector3 &axis) -{ - Matrix4x4 out; - - float s = sinf(angle); - float c = cosf(angle); - - out.m[_11] = (axis.x * axis.x) * (1.0f - c) + c; - out.m[_12] = (axis.x * axis.y) * (1.0f - c) - (axis.z * s); - out.m[_13] = (axis.x * axis.z) * (1.0f - c) + (axis.y * s); - out.m[_14] = 0.0f; - - out.m[_21] = (axis.y * axis.x) * (1.0f - c) + (axis.z * s); - out.m[_22] = (axis.y * axis.y) * (1.0f - c) + c; - out.m[_23] = (axis.y * axis.z) * (1.0f - c) - (axis.x * s); - out.m[_24] = 0.0f; - - out.m[_31] = (axis.z * axis.x) * (1.0f - c) - (axis.y * s); - out.m[_32] = (axis.z * axis.y) * (1.0f - c) + (axis.x * s); - out.m[_33] = (axis.z * axis.z) * (1.0f - c) + c; - out.m[_34] = 0.0f; - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = 0.0f; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a rotation matrix for a rotation around the x axis. This returns - * a matrix equivalent to the matrix that OpenGL multiples into the modelview - * matrix whenever glRotate(angle, 1.0f, 0.0f, 0.0f) is called. - * @param angle angle to rotate the x axis around (in radians) - * @return the rotation matrix - */ -inline Matrix4x4 Matrix4x4::CreateRotationX(float angle) -{ - Matrix4x4 out; - - float s = sinf(angle); - float c = cosf(angle); - - out.m[_11] = 1.0f; - out.m[_12] = 0.0f; - out.m[_13] = 0.0f; - out.m[_14] = 0.0f; - - out.m[_21] = 0.0f; - out.m[_22] = c; - out.m[_23] = -s; - out.m[_24] = 0.0f; - - out.m[_31] = 0.0f; - out.m[_32] = s; - out.m[_33] = c; - out.m[_34] = 0.0f; - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = 0.0f; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a rotation matrix for a rotation around the y axis. This returns - * a matrix equivalent to the matrix that OpenGL multiples into the modelview - * matrix whenever glRotate(angle, 0.0f, 1.0f, 0.0f) is called. - * @param angle angle to rotate the y axis around (in radians) - * @return the rotation matrix - */ -inline Matrix4x4 Matrix4x4::CreateRotationY(float angle) -{ - Matrix4x4 out; - - float s = sinf(angle); - float c = cosf(angle); - - out.m[_11] = c; - out.m[_12] = 0.0f; - out.m[_13] = s; - out.m[_14] = 0.0f; - - out.m[_21] = 0.0f; - out.m[_22] = 1.0f; - out.m[_23] = 0.0f; - out.m[_24] = 0.0f; - - out.m[_31] = -s; - out.m[_32] = 0.0f; - out.m[_33] = c; - out.m[_34] = 0.0f; - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = 0.0f; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a rotation matrix for a rotation around the z axis. This returns - * a matrix equivalent to the matrix that OpenGL multiples into the modelview - * matrix whenever glRotate(angle, 0.0f, 0.0f, 1.0f) is called. - * @param angle angle to rotate the z axis around (in radians) - * @return the rotation matrix - */ -inline Matrix4x4 Matrix4x4::CreateRotationZ(float angle) -{ - Matrix4x4 out; - - float s = sinf(angle); - float c = cosf(angle); - - out.m[_11] = c; - out.m[_12] = -s; - out.m[_13] = 0.0f; - out.m[_14] = 0.0f; - - out.m[_21] = s; - out.m[_22] = c; - out.m[_23] = 0.0f; - out.m[_24] = 0.0f; - - out.m[_31] = 0.0f; - out.m[_32] = 0.0f; - out.m[_33] = 1.0f; - out.m[_34] = 0.0f; - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = 0.0f; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a scaling matrix from scaling factors for each axis. This returns - * a matrix equivalent to the matrix that OpenGL multiples into the modelview - * matrix whenever glScale(x, y, z) is called. - * @param x the scale factor for the x axis - * @param y the scale factor for the y axis - * @param z the scale factor for the z axis - * @return a scaling matrix - */ -inline Matrix4x4 Matrix4x4::CreateScale(float x, float y, float z) -{ - Matrix4x4 out; - - out.m[_11] = x; - out.m[_12] = 0.0f; - out.m[_13] = 0.0f; - out.m[_14] = 0.0f; - - out.m[_21] = 0.0f; - out.m[_22] = y; - out.m[_23] = 0.0f; - out.m[_24] = 0.0f; - - out.m[_31] = 0.0f; - out.m[_32] = 0.0f; - out.m[_33] = z; - out.m[_34] = 0.0f; - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = 0.0f; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a translation matrix. This returns a matrix equivalent to the - * matrix that OpenGL multiples into the modelview matrix whenever - * glTranslate(x, y, z) is called. - * @param x the amount to translate on the x axis - * @param y the amount to translate on the y axis - * @param z the amount to translate on the z axis - * @return a translation matrix - */ -inline Matrix4x4 Matrix4x4::CreateTranslation(float x, float y, float z) -{ - Matrix4x4 out; - - out.m[_11] = 1.0f; - out.m[_12] = 0.0f; - out.m[_13] = 0.0f; - out.m[_14] = x; - - out.m[_21] = 0.0f; - out.m[_22] = 1.0f; - out.m[_23] = 0.0f; - out.m[_24] = y; - - out.m[_31] = 0.0f; - out.m[_32] = 0.0f; - out.m[_33] = 1.0f; - out.m[_34] = z; - - out.m[_41] = 0.0f; - out.m[_42] = 0.0f; - out.m[_43] = 0.0f; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Constructs a world matrix. - * @param position the position of the object (translation) - * @param forward the forward facing direction of the object - * @param up the up direction of the object - * @return a world matrix - */ -inline Matrix4x4 Matrix4x4::CreateWorld(const Vector3 &position, const Vector3 &forward, const Vector3 &up) -{ - Matrix4x4 out; - - Vector3 f = Vector3::Normalize(-forward); - Vector3 l = Vector3::Normalize(Vector3::Cross(up, f)); - Vector3 u = Vector3::Cross(f, l); - - out.m[_11] = l.x; - out.m[_21] = l.y; - out.m[_31] = l.z; - out.m[_41] = 0.0f; - - out.m[_12] = u.x; - out.m[_22] = u.y; - out.m[_32] = u.z; - out.m[_42] = 0.0f; - - out.m[_13] = f.x; - out.m[_23] = f.y; - out.m[_33] = f.z; - out.m[_43] = 0.0f; - - out.m[_14] = position.x; - out.m[_24] = position.y; - out.m[_34] = position.z; - out.m[_44] = 1.0f; - - return out; -} - -/** - * Calculates the inverse of the specified matrix. - * @param m the matrix to calculate the inverse of - * @return the inverse of the specified matrix - */ -inline Matrix4x4 Matrix4x4::Inverse(const Matrix4x4 &m) -{ - float d = m.GetDeterminant(); - if (IS_CLOSE_ENOUGH(d, 0.0f)) - return IDENTITY_MATRIX; - else - { - Matrix4x4 out; - - d = 1.0f / d; - - out.m[_11] = d * (m.m[_22] * (m.m[_33] * m.m[_44] - m.m[_43] * m.m[_34]) + m.m[_32] * (m.m[_43] * m.m[_24] - m.m[_23] * m.m[_44]) + m.m[_42] * (m.m[_23] * m.m[_34] - m.m[_33] * m.m[_24])); - out.m[_21] = d * (m.m[_23] * (m.m[_31] * m.m[_44] - m.m[_41] * m.m[_34]) + m.m[_33] * (m.m[_41] * m.m[_24] - m.m[_21] * m.m[_44]) + m.m[_43] * (m.m[_21] * m.m[_34] - m.m[_31] * m.m[_24])); - out.m[_31] = d * (m.m[_24] * (m.m[_31] * m.m[_42] - m.m[_41] * m.m[_32]) + m.m[_34] * (m.m[_41] * m.m[_22] - m.m[_21] * m.m[_42]) + m.m[_44] * (m.m[_21] * m.m[_32] - m.m[_31] * m.m[_22])); - out.m[_41] = d * (m.m[_21] * (m.m[_42] * m.m[_33] - m.m[_32] * m.m[_43]) + m.m[_31] * (m.m[_22] * m.m[_43] - m.m[_42] * m.m[_23]) + m.m[_41] * (m.m[_32] * m.m[_23] - m.m[_22] * m.m[_33])); - - out.m[_12] = d * (m.m[_32] * (m.m[_13] * m.m[_44] - m.m[_43] * m.m[_14]) + m.m[_42] * (m.m[_33] * m.m[_14] - m.m[_13] * m.m[_34]) + m.m[_12] * (m.m[_43] * m.m[_34] - m.m[_33] * m.m[_44])); - out.m[_22] = d * (m.m[_33] * (m.m[_11] * m.m[_44] - m.m[_41] * m.m[_14]) + m.m[_43] * (m.m[_31] * m.m[_14] - m.m[_11] * m.m[_34]) + m.m[_13] * (m.m[_41] * m.m[_34] - m.m[_31] * m.m[_44])); - out.m[_32] = d * (m.m[_34] * (m.m[_11] * m.m[_42] - m.m[_41] * m.m[_12]) + m.m[_44] * (m.m[_31] * m.m[_12] - m.m[_11] * m.m[_32]) + m.m[_14] * (m.m[_41] * m.m[_32] - m.m[_31] * m.m[_42])); - out.m[_42] = d * (m.m[_31] * (m.m[_42] * m.m[_13] - m.m[_12] * m.m[_43]) + m.m[_41] * (m.m[_12] * m.m[_33] - m.m[_32] * m.m[_13]) + m.m[_11] * (m.m[_32] * m.m[_43] - m.m[_42] * m.m[_33])); - - out.m[_13] = d * (m.m[_42] * (m.m[_13] * m.m[_24] - m.m[_23] * m.m[_14]) + m.m[_12] * (m.m[_23] * m.m[_44] - m.m[_43] * m.m[_24]) + m.m[_22] * (m.m[_43] * m.m[_14] - m.m[_13] * m.m[_44])); - out.m[_23] = d * (m.m[_43] * (m.m[_11] * m.m[_24] - m.m[_21] * m.m[_14]) + m.m[_13] * (m.m[_21] * m.m[_44] - m.m[_41] * m.m[_24]) + m.m[_23] * (m.m[_41] * m.m[_14] - m.m[_11] * m.m[_44])); - out.m[_33] = d * (m.m[_44] * (m.m[_11] * m.m[_22] - m.m[_21] * m.m[_12]) + m.m[_14] * (m.m[_21] * m.m[_42] - m.m[_41] * m.m[_22]) + m.m[_24] * (m.m[_41] * m.m[_12] - m.m[_11] * m.m[_42])); - out.m[_43] = d * (m.m[_41] * (m.m[_22] * m.m[_13] - m.m[_12] * m.m[_23]) + m.m[_11] * (m.m[_42] * m.m[_23] - m.m[_22] * m.m[_43]) + m.m[_21] * (m.m[_12] * m.m[_43] - m.m[_42] * m.m[_13])); - - out.m[_14] = d * (m.m[_12] * (m.m[_33] * m.m[_24] - m.m[_23] * m.m[_34]) + m.m[_22] * (m.m[_13] * m.m[_34] - m.m[_33] * m.m[_14]) + m.m[_32] * (m.m[_23] * m.m[_14] - m.m[_13] * m.m[_24])); - out.m[_24] = d * (m.m[_13] * (m.m[_31] * m.m[_24] - m.m[_21] * m.m[_34]) + m.m[_23] * (m.m[_11] * m.m[_34] - m.m[_31] * m.m[_14]) + m.m[_33] * (m.m[_21] * m.m[_14] - m.m[_11] * m.m[_24])); - out.m[_34] = d * (m.m[_14] * (m.m[_31] * m.m[_22] - m.m[_21] * m.m[_32]) + m.m[_24] * (m.m[_11] * m.m[_32] - m.m[_31] * m.m[_12]) + m.m[_34] * (m.m[_21] * m.m[_12] - m.m[_11] * m.m[_22])); - out.m[_44] = d * (m.m[_11] * (m.m[_22] * m.m[_33] - m.m[_32] * m.m[_23]) + m.m[_21] * (m.m[_32] * m.m[_13] - m.m[_12] * m.m[_33]) + m.m[_31] * (m.m[_12] * m.m[_23] - m.m[_22] * m.m[_13])); - - return out; - } -} - -/** - * Calculates the transpose of a given matrix. - * @param m the matrix to get the transpose of - * @return the transpose matrix - */ -inline Matrix4x4 Matrix4x4::Transpose(const Matrix4x4 &m) -{ - Matrix4x4 out; - - out.m[_11] = m.m[_11]; - out.m[_12] = m.m[_21]; - out.m[_13] = m.m[_31]; - out.m[_14] = m.m[_41]; - - out.m[_21] = m.m[_12]; - out.m[_22] = m.m[_22]; - out.m[_23] = m.m[_32]; - out.m[_24] = m.m[_42]; - - out.m[_31] = m.m[_13]; - out.m[_32] = m.m[_23]; - out.m[_33] = m.m[_33]; - out.m[_34] = m.m[_43]; - - out.m[_41] = m.m[_14]; - out.m[_42] = m.m[_24]; - out.m[_43] = m.m[_34]; - out.m[_44] = m.m[_44]; - - return out; -} - -inline Matrix4x4 operator+(const Matrix4x4 &left, const Matrix4x4 &right) -{ - Matrix4x4 result; - - result.m[_11] = left.m[_11] + right.m[_11]; - result.m[_12] = left.m[_12] + right.m[_12]; - result.m[_13] = left.m[_13] + right.m[_13]; - result.m[_14] = left.m[_14] + right.m[_14]; - result.m[_21] = left.m[_21] + right.m[_21]; - result.m[_22] = left.m[_22] + right.m[_22]; - result.m[_23] = left.m[_23] + right.m[_23]; - result.m[_24] = left.m[_24] + right.m[_24]; - result.m[_31] = left.m[_31] + right.m[_31]; - result.m[_32] = left.m[_32] + right.m[_32]; - result.m[_33] = left.m[_33] + right.m[_33]; - result.m[_34] = left.m[_34] + right.m[_34]; - result.m[_41] = left.m[_41] + right.m[_41]; - result.m[_42] = left.m[_42] + right.m[_42]; - result.m[_43] = left.m[_43] + right.m[_43]; - result.m[_44] = left.m[_44] + right.m[_44]; - - return result; -} - -inline Matrix4x4 &operator+=(Matrix4x4 &left, const Matrix4x4 &right) -{ - left = left + right; - return left; -} - -inline Matrix4x4 operator-(const Matrix4x4 &left, const Matrix4x4 &right) -{ - Matrix4x4 result; - - result.m[_11] = left.m[_11] - right.m[_11]; - result.m[_12] = left.m[_12] - right.m[_12]; - result.m[_13] = left.m[_13] - right.m[_13]; - result.m[_14] = left.m[_14] - right.m[_14]; - result.m[_21] = left.m[_21] - right.m[_21]; - result.m[_22] = left.m[_22] - right.m[_22]; - result.m[_23] = left.m[_23] - right.m[_23]; - result.m[_24] = left.m[_24] - right.m[_24]; - result.m[_31] = left.m[_31] - right.m[_31]; - result.m[_32] = left.m[_32] - right.m[_32]; - result.m[_33] = left.m[_33] - right.m[_33]; - result.m[_34] = left.m[_34] - right.m[_34]; - result.m[_41] = left.m[_41] - right.m[_41]; - result.m[_42] = left.m[_42] - right.m[_42]; - result.m[_43] = left.m[_43] - right.m[_43]; - result.m[_44] = left.m[_44] - right.m[_44]; - - return result; -} - -inline Matrix4x4 &operator-=(Matrix4x4 &left, const Matrix4x4 &right) -{ - left = left - right; - return left; -} - -inline Matrix4x4 operator*(const Matrix4x4 &left, const Matrix4x4 &right) -{ - Matrix4x4 result; - - result.m[_11] = left.m[_11] * right.m[_11] + left.m[_12] * right.m[_21] + left.m[_13] * right.m[_31] + left.m[_14] * right.m[_41]; - result.m[_12] = left.m[_11] * right.m[_12] + left.m[_12] * right.m[_22] + left.m[_13] * right.m[_32] + left.m[_14] * right.m[_42]; - result.m[_13] = left.m[_11] * right.m[_13] + left.m[_12] * right.m[_23] + left.m[_13] * right.m[_33] + left.m[_14] * right.m[_43]; - result.m[_14] = left.m[_11] * right.m[_14] + left.m[_12] * right.m[_24] + left.m[_13] * right.m[_34] + left.m[_14] * right.m[_44]; - - result.m[_21] = left.m[_21] * right.m[_11] + left.m[_22] * right.m[_21] + left.m[_23] * right.m[_31] + left.m[_24] * right.m[_41]; - result.m[_22] = left.m[_21] * right.m[_12] + left.m[_22] * right.m[_22] + left.m[_23] * right.m[_32] + left.m[_24] * right.m[_42]; - result.m[_23] = left.m[_21] * right.m[_13] + left.m[_22] * right.m[_23] + left.m[_23] * right.m[_33] + left.m[_24] * right.m[_43]; - result.m[_24] = left.m[_21] * right.m[_14] + left.m[_22] * right.m[_24] + left.m[_23] * right.m[_34] + left.m[_24] * right.m[_44]; - - result.m[_31] = left.m[_31] * right.m[_11] + left.m[_32] * right.m[_21] + left.m[_33] * right.m[_31] + left.m[_34] * right.m[_41]; - result.m[_32] = left.m[_31] * right.m[_12] + left.m[_32] * right.m[_22] + left.m[_33] * right.m[_32] + left.m[_34] * right.m[_42]; - result.m[_33] = left.m[_31] * right.m[_13] + left.m[_32] * right.m[_23] + left.m[_33] * right.m[_33] + left.m[_34] * right.m[_43]; - result.m[_34] = left.m[_31] * right.m[_14] + left.m[_32] * right.m[_24] + left.m[_33] * right.m[_34] + left.m[_34] * right.m[_44]; - - result.m[_41] = left.m[_41] * right.m[_11] + left.m[_42] * right.m[_21] + left.m[_43] * right.m[_31] + left.m[_44] * right.m[_41]; - result.m[_42] = left.m[_41] * right.m[_12] + left.m[_42] * right.m[_22] + left.m[_43] * right.m[_32] + left.m[_44] * right.m[_42]; - result.m[_43] = left.m[_41] * right.m[_13] + left.m[_42] * right.m[_23] + left.m[_43] * right.m[_33] + left.m[_44] * right.m[_43]; - result.m[_44] = left.m[_41] * right.m[_14] + left.m[_42] * right.m[_24] + left.m[_43] * right.m[_34] + left.m[_44] * right.m[_44]; - - return result; -} - -inline Matrix4x4 &operator*=(Matrix4x4 &left, const Matrix4x4 &right) -{ - left = left * right; - return left; -} - -inline Matrix4x4 operator*(const Matrix4x4 &left, float right) -{ - Matrix4x4 result; - - result.m[_11] = left.m[_11] * right; - result.m[_12] = left.m[_12] * right; - result.m[_13] = left.m[_13] * right; - result.m[_14] = left.m[_14] * right; - result.m[_21] = left.m[_21] * right; - result.m[_22] = left.m[_22] * right; - result.m[_23] = left.m[_23] * right; - result.m[_24] = left.m[_24] * right; - result.m[_31] = left.m[_31] * right; - result.m[_32] = left.m[_32] * right; - result.m[_33] = left.m[_33] * right; - result.m[_34] = left.m[_34] * right; - result.m[_41] = left.m[_41] * right; - result.m[_42] = left.m[_42] * right; - result.m[_43] = left.m[_43] * right; - result.m[_44] = left.m[_44] * right; - - return result; -} - -inline Matrix4x4 &operator*=(Matrix4x4 &left, float right) -{ - left = left * right; - return left; -} - -inline Vector3 operator*(const Vector3 &left, const Matrix4x4 &right) -{ - return Vector3( - left.x * right.m[_11] + left.y * right.m[_12] + left.z * right.m[_13] + right.m[_14], - left.x * right.m[_21] + left.y * right.m[_22] + left.z * right.m[_23] + right.m[_24], - left.x * right.m[_31] + left.y * right.m[_32] + left.z * right.m[_33] + right.m[_34] - ); -} - -#endif +#ifndef __GEOMETRY_MATRIX4X4_H_INCLUDED__ +#define __GEOMETRY_MATRIX4X4_H_INCLUDED__ + +#include +#include "common.h" +#include "vector3.h" + +typedef enum +{ + _11 = 0, + _12 = 4, + _13 = 8, + _14 = 12, + _21 = 1, + _22 = 5, + _23 = 9, + _24 = 13, + _31 = 2, + _32 = 6, + _33 = 10, + _34 = 14, + _41 = 3, + _42 = 7, + _43 = 11, + _44 = 15 +} MATRIX_ELEMENTS; + +/** + * Represents a 4x4 column-major Matrix and provides common methods for + * matrix math. + *

Referenced/based on code from:

+ *
    + *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • + *
  • http://www.dhpoware.com/source/mathlib.html
  • + *
  • http://www.songho.ca/opengl/gl_transform.html
  • + *
  • http://www.opengl.org/sdk/docs/man/
  • + *
+ * @author Gered + */ +class Matrix4x4 +{ +public: + Matrix4x4() {} + + Matrix4x4( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44 + ); + + Matrix4x4(const float *mv); + + ~Matrix4x4() {} + + void Set( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44 + ); + float GetDeterminant() const; + Vector3 GetForward() const; + Vector3 GetBackward() const; + Vector3 GetLeft() const; + Vector3 GetRight() const; + Vector3 GetUp() const; + Vector3 GetDown() const; + Vector3 GetTranslation() const; + + static Matrix4x4 Identity(); + static Matrix4x4 CreateBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraUp, const Vector3 &cameraForward); + static Matrix4x4 CreateCylindricalBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraForward, const Vector3 &axis); + static Matrix4x4 CreateFromEulerAngles(float x, float y, float z); + static Matrix4x4 CreateLookAt(const Vector3 &cameraPosition, const Vector3 &cameraTarget, const Vector3 &cameraUp); + static Matrix4x4 CreateOrthographic(float left, float right, float bottom, float top, float near_, float far_); + static Matrix4x4 CreatePerspective(float left, float right, float bottom, float top, float near_, float far_); + static Matrix4x4 CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float near_, float far_); + static Matrix4x4 CreateRotation(float angle, const Vector3 &axis); + static Matrix4x4 CreateRotationX(float angle); + static Matrix4x4 CreateRotationY(float angle); + static Matrix4x4 CreateRotationZ(float angle); + static Matrix4x4 CreateScale(float x, float y, float z); + static Matrix4x4 CreateTranslation(float x, float y, float z); + static Matrix4x4 CreateWorld(const Vector3 &position, const Vector3 &forward, const Vector3 &up); + static Matrix4x4 Inverse(const Matrix4x4 &m); + static Matrix4x4 Transpose(const Matrix4x4 &m); + + float m[16]; +}; + +Matrix4x4 operator+(const Matrix4x4 &left, const Matrix4x4 &right); +Matrix4x4 &operator+=(Matrix4x4 &left, const Matrix4x4 &right); +Matrix4x4 operator-(const Matrix4x4 &left, const Matrix4x4 &right); +Matrix4x4 &operator-=(Matrix4x4 &left, const Matrix4x4 &right); +Matrix4x4 operator*(const Matrix4x4 &left, const Matrix4x4 &right); +Matrix4x4 &operator*=(Matrix4x4 &left, const Matrix4x4 &right); +Matrix4x4 operator*(const Matrix4x4 &left, float right); +Matrix4x4 &operator*=(Matrix4x4 &left, float right); +Vector3 operator*(const Vector3 &left, const Matrix4x4 &right); + +#define IDENTITY_MATRIX Matrix4x4::Identity() + +inline Matrix4x4::Matrix4x4( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44 + ) +{ + m[_11] = m11; + m[_12] = m12; + m[_13] = m13; + m[_14] = m14; + m[_21] = m21; + m[_22] = m22; + m[_23] = m23; + m[_24] = m24; + m[_31] = m31; + m[_32] = m32; + m[_33] = m33; + m[_34] = m34; + m[_41] = m41; + m[_42] = m42; + m[_43] = m43; + m[_44] = m44; +} + +inline Matrix4x4::Matrix4x4(const float *mv) +{ + m[_11] = mv[_11]; + m[_12] = mv[_12]; + m[_13] = mv[_13]; + m[_14] = mv[_14]; + m[_21] = mv[_21]; + m[_22] = mv[_22]; + m[_23] = mv[_23]; + m[_24] = mv[_24]; + m[_31] = mv[_31]; + m[_32] = mv[_32]; + m[_33] = mv[_33]; + m[_34] = mv[_34]; + m[_41] = mv[_41]; + m[_42] = mv[_42]; + m[_43] = mv[_43]; + m[_44] = mv[_44]; +} + +inline void Matrix4x4::Set( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44 + ) +{ + m[_11] = m11; + m[_12] = m12; + m[_13] = m13; + m[_14] = m14; + m[_21] = m21; + m[_22] = m22; + m[_23] = m23; + m[_24] = m24; + m[_31] = m31; + m[_32] = m32; + m[_33] = m33; + m[_34] = m34; + m[_41] = m41; + m[_42] = m42; + m[_43] = m43; + m[_44] = m44; +} + +/** + * Gets the determinant of the matrix. + * @return the determinant + */ +inline float Matrix4x4::GetDeterminant() const +{ + return + (m[_11] * m[_22] - m[_21] * m[_12]) * + (m[_33] * m[_44] - m[_43] * m[_34]) - + (m[_11] * m[_32] - m[_31] * m[_12]) * + (m[_23] * m[_44] - m[_43] * m[_24]) + + (m[_11] * m[_42] - m[_41] * m[_12]) * + (m[_23] * m[_34] - m[_33] * m[_24]) + + (m[_21] * m[_32] - m[_31] * m[_22]) * + (m[_13] * m[_44] - m[_43] * m[_14]) - + (m[_21] * m[_42] - m[_41] * m[_22]) * + (m[_13] * m[_34] - m[_33] * m[_14]) + + (m[_31] * m[_42] - m[_41] * m[_32]) * + (m[_13] * m[_24] - m[_23] * m[_14]); +} + +/** + * @return Vector3 the forward vector (z-axis) + */ +inline Vector3 Matrix4x4::GetForward() const +{ + return Vector3(m[_13], m[_23], m[_33]); +} + +/** + * @return Vector3 the backward vector (inverse z-axis) + */ +inline Vector3 Matrix4x4::GetBackward() const +{ + return Vector3(-m[_13], -m[_23], -m[_33]); +} + +/** + * @return Vector3 the left vector (x-axis) + */ +inline Vector3 Matrix4x4::GetLeft() const +{ + return Vector3(m[_11], m[_21], m[_31]); +} + +/** + * @return Vector3 the right vector (inverse x-axis) + */ +inline Vector3 Matrix4x4::GetRight() const +{ + return Vector3(-m[_11], -m[_21], -m[_31]); +} + +/** + * @return Vector3 the up vector (y-axis) + */ +inline Vector3 Matrix4x4::GetUp() const +{ + return Vector3(m[_12], m[_22], m[_32]); +} + +/** + * @return Vector3 the down vector (inverse y-axis) + */ +inline Vector3 Matrix4x4::GetDown() const +{ + return Vector3(-m[_12], -m[_22], -m[_32]); +} + +/** + * @return Vector3 the translation vector + */ +inline Vector3 Matrix4x4::GetTranslation() const +{ + return Vector3(m[_14], m[_24], m[_34]); +} + +/** + * @return Matrix4x4 identity matrix + */ +inline Matrix4x4 Matrix4x4::Identity() +{ + Matrix4x4 identity; + + identity.m[_11] = 1.0f; + identity.m[_12] = 0.0f; + identity.m[_13] = 0.0f; + identity.m[_14] = 0.0f; + identity.m[_21] = 0.0f; + identity.m[_22] = 1.0f; + identity.m[_23] = 0.0f; + identity.m[_24] = 0.0f; + identity.m[_31] = 0.0f; + identity.m[_32] = 0.0f; + identity.m[_33] = 1.0f; + identity.m[_34] = 0.0f; + identity.m[_41] = 0.0f; + identity.m[_42] = 0.0f; + identity.m[_43] = 0.0f; + identity.m[_44] = 1.0f; + + return identity; +} + +/** + * Constructs a point billboard (spherical billboard) transformation matrix. + * @param objectPosition the position of the billboard object + * @param cameraPosition the position of the camera viewing the billboard + * @param cameraUp the up vector of the camera + * @param cameraForward the forward vector of the camera + * @return a billboard transformation matrix + */ +inline Matrix4x4 Matrix4x4::CreateBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraUp, const Vector3 &cameraForward) +{ + Vector3 forward = objectPosition - cameraPosition; + float forwardLengthSquared = Vector3::LengthSquared(forward); + if (forwardLengthSquared < 0.0001f) + forward = -cameraForward; + else + forward = forward * (1.0f / (sqrtf(forwardLengthSquared))); + + Vector3 left = Vector3::Normalize(Vector3::Cross(cameraUp, forward)); + Vector3 up = Vector3::Cross(forward, left); + + Matrix4x4 out; + + out.m[_11] = left.x; + out.m[_21] = left.y; + out.m[_31] = left.z; + out.m[_41] = 0.0f; + + out.m[_12] = up.x; + out.m[_22] = up.y; + out.m[_32] = up.z; + out.m[_42] = 0.0f; + + out.m[_13] = forward.x; + out.m[_23] = forward.y; + out.m[_33] = forward.z; + out.m[_43] = 0.0f; + + out.m[_14] = objectPosition.x; + out.m[_24] = objectPosition.y; + out.m[_34] = objectPosition.z; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Creates a transformation matrix for a billboard that is constrained to + * rotate about an arbitrary axis. + * @param objectPosition the position of the billboard object + * @param cameraPosition the position of the camera viewing the billboard + * @param cameraForward the forward vector of the camera + * @param axis the axis that the billboard is to rotate about + * @return a billboard transformation matrix + */ +inline Matrix4x4 Matrix4x4::CreateCylindricalBillboard(const Vector3 &objectPosition, const Vector3 &cameraPosition, const Vector3 &cameraForward, const Vector3 &axis) +{ + Vector3 temp = objectPosition - cameraPosition; + float lengthSquared = Vector3::LengthSquared(temp); + if (lengthSquared < 0.0001f) + temp = -cameraForward; + else + temp = temp * (1.0f / (sqrtf(lengthSquared))); + + Vector3 up = axis; + Vector3 forward; + Vector3 left; + + float dot = Vector3::Dot(axis, temp); + if (fabs(dot) > 0.9982547f) + { + dot = Vector3::Dot(axis, FORWARD); + if (fabs(dot) > 0.9982547f) + forward = RIGHT; + else + forward = FORWARD; + + left = Vector3::Normalize(Vector3::Cross(axis, forward)); + forward = Vector3::Normalize(Vector3::Cross(left, axis)); + } + else + { + left = Vector3::Normalize(Vector3::Cross(axis, temp)); + forward = Vector3::Normalize(Vector3::Cross(left, up)); + } + + Matrix4x4 out; + + out.m[_11] = left.x; + out.m[_21] = left.y; + out.m[_31] = left.z; + out.m[_41] = 0.0f; + + out.m[_12] = up.x; + out.m[_22] = up.y; + out.m[_32] = up.z; + out.m[_42] = 0.0f; + + out.m[_13] = forward.x; + out.m[_23] = forward.y; + out.m[_33] = forward.z; + out.m[_43] = 0.0f; + + out.m[_14] = objectPosition.x; + out.m[_24] = objectPosition.y; + out.m[_34] = objectPosition.z; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a rotation matrix from euler angles (specified in radians). + * @param x the x angle + * @param y the y angle + * @param z the z angle + * @return a rotation matrix representing the provided angles + */ +inline Matrix4x4 Matrix4x4::CreateFromEulerAngles(float x, float y, float z) +{ + Matrix4x4 rotateZ = CreateRotationZ(z); + Matrix4x4 rotateY = CreateRotationY(y); + Matrix4x4 rotateX = CreateRotationX(x); + + // "right-to-left" column-major matrix concatenation + return rotateZ * rotateY * rotateX; +} + +/** + * Constructs a modelview matrix. This constructs the same matrix as a call + * to gluLookAt. + * @param cameraPosition position of the camera (eye) + * @param cameraTarget the direction the camera is pointing (center) + * @param cameraUp the up direction relative to the camera + * @return a modelview matrix + */ +inline Matrix4x4 Matrix4x4::CreateLookAt(const Vector3 &cameraPosition, const Vector3 &cameraTarget, const Vector3 &cameraUp) +{ + Matrix4x4 out; + + // build basic lookat matrix without translation component included + Vector3 forward = Vector3::Normalize(cameraTarget - cameraPosition); + Vector3 left = Vector3::Normalize(Vector3::Cross(forward, cameraUp)); + Vector3 up = Vector3::Cross(left, forward); + + out.m[_11] = left.x; + out.m[_21] = up.x; + out.m[_31] = -forward.x; + out.m[_41] = 0.0f; + + out.m[_12] = left.y; + out.m[_22] = up.y; + out.m[_32] = -forward.y; + out.m[_42] = 0.0f; + + out.m[_13] = left.z; + out.m[_23] = up.z; + out.m[_33] = -forward.z; + out.m[_43] = 0.0f; + + out.m[_14] = 0.0f; + out.m[_24] = 0.0f; + out.m[_34] = 0.0f; + out.m[_44] = 1.0f; + + // multiply the translation into the lookat matrix + // this matrix multiplication is simplified so that we're only multiplying components that can actually affect the result + // out = Matrix4x4::CreateTranslation(-cameraPosition.x, -cameraPosition.y, -cameraPosition.z) * out; + out.m[_14] = out.m[_11] * -cameraPosition.x + out.m[_12] * -cameraPosition.y + out.m[_13] * -cameraPosition.z + out.m[_14]; + out.m[_24] = out.m[_21] * -cameraPosition.x + out.m[_22] * -cameraPosition.y + out.m[_23] * -cameraPosition.z + out.m[_24]; + out.m[_34] = out.m[_31] * -cameraPosition.x + out.m[_32] * -cameraPosition.y + out.m[_33] * -cameraPosition.z + out.m[_34]; + out.m[_44] = out.m[_41] * -cameraPosition.x + out.m[_42] * -cameraPosition.y + out.m[_43] * -cameraPosition.z + out.m[_44]; + + return out; +} + +/** + * Creates an orthogonal projection matrix. This is equivalent to a matrix + * created by using OpenGL's glOrtho() function. + * @param left coordinate of the left vertical clipping plane + * @param right coordinate of the right vertical clipping plane + * @param bottom coordinate of the bottom horizontal clipping plane + * @param top coordinate of the top horizontal clipping plane + * @param near near clipping plane distance (negative value is behind the viewer) + * @param far far clipping plane distance (negative value is behind the viewer) + * @return an orthogonal projection matrix + */ +inline Matrix4x4 Matrix4x4::CreateOrthographic(float left, float right, float bottom, float top, float near_, float far_) +{ + Matrix4x4 out; + + out.m[_11] = 2.0f / (right - left); + out.m[_12] = 0.0f; + out.m[_13] = 0.0f; + out.m[_14] = -((right + left) / (right - left)); + + out.m[_21] = 0.0f; + out.m[_22] = 2.0f / (top - bottom); + out.m[_23] = 0.0f; + out.m[_24] = -((top + bottom) / (top - bottom)); + + out.m[_31] = 0.0f; + out.m[_32] = 0.0f; + out.m[_33] = -2.0f / (far_ - near_); + out.m[_34] = -((far_ + near_) / (far_ - near_)); + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = 0.0f; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a perspective projection matrix. This is equivalent to a + * matrix created by using OpenGL's glFrustum() function. + * @param left coordinate of the left vertical clipping plane + * @param right coordinate of the right vertical clipping plane + * @param bottom coordinate of the bottom horizontal clipping plane + * @param top coordinate of the top horizontal clipping plane + * @param near near clipping plane distance + * @param far far clipping plane distance + * @return a perspective projection matrix + */ +inline Matrix4x4 Matrix4x4::CreatePerspective(float left, float right, float bottom, float top, float near_, float far_) +{ + Matrix4x4 out; + + out.m[_11] = (2.0f * near_) / (right - left); + out.m[_12] = 0.0f; + out.m[_13] = (right + left) / (right - left); + out.m[_14] = 0.0f; + + out.m[_21] = 0.0f; + out.m[_22] = (2.0f * near_) / (top - bottom); + out.m[_23] = (top + bottom) / (top - bottom); + out.m[_24] = 0.0f; + + out.m[_31] = 0.0f; + out.m[_32] = 0.0f; + out.m[_33] = -((far_ + near_)) / (far_ - near_); + out.m[_34] = -((2.0f * far_ * near_)) / (far_ - near_); + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = -1.0f; + out.m[_44] = 0.0f; + + return out; +} + +/** + * Constructs a perspective projection matrix. This is equivalent to a + * matrix created by using OpenGL's gluPerspective() function. + * @param fieldOfView the field of view in the y direction (specified in radians) + * @param aspectRatio the aspect ratio of the viewport + * @param near near clipping plane distance + * @param far far clipping plane distance + * @return a perspective projection matrix + */ +inline Matrix4x4 Matrix4x4::CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float near_, float far_) +{ + Matrix4x4 out; + + float f = 1.0f / tanf(fieldOfView / 2.0f); + + out.m[_11] = f / aspectRatio; + out.m[_12] = 0.0f; + out.m[_13] = 0.0f; + out.m[_14] = 0.0f; + + out.m[_21] = 0.0f; + out.m[_22] = f; + out.m[_23] = 0.0f; + out.m[_24] = 0.0f; + + out.m[_31] = 0.0f; + out.m[_32] = 0.0f; + out.m[_33] = (far_ + near_) / (near_ - far_); + out.m[_34] = (2.0f * far_ * near_) / (near_ - far_); + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = -1.0f; + out.m[_44] = 0.0f; + + return out; +} + +/** + * Sets up a rotation matrix about the specified axis. This returns a matrix + * equivalent to the matrix that OpenGL multiples into the modelview matrix + * whenever glRotate(angle, axis.x, axis.y, axis.z) is called. + * @param angle angle in radians to rotate + * @param axis unit vector denoting the axis for the rotation + * @return a rotation matrix representing the specific axis rotation + */ +inline Matrix4x4 Matrix4x4::CreateRotation(float angle, const Vector3 &axis) +{ + Matrix4x4 out; + + float s = sinf(angle); + float c = cosf(angle); + + out.m[_11] = (axis.x * axis.x) * (1.0f - c) + c; + out.m[_12] = (axis.x * axis.y) * (1.0f - c) - (axis.z * s); + out.m[_13] = (axis.x * axis.z) * (1.0f - c) + (axis.y * s); + out.m[_14] = 0.0f; + + out.m[_21] = (axis.y * axis.x) * (1.0f - c) + (axis.z * s); + out.m[_22] = (axis.y * axis.y) * (1.0f - c) + c; + out.m[_23] = (axis.y * axis.z) * (1.0f - c) - (axis.x * s); + out.m[_24] = 0.0f; + + out.m[_31] = (axis.z * axis.x) * (1.0f - c) - (axis.y * s); + out.m[_32] = (axis.z * axis.y) * (1.0f - c) + (axis.x * s); + out.m[_33] = (axis.z * axis.z) * (1.0f - c) + c; + out.m[_34] = 0.0f; + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = 0.0f; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a rotation matrix for a rotation around the x axis. This returns + * a matrix equivalent to the matrix that OpenGL multiples into the modelview + * matrix whenever glRotate(angle, 1.0f, 0.0f, 0.0f) is called. + * @param angle angle to rotate the x axis around (in radians) + * @return the rotation matrix + */ +inline Matrix4x4 Matrix4x4::CreateRotationX(float angle) +{ + Matrix4x4 out; + + float s = sinf(angle); + float c = cosf(angle); + + out.m[_11] = 1.0f; + out.m[_12] = 0.0f; + out.m[_13] = 0.0f; + out.m[_14] = 0.0f; + + out.m[_21] = 0.0f; + out.m[_22] = c; + out.m[_23] = -s; + out.m[_24] = 0.0f; + + out.m[_31] = 0.0f; + out.m[_32] = s; + out.m[_33] = c; + out.m[_34] = 0.0f; + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = 0.0f; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a rotation matrix for a rotation around the y axis. This returns + * a matrix equivalent to the matrix that OpenGL multiples into the modelview + * matrix whenever glRotate(angle, 0.0f, 1.0f, 0.0f) is called. + * @param angle angle to rotate the y axis around (in radians) + * @return the rotation matrix + */ +inline Matrix4x4 Matrix4x4::CreateRotationY(float angle) +{ + Matrix4x4 out; + + float s = sinf(angle); + float c = cosf(angle); + + out.m[_11] = c; + out.m[_12] = 0.0f; + out.m[_13] = s; + out.m[_14] = 0.0f; + + out.m[_21] = 0.0f; + out.m[_22] = 1.0f; + out.m[_23] = 0.0f; + out.m[_24] = 0.0f; + + out.m[_31] = -s; + out.m[_32] = 0.0f; + out.m[_33] = c; + out.m[_34] = 0.0f; + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = 0.0f; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a rotation matrix for a rotation around the z axis. This returns + * a matrix equivalent to the matrix that OpenGL multiples into the modelview + * matrix whenever glRotate(angle, 0.0f, 0.0f, 1.0f) is called. + * @param angle angle to rotate the z axis around (in radians) + * @return the rotation matrix + */ +inline Matrix4x4 Matrix4x4::CreateRotationZ(float angle) +{ + Matrix4x4 out; + + float s = sinf(angle); + float c = cosf(angle); + + out.m[_11] = c; + out.m[_12] = -s; + out.m[_13] = 0.0f; + out.m[_14] = 0.0f; + + out.m[_21] = s; + out.m[_22] = c; + out.m[_23] = 0.0f; + out.m[_24] = 0.0f; + + out.m[_31] = 0.0f; + out.m[_32] = 0.0f; + out.m[_33] = 1.0f; + out.m[_34] = 0.0f; + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = 0.0f; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a scaling matrix from scaling factors for each axis. This returns + * a matrix equivalent to the matrix that OpenGL multiples into the modelview + * matrix whenever glScale(x, y, z) is called. + * @param x the scale factor for the x axis + * @param y the scale factor for the y axis + * @param z the scale factor for the z axis + * @return a scaling matrix + */ +inline Matrix4x4 Matrix4x4::CreateScale(float x, float y, float z) +{ + Matrix4x4 out; + + out.m[_11] = x; + out.m[_12] = 0.0f; + out.m[_13] = 0.0f; + out.m[_14] = 0.0f; + + out.m[_21] = 0.0f; + out.m[_22] = y; + out.m[_23] = 0.0f; + out.m[_24] = 0.0f; + + out.m[_31] = 0.0f; + out.m[_32] = 0.0f; + out.m[_33] = z; + out.m[_34] = 0.0f; + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = 0.0f; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a translation matrix. This returns a matrix equivalent to the + * matrix that OpenGL multiples into the modelview matrix whenever + * glTranslate(x, y, z) is called. + * @param x the amount to translate on the x axis + * @param y the amount to translate on the y axis + * @param z the amount to translate on the z axis + * @return a translation matrix + */ +inline Matrix4x4 Matrix4x4::CreateTranslation(float x, float y, float z) +{ + Matrix4x4 out; + + out.m[_11] = 1.0f; + out.m[_12] = 0.0f; + out.m[_13] = 0.0f; + out.m[_14] = x; + + out.m[_21] = 0.0f; + out.m[_22] = 1.0f; + out.m[_23] = 0.0f; + out.m[_24] = y; + + out.m[_31] = 0.0f; + out.m[_32] = 0.0f; + out.m[_33] = 1.0f; + out.m[_34] = z; + + out.m[_41] = 0.0f; + out.m[_42] = 0.0f; + out.m[_43] = 0.0f; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Constructs a world matrix. + * @param position the position of the object (translation) + * @param forward the forward facing direction of the object + * @param up the up direction of the object + * @return a world matrix + */ +inline Matrix4x4 Matrix4x4::CreateWorld(const Vector3 &position, const Vector3 &forward, const Vector3 &up) +{ + Matrix4x4 out; + + Vector3 f = Vector3::Normalize(-forward); + Vector3 l = Vector3::Normalize(Vector3::Cross(up, f)); + Vector3 u = Vector3::Cross(f, l); + + out.m[_11] = l.x; + out.m[_21] = l.y; + out.m[_31] = l.z; + out.m[_41] = 0.0f; + + out.m[_12] = u.x; + out.m[_22] = u.y; + out.m[_32] = u.z; + out.m[_42] = 0.0f; + + out.m[_13] = f.x; + out.m[_23] = f.y; + out.m[_33] = f.z; + out.m[_43] = 0.0f; + + out.m[_14] = position.x; + out.m[_24] = position.y; + out.m[_34] = position.z; + out.m[_44] = 1.0f; + + return out; +} + +/** + * Calculates the inverse of the specified matrix. + * @param m the matrix to calculate the inverse of + * @return the inverse of the specified matrix + */ +inline Matrix4x4 Matrix4x4::Inverse(const Matrix4x4 &m) +{ + float d = m.GetDeterminant(); + if (IS_CLOSE_ENOUGH(d, 0.0f)) + return IDENTITY_MATRIX; + else + { + Matrix4x4 out; + + d = 1.0f / d; + + out.m[_11] = d * (m.m[_22] * (m.m[_33] * m.m[_44] - m.m[_43] * m.m[_34]) + m.m[_32] * (m.m[_43] * m.m[_24] - m.m[_23] * m.m[_44]) + m.m[_42] * (m.m[_23] * m.m[_34] - m.m[_33] * m.m[_24])); + out.m[_21] = d * (m.m[_23] * (m.m[_31] * m.m[_44] - m.m[_41] * m.m[_34]) + m.m[_33] * (m.m[_41] * m.m[_24] - m.m[_21] * m.m[_44]) + m.m[_43] * (m.m[_21] * m.m[_34] - m.m[_31] * m.m[_24])); + out.m[_31] = d * (m.m[_24] * (m.m[_31] * m.m[_42] - m.m[_41] * m.m[_32]) + m.m[_34] * (m.m[_41] * m.m[_22] - m.m[_21] * m.m[_42]) + m.m[_44] * (m.m[_21] * m.m[_32] - m.m[_31] * m.m[_22])); + out.m[_41] = d * (m.m[_21] * (m.m[_42] * m.m[_33] - m.m[_32] * m.m[_43]) + m.m[_31] * (m.m[_22] * m.m[_43] - m.m[_42] * m.m[_23]) + m.m[_41] * (m.m[_32] * m.m[_23] - m.m[_22] * m.m[_33])); + + out.m[_12] = d * (m.m[_32] * (m.m[_13] * m.m[_44] - m.m[_43] * m.m[_14]) + m.m[_42] * (m.m[_33] * m.m[_14] - m.m[_13] * m.m[_34]) + m.m[_12] * (m.m[_43] * m.m[_34] - m.m[_33] * m.m[_44])); + out.m[_22] = d * (m.m[_33] * (m.m[_11] * m.m[_44] - m.m[_41] * m.m[_14]) + m.m[_43] * (m.m[_31] * m.m[_14] - m.m[_11] * m.m[_34]) + m.m[_13] * (m.m[_41] * m.m[_34] - m.m[_31] * m.m[_44])); + out.m[_32] = d * (m.m[_34] * (m.m[_11] * m.m[_42] - m.m[_41] * m.m[_12]) + m.m[_44] * (m.m[_31] * m.m[_12] - m.m[_11] * m.m[_32]) + m.m[_14] * (m.m[_41] * m.m[_32] - m.m[_31] * m.m[_42])); + out.m[_42] = d * (m.m[_31] * (m.m[_42] * m.m[_13] - m.m[_12] * m.m[_43]) + m.m[_41] * (m.m[_12] * m.m[_33] - m.m[_32] * m.m[_13]) + m.m[_11] * (m.m[_32] * m.m[_43] - m.m[_42] * m.m[_33])); + + out.m[_13] = d * (m.m[_42] * (m.m[_13] * m.m[_24] - m.m[_23] * m.m[_14]) + m.m[_12] * (m.m[_23] * m.m[_44] - m.m[_43] * m.m[_24]) + m.m[_22] * (m.m[_43] * m.m[_14] - m.m[_13] * m.m[_44])); + out.m[_23] = d * (m.m[_43] * (m.m[_11] * m.m[_24] - m.m[_21] * m.m[_14]) + m.m[_13] * (m.m[_21] * m.m[_44] - m.m[_41] * m.m[_24]) + m.m[_23] * (m.m[_41] * m.m[_14] - m.m[_11] * m.m[_44])); + out.m[_33] = d * (m.m[_44] * (m.m[_11] * m.m[_22] - m.m[_21] * m.m[_12]) + m.m[_14] * (m.m[_21] * m.m[_42] - m.m[_41] * m.m[_22]) + m.m[_24] * (m.m[_41] * m.m[_12] - m.m[_11] * m.m[_42])); + out.m[_43] = d * (m.m[_41] * (m.m[_22] * m.m[_13] - m.m[_12] * m.m[_23]) + m.m[_11] * (m.m[_42] * m.m[_23] - m.m[_22] * m.m[_43]) + m.m[_21] * (m.m[_12] * m.m[_43] - m.m[_42] * m.m[_13])); + + out.m[_14] = d * (m.m[_12] * (m.m[_33] * m.m[_24] - m.m[_23] * m.m[_34]) + m.m[_22] * (m.m[_13] * m.m[_34] - m.m[_33] * m.m[_14]) + m.m[_32] * (m.m[_23] * m.m[_14] - m.m[_13] * m.m[_24])); + out.m[_24] = d * (m.m[_13] * (m.m[_31] * m.m[_24] - m.m[_21] * m.m[_34]) + m.m[_23] * (m.m[_11] * m.m[_34] - m.m[_31] * m.m[_14]) + m.m[_33] * (m.m[_21] * m.m[_14] - m.m[_11] * m.m[_24])); + out.m[_34] = d * (m.m[_14] * (m.m[_31] * m.m[_22] - m.m[_21] * m.m[_32]) + m.m[_24] * (m.m[_11] * m.m[_32] - m.m[_31] * m.m[_12]) + m.m[_34] * (m.m[_21] * m.m[_12] - m.m[_11] * m.m[_22])); + out.m[_44] = d * (m.m[_11] * (m.m[_22] * m.m[_33] - m.m[_32] * m.m[_23]) + m.m[_21] * (m.m[_32] * m.m[_13] - m.m[_12] * m.m[_33]) + m.m[_31] * (m.m[_12] * m.m[_23] - m.m[_22] * m.m[_13])); + + return out; + } +} + +/** + * Calculates the transpose of a given matrix. + * @param m the matrix to get the transpose of + * @return the transpose matrix + */ +inline Matrix4x4 Matrix4x4::Transpose(const Matrix4x4 &m) +{ + Matrix4x4 out; + + out.m[_11] = m.m[_11]; + out.m[_12] = m.m[_21]; + out.m[_13] = m.m[_31]; + out.m[_14] = m.m[_41]; + + out.m[_21] = m.m[_12]; + out.m[_22] = m.m[_22]; + out.m[_23] = m.m[_32]; + out.m[_24] = m.m[_42]; + + out.m[_31] = m.m[_13]; + out.m[_32] = m.m[_23]; + out.m[_33] = m.m[_33]; + out.m[_34] = m.m[_43]; + + out.m[_41] = m.m[_14]; + out.m[_42] = m.m[_24]; + out.m[_43] = m.m[_34]; + out.m[_44] = m.m[_44]; + + return out; +} + +inline Matrix4x4 operator+(const Matrix4x4 &left, const Matrix4x4 &right) +{ + Matrix4x4 result; + + result.m[_11] = left.m[_11] + right.m[_11]; + result.m[_12] = left.m[_12] + right.m[_12]; + result.m[_13] = left.m[_13] + right.m[_13]; + result.m[_14] = left.m[_14] + right.m[_14]; + result.m[_21] = left.m[_21] + right.m[_21]; + result.m[_22] = left.m[_22] + right.m[_22]; + result.m[_23] = left.m[_23] + right.m[_23]; + result.m[_24] = left.m[_24] + right.m[_24]; + result.m[_31] = left.m[_31] + right.m[_31]; + result.m[_32] = left.m[_32] + right.m[_32]; + result.m[_33] = left.m[_33] + right.m[_33]; + result.m[_34] = left.m[_34] + right.m[_34]; + result.m[_41] = left.m[_41] + right.m[_41]; + result.m[_42] = left.m[_42] + right.m[_42]; + result.m[_43] = left.m[_43] + right.m[_43]; + result.m[_44] = left.m[_44] + right.m[_44]; + + return result; +} + +inline Matrix4x4 &operator+=(Matrix4x4 &left, const Matrix4x4 &right) +{ + left = left + right; + return left; +} + +inline Matrix4x4 operator-(const Matrix4x4 &left, const Matrix4x4 &right) +{ + Matrix4x4 result; + + result.m[_11] = left.m[_11] - right.m[_11]; + result.m[_12] = left.m[_12] - right.m[_12]; + result.m[_13] = left.m[_13] - right.m[_13]; + result.m[_14] = left.m[_14] - right.m[_14]; + result.m[_21] = left.m[_21] - right.m[_21]; + result.m[_22] = left.m[_22] - right.m[_22]; + result.m[_23] = left.m[_23] - right.m[_23]; + result.m[_24] = left.m[_24] - right.m[_24]; + result.m[_31] = left.m[_31] - right.m[_31]; + result.m[_32] = left.m[_32] - right.m[_32]; + result.m[_33] = left.m[_33] - right.m[_33]; + result.m[_34] = left.m[_34] - right.m[_34]; + result.m[_41] = left.m[_41] - right.m[_41]; + result.m[_42] = left.m[_42] - right.m[_42]; + result.m[_43] = left.m[_43] - right.m[_43]; + result.m[_44] = left.m[_44] - right.m[_44]; + + return result; +} + +inline Matrix4x4 &operator-=(Matrix4x4 &left, const Matrix4x4 &right) +{ + left = left - right; + return left; +} + +inline Matrix4x4 operator*(const Matrix4x4 &left, const Matrix4x4 &right) +{ + Matrix4x4 result; + + result.m[_11] = left.m[_11] * right.m[_11] + left.m[_12] * right.m[_21] + left.m[_13] * right.m[_31] + left.m[_14] * right.m[_41]; + result.m[_12] = left.m[_11] * right.m[_12] + left.m[_12] * right.m[_22] + left.m[_13] * right.m[_32] + left.m[_14] * right.m[_42]; + result.m[_13] = left.m[_11] * right.m[_13] + left.m[_12] * right.m[_23] + left.m[_13] * right.m[_33] + left.m[_14] * right.m[_43]; + result.m[_14] = left.m[_11] * right.m[_14] + left.m[_12] * right.m[_24] + left.m[_13] * right.m[_34] + left.m[_14] * right.m[_44]; + + result.m[_21] = left.m[_21] * right.m[_11] + left.m[_22] * right.m[_21] + left.m[_23] * right.m[_31] + left.m[_24] * right.m[_41]; + result.m[_22] = left.m[_21] * right.m[_12] + left.m[_22] * right.m[_22] + left.m[_23] * right.m[_32] + left.m[_24] * right.m[_42]; + result.m[_23] = left.m[_21] * right.m[_13] + left.m[_22] * right.m[_23] + left.m[_23] * right.m[_33] + left.m[_24] * right.m[_43]; + result.m[_24] = left.m[_21] * right.m[_14] + left.m[_22] * right.m[_24] + left.m[_23] * right.m[_34] + left.m[_24] * right.m[_44]; + + result.m[_31] = left.m[_31] * right.m[_11] + left.m[_32] * right.m[_21] + left.m[_33] * right.m[_31] + left.m[_34] * right.m[_41]; + result.m[_32] = left.m[_31] * right.m[_12] + left.m[_32] * right.m[_22] + left.m[_33] * right.m[_32] + left.m[_34] * right.m[_42]; + result.m[_33] = left.m[_31] * right.m[_13] + left.m[_32] * right.m[_23] + left.m[_33] * right.m[_33] + left.m[_34] * right.m[_43]; + result.m[_34] = left.m[_31] * right.m[_14] + left.m[_32] * right.m[_24] + left.m[_33] * right.m[_34] + left.m[_34] * right.m[_44]; + + result.m[_41] = left.m[_41] * right.m[_11] + left.m[_42] * right.m[_21] + left.m[_43] * right.m[_31] + left.m[_44] * right.m[_41]; + result.m[_42] = left.m[_41] * right.m[_12] + left.m[_42] * right.m[_22] + left.m[_43] * right.m[_32] + left.m[_44] * right.m[_42]; + result.m[_43] = left.m[_41] * right.m[_13] + left.m[_42] * right.m[_23] + left.m[_43] * right.m[_33] + left.m[_44] * right.m[_43]; + result.m[_44] = left.m[_41] * right.m[_14] + left.m[_42] * right.m[_24] + left.m[_43] * right.m[_34] + left.m[_44] * right.m[_44]; + + return result; +} + +inline Matrix4x4 &operator*=(Matrix4x4 &left, const Matrix4x4 &right) +{ + left = left * right; + return left; +} + +inline Matrix4x4 operator*(const Matrix4x4 &left, float right) +{ + Matrix4x4 result; + + result.m[_11] = left.m[_11] * right; + result.m[_12] = left.m[_12] * right; + result.m[_13] = left.m[_13] * right; + result.m[_14] = left.m[_14] * right; + result.m[_21] = left.m[_21] * right; + result.m[_22] = left.m[_22] * right; + result.m[_23] = left.m[_23] * right; + result.m[_24] = left.m[_24] * right; + result.m[_31] = left.m[_31] * right; + result.m[_32] = left.m[_32] * right; + result.m[_33] = left.m[_33] * right; + result.m[_34] = left.m[_34] * right; + result.m[_41] = left.m[_41] * right; + result.m[_42] = left.m[_42] * right; + result.m[_43] = left.m[_43] * right; + result.m[_44] = left.m[_44] * right; + + return result; +} + +inline Matrix4x4 &operator*=(Matrix4x4 &left, float right) +{ + left = left * right; + return left; +} + +inline Vector3 operator*(const Vector3 &left, const Matrix4x4 &right) +{ + return Vector3( + left.x * right.m[_11] + left.y * right.m[_12] + left.z * right.m[_13] + right.m[_14], + left.x * right.m[_21] + left.y * right.m[_22] + left.z * right.m[_23] + right.m[_24], + left.x * right.m[_31] + left.y * right.m[_32] + left.z * right.m[_33] + right.m[_34] + ); +} + +#endif diff --git a/MeshConverter/src/geometry/quaternion.h b/MeshConverter/src/geometry/quaternion.h index 0db783c..d21ed2d 100644 --- a/MeshConverter/src/geometry/quaternion.h +++ b/MeshConverter/src/geometry/quaternion.h @@ -1,491 +1,491 @@ -#ifndef __GEOMETRY_QUATERNION_H_INCLUDED__ -#define __GEOMETRY_QUATERNION_H_INCLUDED__ - -#include -#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 - *

Referenced/based on code from:

- *
    - *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • - *
  • More OpenGL Game Programming (Dave Astle, 2006)
  • - *
  • http://www.dhpoware.com/source/mathlib.html
  • - *
- * @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 +#ifndef __GEOMETRY_QUATERNION_H_INCLUDED__ +#define __GEOMETRY_QUATERNION_H_INCLUDED__ + +#include +#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 + *

Referenced/based on code from:

+ *
    + *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • + *
  • More OpenGL Game Programming (Dave Astle, 2006)
  • + *
  • http://www.dhpoware.com/source/mathlib.html
  • + *
+ * @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 diff --git a/MeshConverter/src/geometry/triangle.h b/MeshConverter/src/geometry/triangle.h index a31db2a..d0f6909 100644 --- a/MeshConverter/src/geometry/triangle.h +++ b/MeshConverter/src/geometry/triangle.h @@ -1,15 +1,15 @@ -#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 +#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 diff --git a/MeshConverter/src/geometry/vector2.h b/MeshConverter/src/geometry/vector2.h index 596255a..80b75a5 100644 --- a/MeshConverter/src/geometry/vector2.h +++ b/MeshConverter/src/geometry/vector2.h @@ -1,236 +1,236 @@ -#ifndef __GEOMETRY_VECTOR2_H_INCLUDED__ -#define __GEOMETRY_VECTOR2_H_INCLUDED__ - -#include - -/** - * Represents a 2D vector and provides common methods for vector math. - *

Referenced/based on code from:

- *
    - *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • - *
  • http://www.dhpoware.com/source/mathlib.html
  • - *
- * @author Gered - */ -class Vector2 -{ -public: - Vector2() {} - - Vector2(float x, float y) - { - this->x = x; - this->y = y; - } - - Vector2(const float *v) - { - x = v[0]; - y = v[1]; - } - - ~Vector2() {} - - void Set(float x, float y); - - static float Distance(const Vector2 &a, const Vector2 &b); - static float Dot(const Vector2 &a, const Vector2 &b); - static float Length(const Vector2 &v); - static float LengthSquared(const Vector2 &v); - static Vector2 Normalize(const Vector2 &v); - static Vector2 SetLength(const Vector2 &v, float length); - - float x; - float y; -}; - -bool operator==(const Vector2 &left, const Vector2 &right); -Vector2 operator-(const Vector2 &left); -Vector2 operator+(const Vector2 &left, const Vector2 &right); -Vector2 &operator+=(Vector2 &left, const Vector2 &right); -Vector2 operator-(const Vector2 &left, const Vector2 &right); -Vector2 &operator-=(Vector2 &left, const Vector2 &right); -Vector2 operator*(const Vector2 &left, float right); -Vector2 &operator*=(Vector2 &left, float right); -Vector2 operator/(const Vector2 &left, float right); -Vector2 &operator/=(Vector2 &left, float right); -Vector2 operator*(const Vector2 &left, const Vector2 &right); -Vector2 &operator*=(Vector2 &left, const Vector2 &right); -Vector2 operator/(const Vector2 &left, const Vector2 &right); -Vector2 &operator/=(Vector2 &left, const Vector2 &right); - -inline void Vector2::Set(float x, float y) -{ - this->x = x; - this->y = y; -} - -/** - * Calculates the distance between two points. - * @param a the first point - * @param b the second point - * @return the distance between both points - */ -inline float Vector2::Distance(const Vector2 &a, const Vector2 &b) -{ - return sqrtf( - ((b.x - a.x) * (b.x - a.x)) + - ((b.y - a.y) * (b.y - a.y)) - ); -} - -/** - * Computes the dot product of 2 vectors. - * @param a first vector - * @param b second vector - * @return the dot product - */ -inline float Vector2::Dot(const Vector2 &a, const Vector2 &b) -{ - return - (a.x * b.y) + - (a.y * b.y); -} - -/** - * Returns the length (magnitude) of a vector. - * @param v vector to calculate the length of - * @return the vector length - */ -inline float Vector2::Length(const Vector2 &v) -{ - return sqrtf( - (v.x * v.x) + - (v.y * v.y) - ); -} - -/** - * Returns the squared length of a vector (the magnitude minus the sqrt - * call). - * @param v vector to calculate the squared length of - * @return squared length of the vector - */ -inline float Vector2::LengthSquared(const Vector2 &v) -{ - return - (v.x * v.x) + - (v.y * v.y); -} - -/** - * Normalizes a vector. - * @param v vector to normalize - * @return the normalized vector - */ -inline Vector2 Vector2::Normalize(const Vector2 &v) -{ - float inverseLength = 1.0f / Length(v); - return Vector2( - v.x * inverseLength, - v.y * inverseLength - ); -} - -/** - * Adjusts a vector so that it's length is equal to the given length. - * @param v the original vector to be adjusted - * @param length desired vector length (magnitude) - * @return the resulting vector after it's length has been converted to the - * desired amount - */ -inline Vector2 Vector2::SetLength(const Vector2 &v, float length) -{ - return v * (length / Length(v)); -} - -inline bool operator==(const Vector2 &left, const Vector2 &right) -{ - return (left.x == right.x && left.y == right.y); -} - -inline Vector2 operator-(const Vector2 &left) -{ - return Vector2(-left.x, -left.y); -} - -inline Vector2 operator+(const Vector2 &left, const Vector2 &right) -{ - return Vector2(left.x + right.x, left.y + right.y); -} - -inline Vector2 &operator+=(Vector2 &left, const Vector2 &right) -{ - left.x += right.x; - left.y += right.y; - - return left; -} - -inline Vector2 operator-(const Vector2 &left, const Vector2 &right) -{ - return Vector2(left.x - right.x, left.y - right.y); -} - -inline Vector2 &operator-=(Vector2 &left, const Vector2 &right) -{ - left.x -= right.x; - left.y -= right.y; - - return left; -} - -inline Vector2 operator*(const Vector2 &left, float right) -{ - return Vector2(left.x * right, left.y * right); -} - -inline Vector2 &operator*=(Vector2 &left, float right) -{ - left.x *= right; - left.y *= right; - - return left; -} - -inline Vector2 operator/(const Vector2 &left, float right) -{ - return Vector2(left.x / right, left.y / right); -} - -inline Vector2 &operator/=(Vector2 &left, float right) -{ - left.x /= right; - left.y /= right; - - return left; -} - -inline Vector2 operator*(const Vector2 &left, const Vector2 &right) -{ - return Vector2(left.x * right.x, left.y * right.y); -} - -inline Vector2 &operator*=(Vector2 &left, const Vector2 &right) -{ - left.x *= right.x; - left.y *= right.y; - - return left; -} - -inline Vector2 operator/(const Vector2 &left, const Vector2 &right) -{ - return Vector2(left.x / right.x, left.y / right.y); -} - -inline Vector2 &operator/=(Vector2 &left, const Vector2 &right) -{ - left.x /= right.x; - left.y /= right.y; - - return left; -} - - -#endif +#ifndef __GEOMETRY_VECTOR2_H_INCLUDED__ +#define __GEOMETRY_VECTOR2_H_INCLUDED__ + +#include + +/** + * Represents a 2D vector and provides common methods for vector math. + *

Referenced/based on code from:

+ *
    + *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • + *
  • http://www.dhpoware.com/source/mathlib.html
  • + *
+ * @author Gered + */ +class Vector2 +{ +public: + Vector2() {} + + Vector2(float x, float y) + { + this->x = x; + this->y = y; + } + + Vector2(const float *v) + { + x = v[0]; + y = v[1]; + } + + ~Vector2() {} + + void Set(float x, float y); + + static float Distance(const Vector2 &a, const Vector2 &b); + static float Dot(const Vector2 &a, const Vector2 &b); + static float Length(const Vector2 &v); + static float LengthSquared(const Vector2 &v); + static Vector2 Normalize(const Vector2 &v); + static Vector2 SetLength(const Vector2 &v, float length); + + float x; + float y; +}; + +bool operator==(const Vector2 &left, const Vector2 &right); +Vector2 operator-(const Vector2 &left); +Vector2 operator+(const Vector2 &left, const Vector2 &right); +Vector2 &operator+=(Vector2 &left, const Vector2 &right); +Vector2 operator-(const Vector2 &left, const Vector2 &right); +Vector2 &operator-=(Vector2 &left, const Vector2 &right); +Vector2 operator*(const Vector2 &left, float right); +Vector2 &operator*=(Vector2 &left, float right); +Vector2 operator/(const Vector2 &left, float right); +Vector2 &operator/=(Vector2 &left, float right); +Vector2 operator*(const Vector2 &left, const Vector2 &right); +Vector2 &operator*=(Vector2 &left, const Vector2 &right); +Vector2 operator/(const Vector2 &left, const Vector2 &right); +Vector2 &operator/=(Vector2 &left, const Vector2 &right); + +inline void Vector2::Set(float x, float y) +{ + this->x = x; + this->y = y; +} + +/** + * Calculates the distance between two points. + * @param a the first point + * @param b the second point + * @return the distance between both points + */ +inline float Vector2::Distance(const Vector2 &a, const Vector2 &b) +{ + return sqrtf( + ((b.x - a.x) * (b.x - a.x)) + + ((b.y - a.y) * (b.y - a.y)) + ); +} + +/** + * Computes the dot product of 2 vectors. + * @param a first vector + * @param b second vector + * @return the dot product + */ +inline float Vector2::Dot(const Vector2 &a, const Vector2 &b) +{ + return + (a.x * b.y) + + (a.y * b.y); +} + +/** + * Returns the length (magnitude) of a vector. + * @param v vector to calculate the length of + * @return the vector length + */ +inline float Vector2::Length(const Vector2 &v) +{ + return sqrtf( + (v.x * v.x) + + (v.y * v.y) + ); +} + +/** + * Returns the squared length of a vector (the magnitude minus the sqrt + * call). + * @param v vector to calculate the squared length of + * @return squared length of the vector + */ +inline float Vector2::LengthSquared(const Vector2 &v) +{ + return + (v.x * v.x) + + (v.y * v.y); +} + +/** + * Normalizes a vector. + * @param v vector to normalize + * @return the normalized vector + */ +inline Vector2 Vector2::Normalize(const Vector2 &v) +{ + float inverseLength = 1.0f / Length(v); + return Vector2( + v.x * inverseLength, + v.y * inverseLength + ); +} + +/** + * Adjusts a vector so that it's length is equal to the given length. + * @param v the original vector to be adjusted + * @param length desired vector length (magnitude) + * @return the resulting vector after it's length has been converted to the + * desired amount + */ +inline Vector2 Vector2::SetLength(const Vector2 &v, float length) +{ + return v * (length / Length(v)); +} + +inline bool operator==(const Vector2 &left, const Vector2 &right) +{ + return (left.x == right.x && left.y == right.y); +} + +inline Vector2 operator-(const Vector2 &left) +{ + return Vector2(-left.x, -left.y); +} + +inline Vector2 operator+(const Vector2 &left, const Vector2 &right) +{ + return Vector2(left.x + right.x, left.y + right.y); +} + +inline Vector2 &operator+=(Vector2 &left, const Vector2 &right) +{ + left.x += right.x; + left.y += right.y; + + return left; +} + +inline Vector2 operator-(const Vector2 &left, const Vector2 &right) +{ + return Vector2(left.x - right.x, left.y - right.y); +} + +inline Vector2 &operator-=(Vector2 &left, const Vector2 &right) +{ + left.x -= right.x; + left.y -= right.y; + + return left; +} + +inline Vector2 operator*(const Vector2 &left, float right) +{ + return Vector2(left.x * right, left.y * right); +} + +inline Vector2 &operator*=(Vector2 &left, float right) +{ + left.x *= right; + left.y *= right; + + return left; +} + +inline Vector2 operator/(const Vector2 &left, float right) +{ + return Vector2(left.x / right, left.y / right); +} + +inline Vector2 &operator/=(Vector2 &left, float right) +{ + left.x /= right; + left.y /= right; + + return left; +} + +inline Vector2 operator*(const Vector2 &left, const Vector2 &right) +{ + return Vector2(left.x * right.x, left.y * right.y); +} + +inline Vector2 &operator*=(Vector2 &left, const Vector2 &right) +{ + left.x *= right.x; + left.y *= right.y; + + return left; +} + +inline Vector2 operator/(const Vector2 &left, const Vector2 &right) +{ + return Vector2(left.x / right.x, left.y / right.y); +} + +inline Vector2 &operator/=(Vector2 &left, const Vector2 &right) +{ + left.x /= right.x; + left.y /= right.y; + + return left; +} + + +#endif diff --git a/MeshConverter/src/geometry/vector3.h b/MeshConverter/src/geometry/vector3.h index 1803c8a..c93d4a6 100644 --- a/MeshConverter/src/geometry/vector3.h +++ b/MeshConverter/src/geometry/vector3.h @@ -1,341 +1,341 @@ -#ifndef __GEOMETRY_VECTOR3_H_INCLUDED__ -#define __GEOMETRY_VECTOR3_H_INCLUDED__ - -#include -#include "../common.h" - -/** - *

Represents a 3D vector and provides common methods for vector math.

- *

Referenced/based on code from:

- *
    - *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • - *
  • http://www.dhpoware.com/source/mathlib.html
  • - *
  • http://www.peroxide.dk/papers/collision/collision.pdf
  • - *
- * @author Gered - */ -class Vector3 -{ -public: - Vector3() {} - - Vector3(float x, float y, float z) - { - this->x = x; - this->y = y; - this->z = z; - } - - Vector3(const float *v) - { - x = v[0]; - y = v[1]; - z = v[2]; - } - - ~Vector3() {} - - void Set(float x, float y, float z); - - static Vector3 Cross(const Vector3 &a, const Vector3 &b); - static float Distance(const Vector3 &a, const Vector3 &b); - static float Dot(const Vector3 &a, const Vector3 &b); - static BOOL IsPointInTriangle(const Vector3 &point, const Vector3 &a, const Vector3 &b, const Vector3 &c); - static float Length(const Vector3 &v); - static float LengthSquared(const Vector3 &v); - static Vector3 Normalize(const Vector3 &v); - static Vector3 SetLength(const Vector3 &v, float length); - static Vector3 SurfaceNormal(const Vector3 &a, const Vector3 &b, const Vector3 &c); - static Vector3 Lerp(const Vector3 &a, const Vector3 &b, float interpolation); - - float x; - float y; - float z; -}; - -bool operator==(const Vector3 &left, const Vector3 &right); -Vector3 operator-(const Vector3 &left); -Vector3 operator+(const Vector3 &left, const Vector3 &right); -Vector3 &operator+=(Vector3 &left, const Vector3 &right); -Vector3 operator-(const Vector3 &left, const Vector3 &right); -Vector3 &operator-=(Vector3 &left, const Vector3 &right); -Vector3 operator*(const Vector3 &left, float right); -Vector3 &operator*=(Vector3 &left, float right); -Vector3 operator/(const Vector3 &left, float right); -Vector3 &operator/=(Vector3 &left, float right); -Vector3 operator*(const Vector3 &left, const Vector3 &right); -Vector3 &operator*=(Vector3 &left, const Vector3 &right); -Vector3 operator/(const Vector3 &left, const Vector3 &right); -Vector3 &operator/=(Vector3 &left, const Vector3 &right); - -#define ZERO_VECTOR Vector3(0.0f, 0.0f, 0.0f) -#define X_AXIS Vector3(1.0f, 0.0f, 0.0f) -#define Y_AXIS Vector3(0.0f, 1.0f, 0.0f) -#define Z_AXIS Vector3(0.0f, 0.0f, 1.0f) -#define UP Vector3(0.0f, 1.0f, 0.0f) -#define DOWN Vector3(0.0f, -1.0f, 0.0f) -#define FORWARD Vector3(0.0f, 0.0f, -1.0f) -#define BACKWARD Vector3(0.0f, 0.0f, 1.0f) -#define LEFT Vector3(-1.0f, 0.0f, 0.0f) -#define RIGHT Vector3(1.0f, 0.0f, 0.0f) - -inline void Vector3::Set(float x, float y, float z) -{ - this->x = x; - this->y = y; - this->z = z; -} - -/** - * Computes the cross product of 2 vectors. - * @param a first vector - * @param b second vector - * @return the cross product - */ -inline Vector3 Vector3::Cross(const Vector3 &a, const Vector3 &b) -{ - return Vector3( - (a.y * b.z) - (a.z * b.y), - (a.z * b.x) - (a.x * b.z), - (a.x * b.y) - (a.y * b.x) - ); -} - -/** - * Calculates the distance between two points. - * @param a the first point - * @param b the second point - * @return the distance between both points - */ -inline float Vector3::Distance(const Vector3 &a, const Vector3 &b) -{ - return sqrtf( - ((b.x - a.x) * (b.x - a.x)) + - ((b.y - a.y) * (b.y - a.y)) + - ((b.z - a.z) * (b.z - a.z)) - ); -} - -/** - * Computes the dot product of 2 vectors. - * @param a first vector - * @param b second vector - * @return the dot product - */ -inline float Vector3::Dot(const Vector3 &a, const Vector3 &b) -{ - return - (a.x * b.x) + - (a.y * b.y) + - (a.z * b.z); -} - -/** - * Checks if a given point lies inside a triangle or not. - * @param point point to test - * @param a first vector of the triangle - * @param b second vector of the triangle - * @param c third vector of the triangle - * @return TRUE if the point lies inside the triangle - */ -inline BOOL Vector3::IsPointInTriangle(const Vector3 &point, const Vector3 &a, const Vector3 &b, const Vector3 &c) -{ - Vector3 v0 = c - a; - Vector3 v1 = b - a; - Vector3 v2 = point - a; - - float dot00 = (v0.x * v0.x) + (v0.y * v0.y) + (v0.z * v0.z); - float dot01 = (v0.x * v1.x) + (v0.y * v1.y) + (v0.z * v1.z); - float dot02 = (v0.x * v2.x) + (v0.y * v2.y) + (v0.z * v2.z); - float dot11 = (v1.x * v1.x) + (v1.y * v1.y) + (v1.z * v1.z); - float dot12 = (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); - - float denom = dot00 * dot11 - dot01 * dot01; - if (denom == 0) - return FALSE; - - float u = (dot11 * dot02 - dot01 * dot12) / denom; - float v = (dot00 * dot12 - dot01 * dot02) / denom; - - if (u >= 0 && v >= 0 && u + v <= 1) - return TRUE; - else - return FALSE; -} - -/** - * Returns the length (magnitude) of a vector. - * @param v vector to calculate the length of - * @return the vector length - */ -inline float Vector3::Length(const Vector3 &v) -{ - return sqrtf( - (v.x * v.x) + - (v.y * v.y) + - (v.z * v.z) - ); -} - -/** - * Returns the squared length of a vector (the magnitude minus the sqrt - * call). - * @param v vector to calculate the squared length of - * @return squared length of the vector - */ -inline float Vector3::LengthSquared(const Vector3 &v) -{ - return - (v.x * v.x) + - (v.y * v.y) + - (v.z * v.z); -} - -/** - * Normalizes a vector. - * @param v vector to normalize - * @return the normalized vector - */ -inline Vector3 Vector3::Normalize(const Vector3 &v) -{ - float inverseLength = 1.0f / Length(v); - return Vector3( - v.x * inverseLength, - v.y * inverseLength, - v.z * inverseLength - ); -} - -/** - * Adjusts a vector so that it's length is equal to the given - * length. - * @param v the original vector to be adjusted - * @param length desired vector length (magnitude) - * @return the resulting vector after it's length has been converted to the - * desired amount - */ -inline Vector3 Vector3::SetLength(const Vector3 &v, float length) -{ - return v * (length / Length(v)); -} - -/** - * Calculates a normal vector for the given 3 vectors making up a - * triangle (counter clockwise order). - * @param a first vertex - * @param b second vertex - * @param c third vertex - * @return normal vector for the triangle - */ -inline Vector3 Vector3::SurfaceNormal(const Vector3 &a, const Vector3 &b, const Vector3 &c) -{ - return Normalize(Cross((b - a), (c - a))); -} - -/** - * Linearly interpolates between two vectors. - * @param a the first vector - * @param b the second vector - * @param interpolation the amount to interpolate - * @return Vector3 the interpolated vector - */ -inline Vector3 Vector3::Lerp(const Vector3 &a, const Vector3 &b, float interpolation) -{ - return a + (b - a) * interpolation; -} - -inline bool operator==(const Vector3 &left, const Vector3 &right) -{ - return (left.x == right.x && left.y == right.y && left.z == right.z); -} - -inline Vector3 operator-(const Vector3 &left) -{ - return Vector3(-left.x, -left.y, -left.z); -} - -inline Vector3 operator+(const Vector3 &left, const Vector3 &right) -{ - return Vector3(left.x + right.x, left.y + right.y, left.z + right.z); -} - -inline Vector3 &operator+=(Vector3 &left, const Vector3 &right) -{ - left.x += right.x; - left.y += right.y; - left.z += right.z; - - return left; -} - -inline Vector3 operator-(const Vector3 &left, const Vector3 &right) -{ - return Vector3(left.x - right.x, left.y - right.y, left.z - right.z); -} - -inline Vector3 &operator-=(Vector3 &left, const Vector3 &right) -{ - left.x -= right.x; - left.y -= right.y; - left.z -= right.z; - - return left; -} - -inline Vector3 operator*(const Vector3 &left, float right) -{ - return Vector3(left.x * right, left.y * right, left.z * right); -} - -inline Vector3 &operator*=(Vector3 &left, float right) -{ - left.x *= right; - left.y *= right; - left.z *= right; - - return left; -} - -inline Vector3 operator/(const Vector3 &left, float right) -{ - return Vector3(left.x / right, left.y / right, left.z / right); -} - -inline Vector3 &operator/=(Vector3 &left, float right) -{ - left.x /= right; - left.y /= right; - left.z /= right; - - return left; -} - -inline Vector3 operator*(const Vector3 &left, const Vector3 &right) -{ - return Vector3(left.x * right.x, left.y * right.y, left.z * right.z); -} - -inline Vector3 &operator*=(Vector3 &left, const Vector3 &right) -{ - left.x *= right.x; - left.y *= right.y; - left.z *= right.z; - - return left; -} - -inline Vector3 operator/(const Vector3 &left, const Vector3 &right) -{ - return Vector3(left.x / right.x, left.y / right.y, left.z / right.z); -} - -inline Vector3 &operator/=(Vector3 &left, const Vector3 &right) -{ - left.x /= right.x; - left.y /= right.y; - left.z /= right.z; - - return left; -} - -#endif +#ifndef __GEOMETRY_VECTOR3_H_INCLUDED__ +#define __GEOMETRY_VECTOR3_H_INCLUDED__ + +#include +#include "../common.h" + +/** + *

Represents a 3D vector and provides common methods for vector math.

+ *

Referenced/based on code from:

+ *
    + *
  • 3D Math Primer for Graphics and Game Development (Dunn & Parberry, 2002)
  • + *
  • http://www.dhpoware.com/source/mathlib.html
  • + *
  • http://www.peroxide.dk/papers/collision/collision.pdf
  • + *
+ * @author Gered + */ +class Vector3 +{ +public: + Vector3() {} + + Vector3(float x, float y, float z) + { + this->x = x; + this->y = y; + this->z = z; + } + + Vector3(const float *v) + { + x = v[0]; + y = v[1]; + z = v[2]; + } + + ~Vector3() {} + + void Set(float x, float y, float z); + + static Vector3 Cross(const Vector3 &a, const Vector3 &b); + static float Distance(const Vector3 &a, const Vector3 &b); + static float Dot(const Vector3 &a, const Vector3 &b); + static BOOL IsPointInTriangle(const Vector3 &point, const Vector3 &a, const Vector3 &b, const Vector3 &c); + static float Length(const Vector3 &v); + static float LengthSquared(const Vector3 &v); + static Vector3 Normalize(const Vector3 &v); + static Vector3 SetLength(const Vector3 &v, float length); + static Vector3 SurfaceNormal(const Vector3 &a, const Vector3 &b, const Vector3 &c); + static Vector3 Lerp(const Vector3 &a, const Vector3 &b, float interpolation); + + float x; + float y; + float z; +}; + +bool operator==(const Vector3 &left, const Vector3 &right); +Vector3 operator-(const Vector3 &left); +Vector3 operator+(const Vector3 &left, const Vector3 &right); +Vector3 &operator+=(Vector3 &left, const Vector3 &right); +Vector3 operator-(const Vector3 &left, const Vector3 &right); +Vector3 &operator-=(Vector3 &left, const Vector3 &right); +Vector3 operator*(const Vector3 &left, float right); +Vector3 &operator*=(Vector3 &left, float right); +Vector3 operator/(const Vector3 &left, float right); +Vector3 &operator/=(Vector3 &left, float right); +Vector3 operator*(const Vector3 &left, const Vector3 &right); +Vector3 &operator*=(Vector3 &left, const Vector3 &right); +Vector3 operator/(const Vector3 &left, const Vector3 &right); +Vector3 &operator/=(Vector3 &left, const Vector3 &right); + +#define ZERO_VECTOR Vector3(0.0f, 0.0f, 0.0f) +#define X_AXIS Vector3(1.0f, 0.0f, 0.0f) +#define Y_AXIS Vector3(0.0f, 1.0f, 0.0f) +#define Z_AXIS Vector3(0.0f, 0.0f, 1.0f) +#define UP Vector3(0.0f, 1.0f, 0.0f) +#define DOWN Vector3(0.0f, -1.0f, 0.0f) +#define FORWARD Vector3(0.0f, 0.0f, -1.0f) +#define BACKWARD Vector3(0.0f, 0.0f, 1.0f) +#define LEFT Vector3(-1.0f, 0.0f, 0.0f) +#define RIGHT Vector3(1.0f, 0.0f, 0.0f) + +inline void Vector3::Set(float x, float y, float z) +{ + this->x = x; + this->y = y; + this->z = z; +} + +/** + * Computes the cross product of 2 vectors. + * @param a first vector + * @param b second vector + * @return the cross product + */ +inline Vector3 Vector3::Cross(const Vector3 &a, const Vector3 &b) +{ + return Vector3( + (a.y * b.z) - (a.z * b.y), + (a.z * b.x) - (a.x * b.z), + (a.x * b.y) - (a.y * b.x) + ); +} + +/** + * Calculates the distance between two points. + * @param a the first point + * @param b the second point + * @return the distance between both points + */ +inline float Vector3::Distance(const Vector3 &a, const Vector3 &b) +{ + return sqrtf( + ((b.x - a.x) * (b.x - a.x)) + + ((b.y - a.y) * (b.y - a.y)) + + ((b.z - a.z) * (b.z - a.z)) + ); +} + +/** + * Computes the dot product of 2 vectors. + * @param a first vector + * @param b second vector + * @return the dot product + */ +inline float Vector3::Dot(const Vector3 &a, const Vector3 &b) +{ + return + (a.x * b.x) + + (a.y * b.y) + + (a.z * b.z); +} + +/** + * Checks if a given point lies inside a triangle or not. + * @param point point to test + * @param a first vector of the triangle + * @param b second vector of the triangle + * @param c third vector of the triangle + * @return TRUE if the point lies inside the triangle + */ +inline BOOL Vector3::IsPointInTriangle(const Vector3 &point, const Vector3 &a, const Vector3 &b, const Vector3 &c) +{ + Vector3 v0 = c - a; + Vector3 v1 = b - a; + Vector3 v2 = point - a; + + float dot00 = (v0.x * v0.x) + (v0.y * v0.y) + (v0.z * v0.z); + float dot01 = (v0.x * v1.x) + (v0.y * v1.y) + (v0.z * v1.z); + float dot02 = (v0.x * v2.x) + (v0.y * v2.y) + (v0.z * v2.z); + float dot11 = (v1.x * v1.x) + (v1.y * v1.y) + (v1.z * v1.z); + float dot12 = (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); + + float denom = dot00 * dot11 - dot01 * dot01; + if (denom == 0) + return FALSE; + + float u = (dot11 * dot02 - dot01 * dot12) / denom; + float v = (dot00 * dot12 - dot01 * dot02) / denom; + + if (u >= 0 && v >= 0 && u + v <= 1) + return TRUE; + else + return FALSE; +} + +/** + * Returns the length (magnitude) of a vector. + * @param v vector to calculate the length of + * @return the vector length + */ +inline float Vector3::Length(const Vector3 &v) +{ + return sqrtf( + (v.x * v.x) + + (v.y * v.y) + + (v.z * v.z) + ); +} + +/** + * Returns the squared length of a vector (the magnitude minus the sqrt + * call). + * @param v vector to calculate the squared length of + * @return squared length of the vector + */ +inline float Vector3::LengthSquared(const Vector3 &v) +{ + return + (v.x * v.x) + + (v.y * v.y) + + (v.z * v.z); +} + +/** + * Normalizes a vector. + * @param v vector to normalize + * @return the normalized vector + */ +inline Vector3 Vector3::Normalize(const Vector3 &v) +{ + float inverseLength = 1.0f / Length(v); + return Vector3( + v.x * inverseLength, + v.y * inverseLength, + v.z * inverseLength + ); +} + +/** + * Adjusts a vector so that it's length is equal to the given + * length. + * @param v the original vector to be adjusted + * @param length desired vector length (magnitude) + * @return the resulting vector after it's length has been converted to the + * desired amount + */ +inline Vector3 Vector3::SetLength(const Vector3 &v, float length) +{ + return v * (length / Length(v)); +} + +/** + * Calculates a normal vector for the given 3 vectors making up a + * triangle (counter clockwise order). + * @param a first vertex + * @param b second vertex + * @param c third vertex + * @return normal vector for the triangle + */ +inline Vector3 Vector3::SurfaceNormal(const Vector3 &a, const Vector3 &b, const Vector3 &c) +{ + return Normalize(Cross((b - a), (c - a))); +} + +/** + * Linearly interpolates between two vectors. + * @param a the first vector + * @param b the second vector + * @param interpolation the amount to interpolate + * @return Vector3 the interpolated vector + */ +inline Vector3 Vector3::Lerp(const Vector3 &a, const Vector3 &b, float interpolation) +{ + return a + (b - a) * interpolation; +} + +inline bool operator==(const Vector3 &left, const Vector3 &right) +{ + return (left.x == right.x && left.y == right.y && left.z == right.z); +} + +inline Vector3 operator-(const Vector3 &left) +{ + return Vector3(-left.x, -left.y, -left.z); +} + +inline Vector3 operator+(const Vector3 &left, const Vector3 &right) +{ + return Vector3(left.x + right.x, left.y + right.y, left.z + right.z); +} + +inline Vector3 &operator+=(Vector3 &left, const Vector3 &right) +{ + left.x += right.x; + left.y += right.y; + left.z += right.z; + + return left; +} + +inline Vector3 operator-(const Vector3 &left, const Vector3 &right) +{ + return Vector3(left.x - right.x, left.y - right.y, left.z - right.z); +} + +inline Vector3 &operator-=(Vector3 &left, const Vector3 &right) +{ + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + + return left; +} + +inline Vector3 operator*(const Vector3 &left, float right) +{ + return Vector3(left.x * right, left.y * right, left.z * right); +} + +inline Vector3 &operator*=(Vector3 &left, float right) +{ + left.x *= right; + left.y *= right; + left.z *= right; + + return left; +} + +inline Vector3 operator/(const Vector3 &left, float right) +{ + return Vector3(left.x / right, left.y / right, left.z / right); +} + +inline Vector3 &operator/=(Vector3 &left, float right) +{ + left.x /= right; + left.y /= right; + left.z /= right; + + return left; +} + +inline Vector3 operator*(const Vector3 &left, const Vector3 &right) +{ + return Vector3(left.x * right.x, left.y * right.y, left.z * right.z); +} + +inline Vector3 &operator*=(Vector3 &left, const Vector3 &right) +{ + left.x *= right.x; + left.y *= right.y; + left.z *= right.z; + + return left; +} + +inline Vector3 operator/(const Vector3 &left, const Vector3 &right) +{ + return Vector3(left.x / right.x, left.y / right.y, left.z / right.z); +} + +inline Vector3 &operator/=(Vector3 &left, const Vector3 &right) +{ + left.x /= right.x; + left.y /= right.y; + left.z /= right.z; + + return left; +} + +#endif diff --git a/MeshConverter/src/main.cpp b/MeshConverter/src/main.cpp index f6f48b1..8b34121 100644 --- a/MeshConverter/src/main.cpp +++ b/MeshConverter/src/main.cpp @@ -1,117 +1,117 @@ -#include -#include -#include - -#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"); - - if (argc == 1) - { - printf("No input file specified.\n"); - printf("Usage: meshconverter.exe [inputfile]\n\n"); - return 1; - } - - std::string file = argv[1]; - std::string extension; - - try - { - extension = file.substr(file.find_last_of('.'), std::string::npos); - for (int i = 0; i < extension.size(); ++i) - extension[i] = tolower(extension[i]); - } - catch (std::exception &e) - { - extension = ""; - } - - std::string meshFile = ""; - if (extension.length() > 0) - { - meshFile = file; - meshFile.erase(meshFile.find_last_of('.'), std::string::npos); - meshFile.append(".mesh"); - } - - if (extension == ".obj") - { - 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; - } - } - else if (extension == ".md2") - { - 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"); - return 1; - } - - printf("Finished converting to %s\n", meshFile.c_str()); - - return 0; - +#include +#include +#include + +#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"); + + if (argc == 1) + { + printf("No input file specified.\n"); + printf("Usage: meshconverter.exe [inputfile]\n\n"); + return 1; + } + + std::string file = argv[1]; + std::string extension; + + try + { + extension = file.substr(file.find_last_of('.'), std::string::npos); + for (int i = 0; i < extension.size(); ++i) + extension[i] = tolower(extension[i]); + } + catch (std::exception &e) + { + extension = ""; + } + + std::string meshFile = ""; + if (extension.length() > 0) + { + meshFile = file; + meshFile.erase(meshFile.find_last_of('.'), std::string::npos); + meshFile.append(".mesh"); + } + + if (extension == ".obj") + { + 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; + } + } + else if (extension == ".md2") + { + 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"); + return 1; + } + + printf("Finished converting to %s\n", meshFile.c_str()); + + return 0; + } \ No newline at end of file diff --git a/MeshConverter/src/md2/md2.cpp b/MeshConverter/src/md2/md2.cpp index 384df44..009ad02 100644 --- a/MeshConverter/src/md2/md2.cpp +++ b/MeshConverter/src/md2/md2.cpp @@ -1,358 +1,358 @@ -#include "md2.h" - -#include -#include "../chunks/chunks.h" - -Md2::Md2() -{ - m_numFrames = 0; - m_numPolys = 0; - m_numTexCoords = 0; - m_numVertices = 0; - m_numSkins = 0; - m_frames = NULL; - m_polys = NULL; - m_texCoords = NULL; - m_skins = NULL; -} - -void Md2::Release() -{ - delete[] m_frames; - delete[] m_polys; - delete[] m_texCoords; - delete[] m_skins; - m_numFrames = 0; - m_numPolys = 0; - m_numTexCoords = 0; - m_numVertices = 0; - m_numSkins = 0; - m_frames = NULL; - m_polys = NULL; - m_texCoords = NULL; - m_skins = NULL; -} - -bool Md2::Load(const std::string &file) -{ - FILE *fp; - unsigned char c; - unsigned short u, v, t; - float x, y, z; - Md2Header header; - Vector3 scale, translate; - - fp = fopen(file.c_str(), "rb"); - if (!fp) - return false; - - // Simple filetype verification - fread(&header.ident, 4, 1, fp); - if (header.ident[0] != 'I' || header.ident[1] != 'D' || header.ident[2] != 'P' || header.ident[3] != '2') - { - fclose(fp); - return false; - } - fread(&header.version, 4, 1, fp); - if (header.version != 8) - { - fclose(fp); - return false; - } - - Release(); - - // Read rest of the MD2 header - fread(&header.skinWidth, 4, 1, fp); - fread(&header.skinHeight, 4, 1, fp); - fread(&header.frameSize, 4, 1, fp); - fread(&header.numSkins, 4, 1, fp); - fread(&header.numVertices, 4, 1, fp); - fread(&header.numTexCoords, 4, 1, fp); - fread(&header.numPolys, 4, 1, fp); - fread(&header.numGlCmds, 4, 1, fp); - fread(&header.numFrames, 4, 1, fp); - fread(&header.offsetSkins, 4, 1, fp); - fread(&header.offsetTexCoords, 4, 1, fp); - fread(&header.offsetPolys, 4, 1, fp); - fread(&header.offsetFrames, 4, 1, fp); - fread(&header.offsetGlCmds, 4, 1, fp); - fread(&header.offsetEnd, 4, 1, fp); - - // Allocate memory - if (header.numSkins > 0) - { - m_skins = new std::string[header.numSkins]; - //ASSERT(m_skins != NULL); - } - m_texCoords = new Vector2[header.numTexCoords]; - m_polys = new Md2Polygon[header.numPolys]; - m_frames = new Md2Frame[header.numFrames]; - - //ASSERT(m_texCoords != NULL); - //ASSERT(m_polys != NULL); - //ASSERT(m_frames != NULL); - - // Save model properties - m_numFrames = header.numFrames; - m_numPolys = header.numPolys; - m_numSkins = header.numSkins; - m_numTexCoords = header.numTexCoords; - m_numVertices = header.numVertices; - - // Read skin info - fseek(fp, header.offsetSkins, SEEK_SET); - for (int i = 0; i < header.numSkins; ++i) - { - // Not wasting the full 64 characters stored in the file here - for (int j = 0; j < MD2_SKIN_NAME_LENGTH; ++j) - { - fread(&c, 1, 1, fp); - if (!c) - { - fseek(fp, MD2_SKIN_NAME_LENGTH - j - 1, SEEK_CUR); - break; - } - else - m_skins[i].append(1, c); - } - } - - // Read texture coordinates - fseek(fp, header.offsetTexCoords, SEEK_SET); - for (int i = 0; i < header.numTexCoords; ++i) - { - fread(&u, 2, 1, fp); - fread(&v, 2, 1, fp); - m_texCoords[i].x = u / (float)header.skinWidth; - m_texCoords[i].y = v / (float)header.skinHeight; - } - - // Read polygons (this is all just indexes into m_texCoords and m_frames[].vertices) - fseek(fp, header.offsetPolys, SEEK_SET); - for (int i = 0; i < header.numPolys; ++i) - { - fread(&t, 2, 1, fp); - m_polys[i].vertex[0] = t; - fread(&t, 2, 1, fp); - m_polys[i].vertex[2] = t; - fread(&t, 2, 1, fp); - m_polys[i].vertex[1] = t; - - // HACK: Not sure why some of these indexes are invalid? This seems to fix the problem - fread(&t, 2, 1, fp); - m_polys[i].texCoord[0] = (t == 65535 ? 0 : t); - fread(&t, 2, 1, fp); - m_polys[i].texCoord[2] = (t == 65535 ? 0 : t); - fread(&t, 2, 1, fp); - m_polys[i].texCoord[1] = (t == 65535 ? 0 : t); - } - - // Read frames - fseek(fp, header.offsetFrames, SEEK_SET); - for (int i = 0; i < header.numFrames; ++i) - { - // Allocate enough memory for this frame's vertex/normal indexes - m_frames[i].vertices = new Vector3[header.numVertices]; - //m_frames[i].normals = new Vector3[header.numPolys]; - m_frames[i].normals = new Vector3[header.numVertices]; - //ASSERT(m_frames[i].vertices != NULL); - //ASSERT(m_frames[i].normals != NULL); - - fread(&scale.x, 4, 1, fp); - fread(&scale.y, 4, 1, fp); - fread(&scale.z, 4, 1, fp); - - fread(&translate.x, 4, 1, fp); - fread(&translate.y, 4, 1, fp); - fread(&translate.z, 4, 1, fp); - - // Store the text name of the frame (we won't waste the full 16 characters - // reserved in the file here) - for (int j = 0; j < MD2_FRAME_NAME_LENGTH; ++j) - { - fread(&c, 1, 1, fp); - if (!c) - { - fseek(fp, MD2_FRAME_NAME_LENGTH - j - 1, SEEK_CUR); - break; - } - else - m_frames[i].name += c; - } - - // Read vertices, and decompress as we load them for performance when rendering - for (int j = 0; j < header.numVertices; ++j) - { - fread(&c, 1, 1, fp); - x = (float)c; - fread(&c, 1, 1, fp); - y = (float)c; - fread(&c, 1, 1, fp); - z = (float)c; - - // Convert to OpenGL's coordinate system, otherwise models will need to be rotated to be drawn upright - m_frames[i].vertices[j].x = (x * scale.x) + translate.x; - m_frames[i].vertices[j].y = (z * scale.z) + translate.z; - m_frames[i].vertices[j].z = -1.0f * ((y * scale.y) + translate.y); - - fread(&c, 1, 1, fp); // Dummy command to increment file pointer (we don't care about the normal index) - } - - //m_frameMap[m_frames[i].name] = i; - } - - fclose(fp); - - // Cleanup and finishing touches. - // Vertex coordinates, as of now, are waaay out of range (most likely, unless the model is tiny). - // We could've scaled them down above while reading them in, but I noticed issues calculating normals - // when that was done (probably due to lacking precision). So, we calculate the normals using the - // un-touched coordinates (get the most accurate normal calc that way), then scale the vertex down. - for (int i = 0; i < header.numFrames; ++i) - { - // Calculate vertex normals - Vector3 sumNormal; - int sum; - for (int j = 0; j < header.numVertices; ++j) - { - sum = 0; - sumNormal = Vector3(0, 0, 0); - for (int k = 0; k < header.numPolys; ++k) - { - if (m_polys[k].vertex[0] == j || m_polys[k].vertex[1] == j || m_polys[k].vertex[2] == j) - { - ++sum; - sumNormal += Vector3::SurfaceNormal(m_frames[i].vertices[m_polys[k].vertex[0]], - m_frames[i].vertices[m_polys[k].vertex[1]], - m_frames[i].vertices[m_polys[k].vertex[2]]); - } - } - m_frames[i].normals[j] = sumNormal / (float)sum; - } - - //// Done, now scale the vertices down - //for (int j = 0; j < header.numVertices; ++j) - //{ - // m_frames[i].vertices[j] /= (float)(MD2_SCALE_FACTOR); - //} - } - - // 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()); - - Md2Animation *animation = new Md2Animation(); - animation->name = name; - animation->startFrame = start; - animation->endFrame = end; - m_animations.push_back(*animation); - } - } - delete[] buffer; - - fclose(fp); - } - - return true; -} - -bool Md2::ConvertToMesh(const std::string &file) -{ - FILE *fp = fopen(file.c_str(), "wb"); - if (fp == NULL) - return false; - - - WriteFileHeader(fp); - - KeyFramesChunk *keyFramesChunk = new KeyFramesChunk(); - keyFramesChunk->numVertices = m_numVertices; - for (long i = 0; i < m_numFrames; ++i) - { - KeyFrame *frame = keyFramesChunk->AddFrame(); - - for (int j = 0; j < m_numVertices; ++j) - frame->vertices[j] = m_frames[i].vertices[j]; - - for (int j = 0; j < m_numVertices; ++j) - frame->normals[j] = m_frames[i].normals[j]; - } - WriteChunk(keyFramesChunk, fp); - - TexCoordsChunk *texCoordsChunk = new TexCoordsChunk(); - for (long i = 0; i < m_numTexCoords; ++i) - texCoordsChunk->texCoords.push_back(m_texCoords[i]); - WriteChunk(texCoordsChunk, fp); - - KeyFrameTrianglesChunk *trianglesChunk = new KeyFrameTrianglesChunk(); - for (long i = 0; i < m_numPolys; ++i) - { - KeyFrameTriangle t; - - t.vertices[0] = m_polys[i].vertex[0]; - t.vertices[1] = m_polys[i].vertex[1]; - t.vertices[2] = m_polys[i].vertex[2]; - - t.texCoords[0] = m_polys[i].texCoord[0]; - t.texCoords[1] = m_polys[i].texCoord[1]; - t.texCoords[2] = m_polys[i].texCoord[2]; - - trianglesChunk->triangles.push_back(t); - } - WriteChunk(trianglesChunk, fp); - - if (m_animations.size() > 0) - { - AnimationsChunk *animationsChunk = new AnimationsChunk(); - for (long i = 0; i < m_animations.size(); ++i) - { - AnimationSequence a; - - a.name = m_animations[i].name; - a.start = m_animations[i].startFrame; - a.end = m_animations[i].endFrame; - - animationsChunk->animations.push_back(a); - } - WriteChunk(animationsChunk, fp); - } - - fclose(fp); - return true; -} +#include "md2.h" + +#include +#include "../chunks/chunks.h" + +Md2::Md2() +{ + m_numFrames = 0; + m_numPolys = 0; + m_numTexCoords = 0; + m_numVertices = 0; + m_numSkins = 0; + m_frames = NULL; + m_polys = NULL; + m_texCoords = NULL; + m_skins = NULL; +} + +void Md2::Release() +{ + delete[] m_frames; + delete[] m_polys; + delete[] m_texCoords; + delete[] m_skins; + m_numFrames = 0; + m_numPolys = 0; + m_numTexCoords = 0; + m_numVertices = 0; + m_numSkins = 0; + m_frames = NULL; + m_polys = NULL; + m_texCoords = NULL; + m_skins = NULL; +} + +bool Md2::Load(const std::string &file) +{ + FILE *fp; + unsigned char c; + unsigned short u, v, t; + float x, y, z; + Md2Header header; + Vector3 scale, translate; + + fp = fopen(file.c_str(), "rb"); + if (!fp) + return false; + + // Simple filetype verification + fread(&header.ident, 4, 1, fp); + if (header.ident[0] != 'I' || header.ident[1] != 'D' || header.ident[2] != 'P' || header.ident[3] != '2') + { + fclose(fp); + return false; + } + fread(&header.version, 4, 1, fp); + if (header.version != 8) + { + fclose(fp); + return false; + } + + Release(); + + // Read rest of the MD2 header + fread(&header.skinWidth, 4, 1, fp); + fread(&header.skinHeight, 4, 1, fp); + fread(&header.frameSize, 4, 1, fp); + fread(&header.numSkins, 4, 1, fp); + fread(&header.numVertices, 4, 1, fp); + fread(&header.numTexCoords, 4, 1, fp); + fread(&header.numPolys, 4, 1, fp); + fread(&header.numGlCmds, 4, 1, fp); + fread(&header.numFrames, 4, 1, fp); + fread(&header.offsetSkins, 4, 1, fp); + fread(&header.offsetTexCoords, 4, 1, fp); + fread(&header.offsetPolys, 4, 1, fp); + fread(&header.offsetFrames, 4, 1, fp); + fread(&header.offsetGlCmds, 4, 1, fp); + fread(&header.offsetEnd, 4, 1, fp); + + // Allocate memory + if (header.numSkins > 0) + { + m_skins = new std::string[header.numSkins]; + //ASSERT(m_skins != NULL); + } + m_texCoords = new Vector2[header.numTexCoords]; + m_polys = new Md2Polygon[header.numPolys]; + m_frames = new Md2Frame[header.numFrames]; + + //ASSERT(m_texCoords != NULL); + //ASSERT(m_polys != NULL); + //ASSERT(m_frames != NULL); + + // Save model properties + m_numFrames = header.numFrames; + m_numPolys = header.numPolys; + m_numSkins = header.numSkins; + m_numTexCoords = header.numTexCoords; + m_numVertices = header.numVertices; + + // Read skin info + fseek(fp, header.offsetSkins, SEEK_SET); + for (int i = 0; i < header.numSkins; ++i) + { + // Not wasting the full 64 characters stored in the file here + for (int j = 0; j < MD2_SKIN_NAME_LENGTH; ++j) + { + fread(&c, 1, 1, fp); + if (!c) + { + fseek(fp, MD2_SKIN_NAME_LENGTH - j - 1, SEEK_CUR); + break; + } + else + m_skins[i].append(1, c); + } + } + + // Read texture coordinates + fseek(fp, header.offsetTexCoords, SEEK_SET); + for (int i = 0; i < header.numTexCoords; ++i) + { + fread(&u, 2, 1, fp); + fread(&v, 2, 1, fp); + m_texCoords[i].x = u / (float)header.skinWidth; + m_texCoords[i].y = v / (float)header.skinHeight; + } + + // Read polygons (this is all just indexes into m_texCoords and m_frames[].vertices) + fseek(fp, header.offsetPolys, SEEK_SET); + for (int i = 0; i < header.numPolys; ++i) + { + fread(&t, 2, 1, fp); + m_polys[i].vertex[0] = t; + fread(&t, 2, 1, fp); + m_polys[i].vertex[2] = t; + fread(&t, 2, 1, fp); + m_polys[i].vertex[1] = t; + + // HACK: Not sure why some of these indexes are invalid? This seems to fix the problem + fread(&t, 2, 1, fp); + m_polys[i].texCoord[0] = (t == 65535 ? 0 : t); + fread(&t, 2, 1, fp); + m_polys[i].texCoord[2] = (t == 65535 ? 0 : t); + fread(&t, 2, 1, fp); + m_polys[i].texCoord[1] = (t == 65535 ? 0 : t); + } + + // Read frames + fseek(fp, header.offsetFrames, SEEK_SET); + for (int i = 0; i < header.numFrames; ++i) + { + // Allocate enough memory for this frame's vertex/normal indexes + m_frames[i].vertices = new Vector3[header.numVertices]; + //m_frames[i].normals = new Vector3[header.numPolys]; + m_frames[i].normals = new Vector3[header.numVertices]; + //ASSERT(m_frames[i].vertices != NULL); + //ASSERT(m_frames[i].normals != NULL); + + fread(&scale.x, 4, 1, fp); + fread(&scale.y, 4, 1, fp); + fread(&scale.z, 4, 1, fp); + + fread(&translate.x, 4, 1, fp); + fread(&translate.y, 4, 1, fp); + fread(&translate.z, 4, 1, fp); + + // Store the text name of the frame (we won't waste the full 16 characters + // reserved in the file here) + for (int j = 0; j < MD2_FRAME_NAME_LENGTH; ++j) + { + fread(&c, 1, 1, fp); + if (!c) + { + fseek(fp, MD2_FRAME_NAME_LENGTH - j - 1, SEEK_CUR); + break; + } + else + m_frames[i].name += c; + } + + // Read vertices, and decompress as we load them for performance when rendering + for (int j = 0; j < header.numVertices; ++j) + { + fread(&c, 1, 1, fp); + x = (float)c; + fread(&c, 1, 1, fp); + y = (float)c; + fread(&c, 1, 1, fp); + z = (float)c; + + // Convert to OpenGL's coordinate system, otherwise models will need to be rotated to be drawn upright + m_frames[i].vertices[j].x = (x * scale.x) + translate.x; + m_frames[i].vertices[j].y = (z * scale.z) + translate.z; + m_frames[i].vertices[j].z = -1.0f * ((y * scale.y) + translate.y); + + fread(&c, 1, 1, fp); // Dummy command to increment file pointer (we don't care about the normal index) + } + + //m_frameMap[m_frames[i].name] = i; + } + + fclose(fp); + + // Cleanup and finishing touches. + // Vertex coordinates, as of now, are waaay out of range (most likely, unless the model is tiny). + // We could've scaled them down above while reading them in, but I noticed issues calculating normals + // when that was done (probably due to lacking precision). So, we calculate the normals using the + // un-touched coordinates (get the most accurate normal calc that way), then scale the vertex down. + for (int i = 0; i < header.numFrames; ++i) + { + // Calculate vertex normals + Vector3 sumNormal; + int sum; + for (int j = 0; j < header.numVertices; ++j) + { + sum = 0; + sumNormal = Vector3(0, 0, 0); + for (int k = 0; k < header.numPolys; ++k) + { + if (m_polys[k].vertex[0] == j || m_polys[k].vertex[1] == j || m_polys[k].vertex[2] == j) + { + ++sum; + sumNormal += Vector3::SurfaceNormal(m_frames[i].vertices[m_polys[k].vertex[0]], + m_frames[i].vertices[m_polys[k].vertex[1]], + m_frames[i].vertices[m_polys[k].vertex[2]]); + } + } + m_frames[i].normals[j] = sumNormal / (float)sum; + } + + //// Done, now scale the vertices down + //for (int j = 0; j < header.numVertices; ++j) + //{ + // m_frames[i].vertices[j] /= (float)(MD2_SCALE_FACTOR); + //} + } + + // 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()); + + Md2Animation *animation = new Md2Animation(); + animation->name = name; + animation->startFrame = start; + animation->endFrame = end; + m_animations.push_back(*animation); + } + } + delete[] buffer; + + fclose(fp); + } + + return true; +} + +bool Md2::ConvertToMesh(const std::string &file) +{ + FILE *fp = fopen(file.c_str(), "wb"); + if (fp == NULL) + return false; + + + WriteFileHeader(fp); + + KeyFramesChunk *keyFramesChunk = new KeyFramesChunk(); + keyFramesChunk->numVertices = m_numVertices; + for (long i = 0; i < m_numFrames; ++i) + { + KeyFrame *frame = keyFramesChunk->AddFrame(); + + for (int j = 0; j < m_numVertices; ++j) + frame->vertices[j] = m_frames[i].vertices[j]; + + for (int j = 0; j < m_numVertices; ++j) + frame->normals[j] = m_frames[i].normals[j]; + } + WriteChunk(keyFramesChunk, fp); + + TexCoordsChunk *texCoordsChunk = new TexCoordsChunk(); + for (long i = 0; i < m_numTexCoords; ++i) + texCoordsChunk->texCoords.push_back(m_texCoords[i]); + WriteChunk(texCoordsChunk, fp); + + KeyFrameTrianglesChunk *trianglesChunk = new KeyFrameTrianglesChunk(); + for (long i = 0; i < m_numPolys; ++i) + { + KeyFrameTriangle t; + + t.vertices[0] = m_polys[i].vertex[0]; + t.vertices[1] = m_polys[i].vertex[1]; + t.vertices[2] = m_polys[i].vertex[2]; + + t.texCoords[0] = m_polys[i].texCoord[0]; + t.texCoords[1] = m_polys[i].texCoord[1]; + t.texCoords[2] = m_polys[i].texCoord[2]; + + trianglesChunk->triangles.push_back(t); + } + WriteChunk(trianglesChunk, fp); + + if (m_animations.size() > 0) + { + AnimationsChunk *animationsChunk = new AnimationsChunk(); + for (long i = 0; i < m_animations.size(); ++i) + { + AnimationSequence a; + + a.name = m_animations[i].name; + a.start = m_animations[i].startFrame; + a.end = m_animations[i].endFrame; + + animationsChunk->animations.push_back(a); + } + WriteChunk(animationsChunk, fp); + } + + fclose(fp); + return true; +} diff --git a/MeshConverter/src/md2/md2.h b/MeshConverter/src/md2/md2.h index 81e7e2a..fa19d7d 100644 --- a/MeshConverter/src/md2/md2.h +++ b/MeshConverter/src/md2/md2.h @@ -1,100 +1,100 @@ -#ifndef __MD2_H_INCLUDED__ -#define __MD2_H_INCLUDED__ - -#include "../geometry/vector3.h" -#include "../geometry/vector2.h" - -#include -#include - -#define MD2_SKIN_NAME_LENGTH 64 -#define MD2_FRAME_NAME_LENGTH 16 - -typedef struct -{ - char ident[4]; // Should be "IDP2" - int version; // Should be 8 - int skinWidth; // Texture dimensions - int skinHeight; - int frameSize; // Size of a single frame in bytes - int numSkins; - int numVertices; - int numTexCoords; - int numPolys; - int numGlCmds; - int numFrames; - int offsetSkins; - int offsetTexCoords; - int offsetPolys; - int offsetFrames; - int offsetGlCmds; - int offsetEnd; -} Md2Header; - -// Vertex and texcoord indices -typedef struct -{ - unsigned short vertex[3]; - unsigned short texCoord[3]; -} Md2Polygon; - -// For each keyframe, stores the vertices, normals, and the string name -typedef struct Md2Frame -{ - std::string name; - Vector3 *vertices; - Vector3 *normals; - - Md2Frame() - { - vertices = NULL; - normals = NULL; - } - - ~Md2Frame() - { - delete[] vertices; - delete[] normals; - } -} Md2Frame; - -typedef struct -{ - std::string name; - unsigned int startFrame; - unsigned int endFrame; -} Md2Animation; - -class Md2 -{ -public: - Md2(); - virtual ~Md2() { Release(); } - - void Release(); - bool Load(const std::string &file); - bool ConvertToMesh(const std::string &file); - - int GetNumFrames() { return m_numFrames; } - int GetNumVertices() { return m_numVertices; } - int GetNumTexCoords() { return m_numTexCoords; } - int GetNumPolys() { return m_numPolys; } - int GetNumSkins() { return m_numSkins; } - Md2Frame* GetFrames() { return m_frames; } - Md2Polygon* GetPolygons() { return m_polys; } - Vector2* GetTexCoords() { return m_texCoords; } - -private: - int m_numFrames; - int m_numVertices; - int m_numTexCoords; - int m_numPolys; - int m_numSkins; - Md2Frame *m_frames; - Md2Polygon *m_polys; - Vector2 *m_texCoords; - std::string *m_skins; - std::vector m_animations; -}; - +#ifndef __MD2_H_INCLUDED__ +#define __MD2_H_INCLUDED__ + +#include "../geometry/vector3.h" +#include "../geometry/vector2.h" + +#include +#include + +#define MD2_SKIN_NAME_LENGTH 64 +#define MD2_FRAME_NAME_LENGTH 16 + +typedef struct +{ + char ident[4]; // Should be "IDP2" + int version; // Should be 8 + int skinWidth; // Texture dimensions + int skinHeight; + int frameSize; // Size of a single frame in bytes + int numSkins; + int numVertices; + int numTexCoords; + int numPolys; + int numGlCmds; + int numFrames; + int offsetSkins; + int offsetTexCoords; + int offsetPolys; + int offsetFrames; + int offsetGlCmds; + int offsetEnd; +} Md2Header; + +// Vertex and texcoord indices +typedef struct +{ + unsigned short vertex[3]; + unsigned short texCoord[3]; +} Md2Polygon; + +// For each keyframe, stores the vertices, normals, and the string name +typedef struct Md2Frame +{ + std::string name; + Vector3 *vertices; + Vector3 *normals; + + Md2Frame() + { + vertices = NULL; + normals = NULL; + } + + ~Md2Frame() + { + delete[] vertices; + delete[] normals; + } +} Md2Frame; + +typedef struct +{ + std::string name; + unsigned int startFrame; + unsigned int endFrame; +} Md2Animation; + +class Md2 +{ +public: + Md2(); + virtual ~Md2() { Release(); } + + void Release(); + bool Load(const std::string &file); + bool ConvertToMesh(const std::string &file); + + int GetNumFrames() { return m_numFrames; } + int GetNumVertices() { return m_numVertices; } + int GetNumTexCoords() { return m_numTexCoords; } + int GetNumPolys() { return m_numPolys; } + int GetNumSkins() { return m_numSkins; } + Md2Frame* GetFrames() { return m_frames; } + Md2Polygon* GetPolygons() { return m_polys; } + Vector2* GetTexCoords() { return m_texCoords; } + +private: + int m_numFrames; + int m_numVertices; + int m_numTexCoords; + int m_numPolys; + int m_numSkins; + Md2Frame *m_frames; + Md2Polygon *m_polys; + Vector2 *m_texCoords; + std::string *m_skins; + std::vector m_animations; +}; + #endif \ No newline at end of file diff --git a/MeshConverter/src/ms3d/ms3d.cpp b/MeshConverter/src/ms3d/ms3d.cpp index 6b78ad2..7f2a6e6 100644 --- a/MeshConverter/src/ms3d/ms3d.cpp +++ b/MeshConverter/src/ms3d/ms3d.cpp @@ -1,435 +1,435 @@ -#include "ms3d.h" - -#include - -#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; -} +#include "ms3d.h" + +#include + +#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; +} diff --git a/MeshConverter/src/ms3d/ms3d.h b/MeshConverter/src/ms3d/ms3d.h index c52b5e1..d6c85b0 100644 --- a/MeshConverter/src/ms3d/ms3d.h +++ b/MeshConverter/src/ms3d/ms3d.h @@ -1,146 +1,146 @@ -#ifndef __MS3D_H_INCLUDED__ -#define __MS3D_H_INCLUDED__ - -#include -#include "../geometry/vector3.h" -#include "../geometry/vector2.h" -#include - -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 m_animations; -}; - -#endif +#ifndef __MS3D_H_INCLUDED__ +#define __MS3D_H_INCLUDED__ + +#include +#include "../geometry/vector3.h" +#include "../geometry/vector2.h" +#include + +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 m_animations; +}; + +#endif diff --git a/MeshConverter/src/obj/obj.cpp b/MeshConverter/src/obj/obj.cpp index f3a9b54..82701af 100644 --- a/MeshConverter/src/obj/obj.cpp +++ b/MeshConverter/src/obj/obj.cpp @@ -1,496 +1,496 @@ -#include "obj.h" - -#include -#include -#include - -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]); - 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->SetAmbient(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->SetDiffuse(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->SetSpecular(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->SetTexture(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; - int count = 0; - - 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; -} +#include "obj.h" + +#include +#include +#include + +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]); + 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->SetAmbient(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->SetDiffuse(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->SetSpecular(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->SetTexture(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; + int count = 0; + + 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; +} diff --git a/MeshConverter/src/obj/obj.h b/MeshConverter/src/obj/obj.h index a1c7387..7d3144b 100644 --- a/MeshConverter/src/obj/obj.h +++ b/MeshConverter/src/obj/obj.h @@ -1,84 +1,84 @@ -#ifndef __OBJ_H_INCLUDED__ -#define __OBJ_H_INCLUDED__ - -#include "../geometry/vector3.h" -#include "../geometry/vector2.h" -#include "../assets/material.h" - -#include - -typedef enum OBJ_FACE_VERTEX_TYPE -{ - OBJ_VERTEX_TEXCOORD, - OBJ_VERTEX_NORMAL, - OBJ_VERTEX_FULL -}; - -typedef struct -{ - unsigned int vertices[3]; - unsigned int texcoords[3]; - unsigned int normals[3]; -} ObjFace; - -typedef 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; - } -} ObjMaterial; - -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; - -}; - +#ifndef __OBJ_H_INCLUDED__ +#define __OBJ_H_INCLUDED__ + +#include "../geometry/vector3.h" +#include "../geometry/vector2.h" +#include "../assets/material.h" + +#include + +typedef enum OBJ_FACE_VERTEX_TYPE +{ + OBJ_VERTEX_TEXCOORD, + OBJ_VERTEX_NORMAL, + OBJ_VERTEX_FULL +}; + +typedef struct +{ + unsigned int vertices[3]; + unsigned int texcoords[3]; + unsigned int normals[3]; +} ObjFace; + +typedef 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; + } +} ObjMaterial; + +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 \ No newline at end of file diff --git a/MeshConverter/src/sm/sm.cpp b/MeshConverter/src/sm/sm.cpp index 8232803..8906cc6 100644 --- a/MeshConverter/src/sm/sm.cpp +++ b/MeshConverter/src/sm/sm.cpp @@ -1,261 +1,261 @@ -#include "sm.h" - -#include -#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; - int count; - float x, y, z; - unsigned char header[2]; - unsigned char c; - 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; -} +#include "sm.h" + +#include +#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; + int count; + float x, y, z; + unsigned char header[2]; + unsigned char c; + 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; +} diff --git a/MeshConverter/src/sm/sm.h b/MeshConverter/src/sm/sm.h index ade4af7..6d89e23 100644 --- a/MeshConverter/src/sm/sm.h +++ b/MeshConverter/src/sm/sm.h @@ -1,73 +1,73 @@ -#ifndef __SM_H_INCLUDED__ -#define __SM_H_INCLUDED__ - -#include "../assets/material.h" -#include "../geometry/vector3.h" -#include "../geometry/vector2.h" -#include - - -typedef struct -{ - unsigned int vertices[3]; - unsigned int normals[3]; - unsigned int texcoords[3]; - unsigned short colors[3]; - short material; -} SmPolygon; - -typedef struct SmMaterial -{ - Material *material; - unsigned int polyStart; - unsigned int polyEnd; - - SmMaterial() - { - material = new Material(); - polyStart = 0; - polyEnd = 0; - }; - - ~SmMaterial() - { - delete material; - } -} SmMaterial; - -#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; -}; - +#ifndef __SM_H_INCLUDED__ +#define __SM_H_INCLUDED__ + +#include "../assets/material.h" +#include "../geometry/vector3.h" +#include "../geometry/vector2.h" +#include + + +typedef struct +{ + unsigned int vertices[3]; + unsigned int normals[3]; + unsigned int texcoords[3]; + unsigned short colors[3]; + short material; +} SmPolygon; + +typedef struct SmMaterial +{ + Material *material; + unsigned int polyStart; + unsigned int polyEnd; + + SmMaterial() + { + material = new Material(); + polyStart = 0; + polyEnd = 0; + }; + + ~SmMaterial() + { + delete material; + } +} SmMaterial; + +#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 \ No newline at end of file diff --git a/MeshConverter/src/util/files.cpp b/MeshConverter/src/util/files.cpp index 52bcd5c..38253dc 100644 --- a/MeshConverter/src/util/files.cpp +++ b/MeshConverter/src/util/files.cpp @@ -1,25 +1,25 @@ -#include "files.h" - -void ReadString(FILE *fp, std::string &buffer, int fixedLength) -{ - char c; - - if (fixedLength > 0) - { - for (int i = 0; i < fixedLength; ++i) - { - fread(&c, 1, 1, fp); - if (c != '\0') - buffer += c; - } - } - else - { - do - { - fread(&c, 1, 1, fp); - if (c != '\0') - buffer += c; - } while (c != '\0'); - } -} +#include "files.h" + +void ReadString(FILE *fp, std::string &buffer, int fixedLength) +{ + char c; + + if (fixedLength > 0) + { + for (int i = 0; i < fixedLength; ++i) + { + fread(&c, 1, 1, fp); + if (c != '\0') + buffer += c; + } + } + else + { + do + { + fread(&c, 1, 1, fp); + if (c != '\0') + buffer += c; + } while (c != '\0'); + } +} diff --git a/MeshConverter/src/util/files.h b/MeshConverter/src/util/files.h index 4c79e99..6ad1d72 100644 --- a/MeshConverter/src/util/files.h +++ b/MeshConverter/src/util/files.h @@ -1,9 +1,9 @@ -#ifndef __UTIL_FILES_H_INCLUDED__ -#define __UTIL_FILES_H_INCLUDED__ - -#include -#include - -void ReadString(FILE *fp, std::string &buffer, int fixedLength = 0); - -#endif +#ifndef __UTIL_FILES_H_INCLUDED__ +#define __UTIL_FILES_H_INCLUDED__ + +#include +#include + +void ReadString(FILE *fp, std::string &buffer, int fixedLength = 0); + +#endif