1
// Copyright (C) 2010-2011 Gaz Davidson / Joseph Ellis
2
// This file is part of the "Irrlicht Engine".
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
5
#include "IrrCompileConfig.h"
7
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
9
#include "CSMFMeshFileLoader.h"
10
#include "SAnimatedMesh.h"
11
#include "SMeshBuffer.h"
12
#include "IReadFile.h"
15
#include "IVideoDriver.h"
22
CSMFMeshFileLoader::CSMFMeshFileLoader(video::IVideoDriver* driver)
27
//! Returns true if the file might be loaded by this class.
28
bool CSMFMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
30
return core::hasFileExtension(filename, "smf");
33
//! Creates/loads an animated mesh from the file.
34
IAnimatedMesh* CSMFMeshFileLoader::createMesh(io::IReadFile* file)
37
SMesh *mesh = new SMesh();
45
io::BinaryFile::read(file, version);
46
io::BinaryFile::read(file, flags);
47
io::BinaryFile::read(file, limbCount);
50
core::matrix4 identity;
51
for (i=0; i < limbCount; ++i)
52
loadLimb(file, mesh, identity);
54
// recalculate buffer bounding boxes
55
for (i=0; i < (s32)mesh->getMeshBufferCount(); ++i)
56
mesh->getMeshBuffer(i)->recalculateBoundingBox();
58
mesh->recalculateBoundingBox();
59
SAnimatedMesh *am = new SAnimatedMesh();
62
am->recalculateBoundingBox();
67
void CSMFMeshFileLoader::loadLimb(io::IReadFile* file, SMesh* mesh, const core::matrix4 &parentTransformation)
69
core::matrix4 transformation;
71
// limb transformation
72
core::vector3df translate, rotate, scale;
73
io::BinaryFile::read(file, translate);
74
io::BinaryFile::read(file, rotate);
75
io::BinaryFile::read(file, scale);
77
transformation.setTranslation(translate);
78
transformation.setRotationDegrees(rotate);
79
transformation.setScale(scale);
81
transformation = parentTransformation * transformation;
83
core::stringc textureName, textureGroupName;
85
// texture information
86
io::BinaryFile::read(file, textureGroupName);
87
io::BinaryFile::read(file, textureName);
89
// attempt to load texture using known formats
90
video::ITexture* texture = 0;
92
const c8* extensions[] = {".jpg", ".png", ".tga", ".bmp", 0};
94
for (const c8 **ext = extensions; !texture && *ext; ++ext)
96
texture = Driver->getTexture(textureName + *ext);
98
textureName = textureName + *ext;
100
// find the correct mesh buffer
102
for (i=0; i<mesh->MeshBuffers.size(); ++i)
103
if (mesh->MeshBuffers[i]->getMaterial().TextureLayer[0].Texture == texture)
106
// create mesh buffer if none was found
107
if (i == mesh->MeshBuffers.size())
109
CMeshBuffer<video::S3DVertex>* mb = new CMeshBuffer<video::S3DVertex>();
110
mb->Material.TextureLayer[0].Texture = texture;
112
// horribly hacky way to do this, maybe it's in the flags?
113
if (core::hasFileExtension(textureName, "tga", "png"))
114
mb->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
116
mb->Material.MaterialType = video::EMT_SOLID;
118
mesh->MeshBuffers.push_back(mb);
121
CMeshBuffer<video::S3DVertex>* mb = (CMeshBuffer<video::S3DVertex>*)mesh->MeshBuffers[i];
123
u16 vertexCount, firstVertex = mb->getVertexCount();
125
io::BinaryFile::read(file, vertexCount);
126
mb->Vertices.reallocate(mb->Vertices.size() + vertexCount);
128
// add vertices and set positions
129
for (i=0; i<vertexCount; ++i)
132
io::BinaryFile::read(file, pos);
133
transformation.transformVect(pos);
134
video::S3DVertex vert;
135
vert.Color = 0xFFFFFFFF;
137
mb->Vertices.push_back(vert);
140
// set vertex normals
141
for (i=0; i < vertexCount; ++i)
143
core::vector3df normal;
144
io::BinaryFile::read(file, normal);
145
transformation.rotateVect(normal);
146
mb->Vertices[firstVertex + i].Normal = normal;
148
// set texture coordinates
150
for (i=0; i < vertexCount; ++i)
152
core::vector2df tcoords;
153
io::BinaryFile::read(file, tcoords);
154
mb->Vertices[firstVertex + i].TCoords = tcoords;
159
// vertexCount used as temporary
160
io::BinaryFile::read(file, vertexCount);
161
triangleCount=3*vertexCount;
162
mb->Indices.reallocate(mb->Indices.size() + triangleCount);
164
for (i=0; i < triangleCount; ++i)
167
io::BinaryFile::read(file, index);
168
mb->Indices.push_back(firstVertex + index);
173
io::BinaryFile::read(file, limbCount);
175
for (s32 l=0; l < limbCount; ++l)
176
loadLimb(file, mesh, transformation);
181
// todo: at some point in the future let's move these to a place where everyone can use them.
186
#define _SYSTEM_BIG_ENDIAN_ (true)
188
#define _SYSTEM_BIG_ENDIAN_ (false)
192
void BinaryFile::read(io::IReadFile* file, T &out, bool bigEndian)
194
file->read((void*)&out, sizeof(out));
195
if (bigEndian != (_SYSTEM_BIG_ENDIAN_))
196
out = os::Byteswap::byteswap(out);
199
//! reads a 3d vector from the file, moving the file pointer along
200
void BinaryFile::read(io::IReadFile* file, core::vector3df &outVector2d, bool bigEndian)
202
BinaryFile::read(file, outVector2d.X, bigEndian);
203
BinaryFile::read(file, outVector2d.Y, bigEndian);
204
BinaryFile::read(file, outVector2d.Z, bigEndian);
207
//! reads a 2d vector from the file, moving the file pointer along
208
void BinaryFile::read(io::IReadFile* file, core::vector2df &outVector2d, bool bigEndian)
210
BinaryFile::read(file, outVector2d.X, bigEndian);
211
BinaryFile::read(file, outVector2d.Y, bigEndian);
214
//! reads a null terminated string from the file, moving the file pointer along
215
void BinaryFile::read(io::IReadFile* file, core::stringc &outString, bool bigEndian)
218
file->read((void*)&c, 1);
223
file->read((void*)&c, 1);
231
#endif // compile with SMF loader