OgreImporter: Implement Ogre binary mesh support (.mesh). All Ogre3D SDK media samples tested to work. Assimp repo does not yet have binary versions of Ogre meshes.

pull/280/head
Jonne Nauha 2014-05-18 11:57:44 +03:00
parent 36c08a0a7d
commit 4b16b182be
13 changed files with 2424 additions and 94 deletions

View File

@ -322,8 +322,14 @@ SOURCE_GROUP( Obj FILES ${Obj_SRCS})
SET( Ogre_SRCS SET( Ogre_SRCS
OgreImporter.h OgreImporter.h
OgreStructs.h
OgreParsingUtils.h OgreParsingUtils.h
OgreBinarySerializer.h
OgreXmlSerializer.h
OgreImporter.cpp OgreImporter.cpp
OgreStructs.cpp
OgreBinarySerializer.cpp
OgreXmlSerializer.cpp
OgreMaterial.cpp OgreMaterial.cpp
OgreMesh.cpp OgreMesh.cpp
OgreSkeleton.cpp OgreSkeleton.cpp

View File

@ -0,0 +1,759 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#include "OgreBinarySerializer.h"
#include "TinyFormatter.h"
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
namespace Assimp
{
namespace Ogre
{
const std::string VERSION_1_8 = "[MeshSerializer_v1.8]";
const unsigned short HEADER_CHUNK_ID = 0x1000;
const long MSTREAM_OVERHEAD_SIZE = sizeof(uint16_t) + sizeof(uint32_t);
template<>
inline bool OgreBinarySerializer::Read<bool>()
{
return (m_reader->GetU1() > 0);
}
template<>
inline char OgreBinarySerializer::Read<char>()
{
return static_cast<char>(m_reader->GetU1());
}
template<>
inline uint8_t OgreBinarySerializer::Read<uint8_t>()
{
return m_reader->GetU1();
}
template<>
inline uint16_t OgreBinarySerializer::Read<uint16_t>()
{
return m_reader->GetU2();
}
template<>
inline uint32_t OgreBinarySerializer::Read<uint32_t>()
{
return m_reader->GetU4();
}
template<>
inline float OgreBinarySerializer::Read<float>()
{
return m_reader->GetF4();
}
void OgreBinarySerializer::ReadBytes(char *dest, size_t numBytes)
{
ReadBytes(static_cast<void*>(dest), numBytes);
}
void OgreBinarySerializer::ReadBytes(uint8_t *dest, size_t numBytes)
{
ReadBytes(static_cast<void*>(dest), numBytes);
}
void OgreBinarySerializer::ReadBytes(void *dest, size_t numBytes)
{
m_reader->CopyAndAdvance(dest, numBytes);
}
uint8_t *OgreBinarySerializer::ReadBytes(size_t numBytes)
{
uint8_t *bytes = new uint8_t[numBytes];
ReadBytes(bytes, numBytes);
return bytes;
}
void OgreBinarySerializer::ReadVector(aiVector3D &vec)
{
m_reader->CopyAndAdvance(&vec.x, sizeof(float)*3);
}
bool OgreBinarySerializer::AtEnd() const
{
return (m_reader->GetRemainingSize() == 0);
}
std::string OgreBinarySerializer::ReadString(size_t len)
{
std::string str;
str.resize(len);
ReadBytes(&str[0], len);
return str;
}
std::string OgreBinarySerializer::ReadLine()
{
std::string str;
while(!AtEnd())
{
char c = Read<char>();
if (c == '\n')
break;
str += c;
}
return str;
}
uint16_t OgreBinarySerializer::ReadHeader(bool readLen)
{
uint16_t id = Read<uint16_t>();
if (readLen)
m_currentLen = Read<uint32_t>();
//if (id != HEADER_CHUNK_ID)
// DefaultLogger::get()->debug(Formatter::format() << MeshHeaderToString(static_cast<MeshChunkId>(id)));
return id;
}
void OgreBinarySerializer::RollbackHeader()
{
m_reader->IncPtr(-MSTREAM_OVERHEAD_SIZE);
}
void OgreBinarySerializer::SkipBytes(size_t num)
{
m_reader->IncPtr(num);
}
Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream)
{
OgreBinarySerializer serializer(stream);
uint16_t id = serializer.ReadHeader(false);
if (id != HEADER_CHUNK_ID)
throw DeadlyExportError("Invalid Mesh file header");
/// @todo Check what we can actually support.
std::string version = serializer.ReadLine();
if (version != VERSION_1_8)
throw DeadlyExportError("Mesh version " + version + " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again.");
Mesh *mesh = new Mesh();
while (!serializer.AtEnd())
{
id = serializer.ReadHeader();
switch(id)
{
case M_MESH:
{
serializer.ReadMesh(mesh);
break;
}
}
}
return mesh;
}
void OgreBinarySerializer::ReadMesh(Mesh *mesh)
{
mesh->hasSkeletalAnimations = Read<bool>();
DefaultLogger::get()->debug(Formatter::format() << "Reading Mesh");
DefaultLogger::get()->debug(Formatter::format() << " - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false"));
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() &&
(id == M_GEOMETRY ||
id == M_SUBMESH ||
id == M_MESH_SKELETON_LINK ||
id == M_MESH_BONE_ASSIGNMENT ||
id == M_MESH_LOD ||
id == M_MESH_BOUNDS ||
id == M_SUBMESH_NAME_TABLE ||
id == M_EDGE_LISTS ||
id == M_POSES ||
id == M_ANIMATIONS ||
id == M_TABLE_EXTREMES))
{
switch(id)
{
case M_GEOMETRY:
{
mesh->sharedVertexData = new VertexData();
ReadGeometry(mesh, mesh->sharedVertexData);
break;
}
case M_SUBMESH:
ReadSubMesh(mesh);
break;
case M_MESH_SKELETON_LINK:
ReadMeshSkeletonLink(mesh);
break;
case M_MESH_BONE_ASSIGNMENT:
ReadBoneAssignment(mesh);
break;
case M_MESH_LOD:
ReadMeshLodInfo(mesh);
break;
case M_MESH_BOUNDS:
ReadMeshBounds(mesh);
break;
case M_SUBMESH_NAME_TABLE:
ReadSubMeshNames(mesh);
break;
case M_EDGE_LISTS:
ReadEdgeList(mesh);
break;
case M_POSES:
ReadPoses(mesh);
break;
case M_ANIMATIONS:
ReadAnimations(mesh);
break;
case M_TABLE_EXTREMES:
ReadMeshExtremes(mesh);
break;
}
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadMeshLodInfo(Mesh *mesh)
{
// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
// @todo Put this stuff to scene/mesh custom properties. If manual mesh the app can use the information.
ReadLine(); // strategy name
uint16_t numLods = Read<uint16_t>();
bool manual = Read<bool>();
/// @note Main mesh is considered as LOD 0, start from index 1.
for (size_t i=1; i<numLods; ++i)
{
uint16_t id = ReadHeader();
if (id != M_MESH_LOD_USAGE)
throw DeadlyImportError("M_MESH_LOD does not contain a M_MESH_LOD_USAGE for each LOD level");
m_reader->IncPtr(sizeof(float)); // user value
if (manual)
{
id = ReadHeader();
if (id != M_MESH_LOD_MANUAL)
throw DeadlyImportError("Manual M_MESH_LOD_USAGE does not contain M_MESH_LOD_MANUAL");
ReadLine(); // manual mesh name (ref to another mesh)
}
else
{
for(size_t si=0, silen=mesh->NumSubMeshes(); si<silen; ++si)
{
id = ReadHeader();
if (id != M_MESH_LOD_GENERATED)
throw DeadlyImportError("Generated M_MESH_LOD_USAGE does not contain M_MESH_LOD_GENERATED");
uint32_t indexCount = Read<uint32_t>();
bool is32bit = Read<bool>();
if (indexCount > 0)
{
uint32_t len = indexCount * (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
m_reader->IncPtr(len);
}
}
}
}
}
void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
{
mesh->skeletonRef = ReadLine();
}
void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
{
// Skip bounds, not compatible with Assimp.
// 2x float vec3 + 1x float sphere radius
SkipBytes(sizeof(float) * 7);
}
void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
{
// Skip extremes, not compatible with Assimp.
size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
SkipBytes(numBytes);
}
void OgreBinarySerializer::ReadBoneAssignment(Mesh *dest)
{
VertexBoneAssignment ba;
ba.vertexIndex = Read<uint32_t>();
ba.boneIndex = Read<uint16_t>();
ba.weight = Read<float>();
dest->boneAssignments.push_back(ba);
}
void OgreBinarySerializer::ReadBoneAssignment(SubMesh2 *dest)
{
VertexBoneAssignment ba;
ba.vertexIndex = Read<uint32_t>();
ba.boneIndex = Read<uint16_t>();
ba.weight = Read<float>();
dest->boneAssignments.push_back(ba);
}
void OgreBinarySerializer::ReadSubMesh(Mesh *mesh)
{
uint16_t id = 0;
SubMesh2 *submesh = new SubMesh2();
submesh->materialRef = ReadLine();
submesh->usesSharedVertexData = Read<bool>();
submesh->indexData->count = Read<uint32_t>();
submesh->indexData->faceCount = static_cast<uint32_t>(submesh->indexData->count / 3);
submesh->indexData->is32bit = Read<bool>();
DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
DefaultLogger::get()->debug(Formatter::format() << " - Material: '" << submesh->materialRef << "'");
DefaultLogger::get()->debug(Formatter::format() << " - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));
// Index buffer
if (submesh->indexData->count > 0)
{
uint32_t numBytes = submesh->indexData->count * (submesh->indexData->is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
uint8_t *indexBuffer = ReadBytes(numBytes);
submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true));
DefaultLogger::get()->debug(Formatter::format() << " - " << submesh->indexData->faceCount
<< " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit")
<< " indexes of " << numBytes << " bytes");
}
// Vertex buffer if not referencing the shared geometry
if (!submesh->usesSharedVertexData)
{
id = ReadHeader();
if (id != M_GEOMETRY)
throw DeadlyImportError("M_SUBMESH does not contain M_GEOMETRY, but shader geometry is set to false");
submesh->vertexData = new VertexData();
ReadGeometry(mesh, submesh->vertexData);
}
// Bone assignment, submesh operation and texture aliases
if (!AtEnd())
{
id = ReadHeader();
while (!AtEnd() &&
(id == M_SUBMESH_OPERATION ||
id == M_SUBMESH_BONE_ASSIGNMENT ||
id == M_SUBMESH_TEXTURE_ALIAS))
{
switch(id)
{
case M_SUBMESH_OPERATION:
{
ReadSubMeshOperation(submesh);
break;
}
case M_SUBMESH_BONE_ASSIGNMENT:
{
ReadBoneAssignment(submesh);
break;
}
case M_SUBMESH_TEXTURE_ALIAS:
{
ReadSubMeshTextureAlias(submesh);
break;
}
}
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
submesh->index = mesh->subMeshes.size();
mesh->subMeshes.push_back(submesh);
}
void OgreBinarySerializer::ReadSubMeshOperation(SubMesh2 *submesh)
{
submesh->operationType = static_cast<SubMesh2::OperationType>(Read<uint16_t>());
}
void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh2 *submesh)
{
submesh->textureAliasName = ReadLine();
submesh->textureAliasRef = ReadLine();
}
void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
{
uint16_t id = 0;
uint16_t submeshIndex = 0;
if (!AtEnd())
{
id = ReadHeader();
while (!AtEnd() && id == M_SUBMESH_NAME_TABLE_ELEMENT)
{
SubMesh2 *submesh = mesh->SubMesh(Read<uint16_t>());
if (submesh)
{
submesh->name = ReadLine();
DefaultLogger::get()->debug(Formatter::format() << " - SubMesh " << submesh->index << " name '" << submesh->name << "'");
}
else
ReadLine();
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadGeometry(Mesh *mesh, VertexData *dest)
{
dest->count = Read<uint32_t>();
DefaultLogger::get()->debug(Formatter::format() << " - Reading geometry of " << dest->count << " vertices");
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() &&
(id == M_GEOMETRY_VERTEX_DECLARATION ||
id == M_GEOMETRY_VERTEX_BUFFER))
{
switch(id)
{
case M_GEOMETRY_VERTEX_DECLARATION:
{
ReadGeometryVertexDeclaration(mesh, dest);
break;
}
case M_GEOMETRY_VERTEX_BUFFER:
{
ReadGeometryVertexBuffer(mesh, dest);
break;
}
}
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadGeometryVertexDeclaration(Mesh *mesh, VertexData *dest)
{
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() && id == M_GEOMETRY_VERTEX_ELEMENT)
{
ReadGeometryVertexElement(mesh, dest);
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadGeometryVertexElement(Mesh *mesh, VertexData *dest)
{
VertexElement element;
element.source = Read<uint16_t>();
element.type = static_cast<VertexElement::Type>(Read<uint16_t>());
element.semantic = static_cast<VertexElement::Semantic>(Read<uint16_t>());
element.offset = Read<uint16_t>();
element.index = Read<uint16_t>();
DefaultLogger::get()->debug(Formatter::format() << " - Vertex element " << element.SemanticToString() << " of type "
<< element.TypeToString() << " index=" << element.index << " source=" << element.source);
dest->vertexElements.push_back(element);
}
void OgreBinarySerializer::ReadGeometryVertexBuffer(Mesh *mesh, VertexData *dest)
{
uint16_t bindIndex = Read<uint16_t>();
uint16_t vertexSize = Read<uint16_t>();
uint16_t id = ReadHeader();
if (id != M_GEOMETRY_VERTEX_BUFFER_DATA)
throw DeadlyImportError("M_GEOMETRY_VERTEX_BUFFER_DATA not found in M_GEOMETRY_VERTEX_BUFFER");
if (dest->VertexSize(bindIndex) != vertexSize)
throw DeadlyImportError("Vertex buffer size does not agree with vertex declaration in M_GEOMETRY_VERTEX_BUFFER");
size_t numBytes = dest->count * vertexSize;
uint8_t *vertexBuffer = ReadBytes(numBytes);
dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true));
DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
}
void OgreBinarySerializer::ReadEdgeList(Mesh *mesh)
{
// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() && id == M_EDGE_LIST_LOD)
{
m_reader->IncPtr(sizeof(uint16_t)); // lod index
bool manual = Read<bool>();
if (!manual)
{
m_reader->IncPtr(sizeof(uint8_t));
uint32_t numTriangles = Read<uint32_t>();
uint32_t numEdgeGroups = Read<uint32_t>();
size_t skipBytes = (sizeof(uint32_t) * 8 + sizeof(float) * 4) * numTriangles;
m_reader->IncPtr(skipBytes);
for (size_t i=0; i<numEdgeGroups; ++i)
{
uint16_t id = ReadHeader();
if (id != M_EDGE_GROUP)
throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD");
m_reader->IncPtr(sizeof(uint32_t) * 3);
uint32_t numEdges = Read<uint32_t>();
for (size_t j=0; j<numEdges; ++j)
{
m_reader->IncPtr(sizeof(uint32_t) * 6 + sizeof(uint8_t));
}
}
}
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadPoses(Mesh *mesh)
{
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() && id == M_POSE)
{
Pose *pose = new Pose();
pose->name = ReadLine();
pose->target = Read<uint16_t>();
pose->hasNormals = Read<bool>();
ReadPoseVertices(pose);
mesh->poses.push_back(pose);
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadPoseVertices(Pose *pose)
{
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() && id == M_POSE_VERTEX)
{
Pose::Vertex v;
v.index = Read<uint32_t>();
ReadVector(v.offset);
if (pose->hasNormals)
ReadVector(v.normal);
pose->vertices[v.index] = v;
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadAnimations(Mesh *mesh)
{
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() && id == M_ANIMATION)
{
Animation2 *anim = new Animation2(mesh);
anim->name = ReadLine();
anim->length = Read<float>();
ReadAnimation(anim);
mesh->animations.push_back(anim);
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadAnimation(Animation2 *anim)
{
if (!AtEnd())
{
uint16_t id = ReadHeader();
if (id == M_ANIMATION_BASEINFO)
{
anim->baseName = ReadLine();
anim->baseTime = Read<float>();
// Advance to first track
id = ReadHeader();
}
while (!AtEnd() && id == M_ANIMATION_TRACK)
{
VertexAnimationTrack track;
track.type = static_cast<VertexAnimationTrack::Type>(Read<uint16_t>());
track.target = Read<uint16_t>();
ReadAnimationKeyFrames(anim, &track);
anim->tracks.push_back(track);
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
void OgreBinarySerializer::ReadAnimationKeyFrames(Animation2 *anim, VertexAnimationTrack *track)
{
if (!AtEnd())
{
uint16_t id = ReadHeader();
while (!AtEnd() &&
(id == M_ANIMATION_MORPH_KEYFRAME ||
id == M_ANIMATION_POSE_KEYFRAME))
{
if (id == M_ANIMATION_MORPH_KEYFRAME)
{
MorphKeyFrame kf;
kf.timePos = Read<float>();
bool hasNormals = Read<bool>();
size_t vertexCount = anim->AssociatedVertexData(track)->count;
size_t vertexSize = sizeof(float) * (hasNormals ? 6 : 3);
size_t numBytes = vertexCount * vertexSize;
uint8_t *morphBuffer = ReadBytes(numBytes);
kf.buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(morphBuffer, numBytes, true));
track->morphKeyFrames.push_back(kf);
}
else if (id == M_ANIMATION_POSE_KEYFRAME)
{
PoseKeyFrame kf;
kf.timePos = Read<float>();
if (!AtEnd())
{
id = ReadHeader();
while (!AtEnd() && id == M_ANIMATION_POSE_REF)
{
PoseRef pr;
pr.index = Read<uint16_t>();
pr.influence = Read<float>();
kf.references.push_back(pr);
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
track->poseKeyFrames.push_back(kf);
}
if (!AtEnd())
id = ReadHeader();
}
if (!AtEnd())
RollbackHeader();
}
}
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER

View File

@ -0,0 +1,312 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef AI_OGREBINARYSERIALIZER_H_INC
#define AI_OGREBINARYSERIALIZER_H_INC
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "OgreStructs.h"
namespace Assimp
{
namespace Ogre
{
class OgreBinarySerializer
{
public:
static Mesh *ImportMesh(MemoryStreamReader *reader);
private:
OgreBinarySerializer(MemoryStreamReader *reader) :
m_reader(reader),
m_currentLen(0)
{
}
bool AtEnd() const;
void ReadMesh(Mesh *mesh);
void ReadMeshLodInfo(Mesh *mesh);
void ReadMeshSkeletonLink(Mesh *mesh);
void ReadMeshBounds(Mesh *mesh);
void ReadMeshExtremes(Mesh *mesh);
void ReadSubMesh(Mesh *mesh);
void ReadSubMeshNames(Mesh *mesh);
void ReadSubMeshOperation(SubMesh2 *submesh);
void ReadSubMeshTextureAlias(SubMesh2 *submesh);
void ReadBoneAssignment(Mesh *dest);
void ReadBoneAssignment(SubMesh2 *dest);
void ReadGeometry(Mesh *mesh, VertexData *dest);
void ReadGeometryVertexDeclaration(Mesh *mesh, VertexData *dest);
void ReadGeometryVertexElement(Mesh *mesh, VertexData *dest);
void ReadGeometryVertexBuffer(Mesh *mesh, VertexData *dest);
void ReadEdgeList(Mesh *mesh);
void ReadPoses(Mesh *mesh);
void ReadPoseVertices(Pose *pose);
void ReadAnimations(Mesh *mesh);
void ReadAnimation(Animation2 *anim);
void ReadAnimationKeyFrames(Animation2 *anim, VertexAnimationTrack *track);
uint16_t ReadHeader(bool readLen = true);
void RollbackHeader();
template<typename T>
inline T Read();
void ReadBytes(char *dest, size_t numBytes);
void ReadBytes(uint8_t *dest, size_t numBytes);
void ReadBytes(void *dest, size_t numBytes);
uint8_t *ReadBytes(size_t numBytes);
void ReadVector(aiVector3D &vec);
std::string ReadString(size_t len);
std::string ReadLine();
void SkipBytes(size_t num);
uint32_t m_currentLen;
MemoryStreamReader *m_reader;
};
enum MeshChunkId
{
M_HEADER = 0x1000,
// char* version : Version number check
M_MESH = 0x3000,
// bool skeletallyAnimated // important flag which affects h/w buffer policies
// Optional M_GEOMETRY chunk
M_SUBMESH = 0x4000,
// char* materialName
// bool useSharedVertices
// unsigned int indexCount
// bool indexes32Bit
// unsigned int* faceVertexIndices (indexCount)
// OR
// unsigned short* faceVertexIndices (indexCount)
// M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
M_SUBMESH_OPERATION = 0x4010, // optional, trilist assumed if missing
// unsigned short operationType
M_SUBMESH_BONE_ASSIGNMENT = 0x4100,
// Optional bone weights (repeating section)
// unsigned int vertexIndex;
// unsigned short boneIndex;
// float weight;
// Optional chunk that matches a texture name to an alias
// a texture alias is sent to the submesh material to use this texture name
// instead of the one in the texture unit with a matching alias name
M_SUBMESH_TEXTURE_ALIAS = 0x4200, // Repeating section
// char* aliasName;
// char* textureName;
M_GEOMETRY = 0x5000, // NB this chunk is embedded within M_MESH and M_SUBMESH
// unsigned int vertexCount
M_GEOMETRY_VERTEX_DECLARATION = 0x5100,
M_GEOMETRY_VERTEX_ELEMENT = 0x5110, // Repeating section
// unsigned short source; // buffer bind source
// unsigned short type; // VertexElementType
// unsigned short semantic; // VertexElementSemantic
// unsigned short offset; // start offset in buffer in bytes
// unsigned short index; // index of the semantic (for colours and texture coords)
M_GEOMETRY_VERTEX_BUFFER = 0x5200, // Repeating section
// unsigned short bindIndex; // Index to bind this buffer to
// unsigned short vertexSize; // Per-vertex size, must agree with declaration at this index
M_GEOMETRY_VERTEX_BUFFER_DATA = 0x5210,
// raw buffer data
M_MESH_SKELETON_LINK = 0x6000,
// Optional link to skeleton
// char* skeletonName : name of .skeleton to use
M_MESH_BONE_ASSIGNMENT = 0x7000,
// Optional bone weights (repeating section)
// unsigned int vertexIndex;
// unsigned short boneIndex;
// float weight;
M_MESH_LOD = 0x8000,
// Optional LOD information
// string strategyName;
// unsigned short numLevels;
// bool manual; (true for manual alternate meshes, false for generated)
M_MESH_LOD_USAGE = 0x8100,
// Repeating section, ordered in increasing depth
// NB LOD 0 (full detail from 0 depth) is omitted
// LOD value - this is a distance, a pixel count etc, based on strategy
// float lodValue;
M_MESH_LOD_MANUAL = 0x8110,
// Required if M_MESH_LOD section manual = true
// String manualMeshName;
M_MESH_LOD_GENERATED = 0x8120,
// Required if M_MESH_LOD section manual = false
// Repeating section (1 per submesh)
// unsigned int indexCount;
// bool indexes32Bit
// unsigned short* faceIndexes; (indexCount)
// OR
// unsigned int* faceIndexes; (indexCount)
M_MESH_BOUNDS = 0x9000,
// float minx, miny, minz
// float maxx, maxy, maxz
// float radius
// Added By DrEvil
// optional chunk that contains a table of submesh indexes and the names of
// the sub-meshes.
M_SUBMESH_NAME_TABLE = 0xA000,
// Subchunks of the name table. Each chunk contains an index & string
M_SUBMESH_NAME_TABLE_ELEMENT = 0xA100,
// short index
// char* name
// Optional chunk which stores precomputed edge data
M_EDGE_LISTS = 0xB000,
// Each LOD has a separate edge list
M_EDGE_LIST_LOD = 0xB100,
// unsigned short lodIndex
// bool isManual // If manual, no edge data here, loaded from manual mesh
// bool isClosed
// unsigned long numTriangles
// unsigned long numEdgeGroups
// Triangle* triangleList
// unsigned long indexSet
// unsigned long vertexSet
// unsigned long vertIndex[3]
// unsigned long sharedVertIndex[3]
// float normal[4]
M_EDGE_GROUP = 0xB110,
// unsigned long vertexSet
// unsigned long triStart
// unsigned long triCount
// unsigned long numEdges
// Edge* edgeList
// unsigned long triIndex[2]
// unsigned long vertIndex[2]
// unsigned long sharedVertIndex[2]
// bool degenerate
// Optional poses section, referred to by pose keyframes
M_POSES = 0xC000,
M_POSE = 0xC100,
// char* name (may be blank)
// unsigned short target // 0 for shared geometry,
// 1+ for submesh index + 1
// bool includesNormals [1.8+]
M_POSE_VERTEX = 0xC111,
// unsigned long vertexIndex
// float xoffset, yoffset, zoffset
// float xnormal, ynormal, znormal (optional, 1.8+)
// Optional vertex animation chunk
M_ANIMATIONS = 0xD000,
M_ANIMATION = 0xD100,
// char* name
// float length
M_ANIMATION_BASEINFO = 0xD105,
// [Optional] base keyframe information (pose animation only)
// char* baseAnimationName (blank for self)
// float baseKeyFrameTime
M_ANIMATION_TRACK = 0xD110,
// unsigned short type // 1 == morph, 2 == pose
// unsigned short target // 0 for shared geometry,
// 1+ for submesh index + 1
M_ANIMATION_MORPH_KEYFRAME = 0xD111,
// float time
// bool includesNormals [1.8+]
// float x,y,z // repeat by number of vertices in original geometry
M_ANIMATION_POSE_KEYFRAME = 0xD112,
// float time
M_ANIMATION_POSE_REF = 0xD113, // repeat for number of referenced poses
// unsigned short poseIndex
// float influence
// Optional submesh extreme vertex list chink
M_TABLE_EXTREMES = 0xE000,
// unsigned short submesh_index;
// float extremes [n_extremes][3];
};
static std::string MeshHeaderToString(MeshChunkId id)
{
switch(id)
{
case M_HEADER: return "HEADER";
case M_MESH: return "MESH";
case M_SUBMESH: return "SUBMESH";
case M_SUBMESH_OPERATION: return "SUBMESH_OPERATION";
case M_SUBMESH_BONE_ASSIGNMENT: return "SUBMESH_BONE_ASSIGNMENT";
case M_SUBMESH_TEXTURE_ALIAS: return "SUBMESH_TEXTURE_ALIAS";
case M_GEOMETRY: return "GEOMETRY";
case M_GEOMETRY_VERTEX_DECLARATION: return "GEOMETRY_VERTEX_DECLARATION";
case M_GEOMETRY_VERTEX_ELEMENT: return "GEOMETRY_VERTEX_ELEMENT";
case M_GEOMETRY_VERTEX_BUFFER: return "GEOMETRY_VERTEX_BUFFER";
case M_GEOMETRY_VERTEX_BUFFER_DATA: return "GEOMETRY_VERTEX_BUFFER_DATA";
case M_MESH_SKELETON_LINK: return "MESH_SKELETON_LINK";
case M_MESH_BONE_ASSIGNMENT: return "MESH_BONE_ASSIGNMENT";
case M_MESH_LOD: return "MESH_LOD";
case M_MESH_LOD_USAGE: return "MESH_LOD_USAGE";
case M_MESH_LOD_MANUAL: return "MESH_LOD_MANUAL";
case M_MESH_LOD_GENERATED: return "MESH_LOD_GENERATED";
case M_MESH_BOUNDS: return "MESH_BOUNDS";
case M_SUBMESH_NAME_TABLE: return "SUBMESH_NAME_TABLE";
case M_SUBMESH_NAME_TABLE_ELEMENT: return "SUBMESH_NAME_TABLE_ELEMENT";
case M_EDGE_LISTS: return "EDGE_LISTS";
case M_EDGE_LIST_LOD: return "EDGE_LIST_LOD";
case M_EDGE_GROUP: return "EDGE_GROUP";
case M_POSES: return "POSES";
case M_POSE: return "POSE";
case M_POSE_VERTEX: return "POSE_VERTEX";
case M_ANIMATIONS: return "ANIMATIONS";
case M_ANIMATION: return "ANIMATION";
case M_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
case M_ANIMATION_TRACK: return "ANIMATION_TRACK";
case M_ANIMATION_MORPH_KEYFRAME: return "ANIMATION_MORPH_KEYFRAME";
case M_ANIMATION_POSE_KEYFRAME: return "ANIMATION_POSE_KEYFRAME";
case M_ANIMATION_POSE_REF: return "ANIMATION_POSE_REF";
case M_TABLE_EXTREMES: return "TABLE_EXTREMES";
}
return "Uknown_MeshChunkId";
}
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGREBINARYSERIALIZER_H_INC

View File

@ -38,28 +38,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "AssimpPCH.h"
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <istream>
#include "OgreImporter.h" #include "OgreImporter.h"
#include "OgreBinarySerializer.h"
#include "TinyFormatter.h" #include "TinyFormatter.h"
#include "irrXMLWrapper.h" #include "irrXMLWrapper.h"
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"Ogre XML Mesh Importer", "Ogre3D Mesh Importer",
"", "",
"", "",
"", "",
aiImporterFlags_SupportTextFlavour, aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
0, 0,
0, 0,
0, 0,
0, 0,
"mesh.xml" "mesh mesh.xml"
}; };
using namespace std; using namespace std;
@ -83,24 +86,49 @@ void OgreImporter::SetupProperties(const Importer* pImp)
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
{ {
if (!checkSig) { if (!checkSig) {
return EndsWith(pFile, ".mesh.xml", false); return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false);
} }
if (EndsWith(pFile, ".mesh.xml", false))
{
const char* tokens[] = { "<mesh>" }; const char* tokens[] = { "<mesh>" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
} }
else
{
return EndsWith(pFile, ".mesh", false);
}
}
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler) void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
{ {
// -------------------- Initial file and XML operations -------------------- // -------------------- Initial file and XML operations --------------------
// Open // Open
boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile)); IOStream *f = pIOHandler->Open(pFile, "rb");
if (!file.get()) { if (!f) {
throw DeadlyImportError("Failed to open file " + pFile); throw DeadlyImportError("Failed to open file " + pFile);
} }
// Binary .mesh import
if (EndsWith(pFile, ".mesh", false)) {
// Read full data from file
/// @note MemoryStreamReader takes ownership of f.
MemoryStreamReader reader(f);
// Import mesh
boost::scoped_ptr<Mesh> mesh = OgreBinarySerializer::ImportMesh(&reader);
// Import mesh referenced materials
ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
// Convert to Assimp.
mesh->ConvertToAssimpScene(pScene);
return;
}
// Read // Read
boost::scoped_ptr<IOStream> file(f);
boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(file.get())); boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(file.get()));
boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get())); boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
if (!reader) { if (!reader) {
@ -153,20 +181,21 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
SubMesh* submesh = new SubMesh(); SubMesh* submesh = new SubMesh();
ReadSubMesh(subMeshes.size(), *submesh, reader.get()); ReadSubMesh(subMeshes.size(), *submesh, reader.get());
// Just a index in a array, we add a mesh in each loop cycle, so we get indicies like 0, 1, 2 ... n;
// so it is important to do this before pushing the mesh in the vector!
/// @todo Not sure if this really is needed, refactor out if possible.
submesh->MaterialIndex = subMeshes.size();
subMeshes.push_back(boost::shared_ptr<SubMesh>(submesh));
/** @todo What is the correct way of handling empty ref here. /** @todo What is the correct way of handling empty ref here.
Does Assimp require there to be a valid material index for each mesh, Does Assimp require there to be a valid material index for each mesh,
even if its a dummy material. */ even if its a dummy material. */
aiMaterial* material = ReadMaterial(pFile, pIOHandler, submesh->MaterialName); aiMaterial* material = ReadMaterial(pFile, pIOHandler, submesh->MaterialName);
if (!material)
material = new aiMaterial();
if (material)
{
submesh->MaterialIndex = materials.size();
materials.push_back(material); materials.push_back(material);
} }
subMeshes.push_back(boost::shared_ptr<SubMesh>(submesh));
}
if (subMeshes.empty()) { if (subMeshes.empty()) {
throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node"); throw DeadlyImportError("Could not find <submeshes> node inside root <mesh> node");
} }
@ -223,10 +252,12 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
// -------------------- Apply to aiScene -------------------- // -------------------- Apply to aiScene --------------------
// Materials // Materials
pScene->mMaterials = new aiMaterial*[materials.size()];
pScene->mNumMaterials = materials.size(); pScene->mNumMaterials = materials.size();
if (pScene->mNumMaterials > 0) {
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
}
for(size_t i=0, len=materials.size(); i<len; ++i) { for(size_t i=0; i<pScene->mNumMaterials; ++i) {
pScene->mMaterials[i] = materials[i]; pScene->mMaterials[i] = materials[i];
} }

View File

@ -1,3 +1,42 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef AI_OGREIMPORTER_H_INC #ifndef AI_OGREIMPORTER_H_INC
#define AI_OGREIMPORTER_H_INC #define AI_OGREIMPORTER_H_INC
@ -5,6 +44,8 @@
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "BaseImporter.h" #include "BaseImporter.h"
#include "OgreStructs.h"
#include "OgreParsingUtils.h" #include "OgreParsingUtils.h"
namespace Assimp namespace Assimp
@ -114,6 +155,9 @@ private:
//-------------------------------- OgreMaterial.cpp ------------------------------- //-------------------------------- OgreMaterial.cpp -------------------------------
/// Read materials referenced by the @c mesh to @c pScene.
void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh);
/// Reads material /// Reads material
aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName); aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName);

View File

@ -59,11 +59,40 @@ static const string partComment = "//";
static const string partBlockStart = "{"; static const string partBlockStart = "{";
static const string partBlockEnd = "}"; static const string partBlockEnd = "}";
void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh)
{
std::vector<aiMaterial*> materials;
// Create materials that can be found and parsed via the IOSystem.
for (size_t i=0, len=mesh->NumSubMeshes(); i<len; ++i)
{
SubMesh2 *submesh = mesh->SubMesh(i);
if (submesh && !submesh->materialRef.empty())
{
aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
if (material)
{
submesh->materialIndex = materials.size();
materials.push_back(material);
}
}
}
// Assign material to scene
pScene->mNumMaterials = materials.size();
if (pScene->mNumMaterials > 0)
{
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
for(size_t i=0;i<pScene->mNumMaterials; ++i) {
pScene->mMaterials[i] = materials[i];
}
}
}
aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string materialName) aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string materialName)
{ {
/// @todo Should we return null ptr here or a empty material?
if (materialName.empty()) { if (materialName.empty()) {
return new aiMaterial(); return 0;
} }
// Full reference and examples of Ogre Material Script // Full reference and examples of Ogre Material Script
@ -117,17 +146,15 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
} }
if (!materialFile) if (!materialFile)
{ {
/// @todo Should we return null ptr here or a empty material?
DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'"); DefaultLogger::get()->error(Formatter::format() << "Failed to find source file for material '" << materialName << "'");
return new aiMaterial(); return 0;
} }
boost::scoped_ptr<IOStream> stream(materialFile); boost::scoped_ptr<IOStream> stream(materialFile);
if (stream->FileSize() == 0) if (stream->FileSize() == 0)
{ {
/// @todo Should we return null ptr here or a empty material?
DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)"); DefaultLogger::get()->warn(Formatter::format() << "Source file for material '" << materialName << "' is empty (size is 0 bytes)");
return new aiMaterial(); return 0;
} }
// Read bytes // Read bytes

View File

@ -469,6 +469,7 @@ aiMesh *OgreImporter::CreateAssimpSubMesh(aiScene *pScene, const SubMesh& submes
aiMesh *dest = new aiMesh(); aiMesh *dest = new aiMesh();
// Material // Material
if (submesh.MaterialIndex != -1)
dest->mMaterialIndex = submesh.MaterialIndex; dest->mMaterialIndex = submesh.MaterialIndex;
// Positions // Positions

View File

@ -1,3 +1,42 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef AI_OGREPARSINGUTILS_H_INC #ifndef AI_OGREPARSINGUTILS_H_INC
#define AI_OGREPARSINGUTILS_H_INC #define AI_OGREPARSINGUTILS_H_INC
@ -13,6 +52,70 @@ namespace Assimp
namespace Ogre namespace Ogre
{ {
/// Returns a lower cased copy of @s.
static inline std::string ToLower(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
}
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true)
{
if (s.empty() || suffix.empty())
{
return false;
}
else if (s.length() < suffix.length())
{
return false;
}
if (!caseSensitive) {
return EndsWith(ToLower(s), ToLower(suffix), true);
}
size_t len = suffix.length();
std::string sSuffix = s.substr(s.length()-len, len);
return (ASSIMP_stricmp(sSuffix, suffix) == 0);
}
// Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
/// Trim from start
static inline std::string &TrimLeft(std::string &s, bool newlines = true)
{
if (!newlines)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
}
else
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
}
return s;
}
/// Trim from end
static inline std::string &TrimRight(std::string &s, bool newlines = true)
{
if (!newlines)
{
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
}
else
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
}
return s;
}
/// Trim from both ends
static inline std::string &Trim(std::string &s, bool newlines = true)
{
return TrimLeft(TrimRight(s, newlines), newlines);
}
typedef irr::io::IrrXMLReader XmlReader; typedef irr::io::IrrXMLReader XmlReader;
static void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "") static void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "")
@ -93,7 +196,7 @@ inline std::string GetAttribute<std::string>(const XmlReader* reader, const std:
template<> template<>
inline bool GetAttribute<bool>(const XmlReader* reader, const std::string &name) inline bool GetAttribute<bool>(const XmlReader* reader, const std::string &name)
{ {
std::string value = GetAttribute<std::string>(reader, name); std::string value = Ogre::ToLower(GetAttribute<std::string>(reader, name));
if (ASSIMP_stricmp(value, "true") == 0) if (ASSIMP_stricmp(value, "true") == 0)
{ {
return true; return true;
@ -143,70 +246,6 @@ static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &n
return skipped; return skipped;
} }
/// Returns a lower cased copy of @s.
static inline std::string ToLower(std::string s)
{
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
}
/// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching.
static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true)
{
if (s.empty() || suffix.empty())
{
return false;
}
else if (s.length() < suffix.length())
{
return false;
}
if (!caseSensitive) {
return EndsWith(ToLower(s), ToLower(suffix), true);
}
size_t len = suffix.length();
std::string sSuffix = s.substr(s.length()-len, len);
return (ASSIMP_stricmp(sSuffix, suffix) == 0);
}
// Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
/// Trim from start
static inline std::string &TrimLeft(std::string &s, bool newlines = true)
{
if (!newlines)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))));
}
else
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
}
return s;
}
/// Trim from end
static inline std::string &TrimRight(std::string &s, bool newlines = true)
{
if (!newlines)
{
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace<char>))).base(),s.end());
}
else
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine<char>))));
}
return s;
}
/// Trim from both ends
static inline std::string &Trim(std::string &s, bool newlines = true)
{
return TrimLeft(TrimRight(s, newlines), newlines);
}
} // Ogre } // Ogre
} // Assimp } // Assimp

View File

@ -5,11 +5,11 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2012, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in aSource and binary forms, Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of aSource code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.

View File

@ -0,0 +1,583 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "OgreStructs.h"
#include "TinyFormatter.h"
namespace Assimp
{
namespace Ogre
{
// VertexElement
VertexElement::VertexElement() :
index(0),
source(0),
offset(0),
type(VET_FLOAT1),
semantic(VES_POSITION)
{
}
size_t VertexElement::Size() const
{
return TypeSize(type);
}
size_t VertexElement::ComponentCount() const
{
return ComponentCount(type);
}
size_t VertexElement::ComponentCount(Type type)
{
switch(type)
{
case VET_COLOUR:
case VET_COLOUR_ABGR:
case VET_COLOUR_ARGB:
case VET_FLOAT1:
case VET_DOUBLE1:
case VET_SHORT1:
case VET_USHORT1:
case VET_INT1:
case VET_UINT1:
return 1;
case VET_FLOAT2:
case VET_DOUBLE2:
case VET_SHORT2:
case VET_USHORT2:
case VET_INT2:
case VET_UINT2:
return 2;
case VET_FLOAT3:
case VET_DOUBLE3:
case VET_SHORT3:
case VET_USHORT3:
case VET_INT3:
case VET_UINT3:
return 3;
case VET_FLOAT4:
case VET_DOUBLE4:
case VET_SHORT4:
case VET_USHORT4:
case VET_INT4:
case VET_UINT4:
case VET_UBYTE4:
return 4;
}
return 0;
}
size_t VertexElement::TypeSize(Type type)
{
switch(type)
{
case VET_COLOUR:
case VET_COLOUR_ABGR:
case VET_COLOUR_ARGB:
return sizeof(unsigned int);
case VET_FLOAT1:
return sizeof(float);
case VET_FLOAT2:
return sizeof(float)*2;
case VET_FLOAT3:
return sizeof(float)*3;
case VET_FLOAT4:
return sizeof(float)*4;
case VET_DOUBLE1:
return sizeof(double);
case VET_DOUBLE2:
return sizeof(double)*2;
case VET_DOUBLE3:
return sizeof(double)*3;
case VET_DOUBLE4:
return sizeof(double)*4;
case VET_SHORT1:
return sizeof(short);
case VET_SHORT2:
return sizeof(short)*2;
case VET_SHORT3:
return sizeof(short)*3;
case VET_SHORT4:
return sizeof(short)*4;
case VET_USHORT1:
return sizeof(unsigned short);
case VET_USHORT2:
return sizeof(unsigned short)*2;
case VET_USHORT3:
return sizeof(unsigned short)*3;
case VET_USHORT4:
return sizeof(unsigned short)*4;
case VET_INT1:
return sizeof(int);
case VET_INT2:
return sizeof(int)*2;
case VET_INT3:
return sizeof(int)*3;
case VET_INT4:
return sizeof(int)*4;
case VET_UINT1:
return sizeof(unsigned int);
case VET_UINT2:
return sizeof(unsigned int)*2;
case VET_UINT3:
return sizeof(unsigned int)*3;
case VET_UINT4:
return sizeof(unsigned int)*4;
case VET_UBYTE4:
return sizeof(unsigned char)*4;
}
return 0;
}
std::string VertexElement::TypeToString()
{
return TypeToString(type);
}
std::string VertexElement::TypeToString(Type type)
{
switch(type)
{
case VET_COLOUR: return "COLOUR";
case VET_COLOUR_ABGR: return "COLOUR_ABGR";
case VET_COLOUR_ARGB: return "COLOUR_ARGB";
case VET_FLOAT1: return "FLOAT1";
case VET_FLOAT2: return "FLOAT2";
case VET_FLOAT3: return "FLOAT3";
case VET_FLOAT4: return "FLOAT4";
case VET_DOUBLE1: return "DOUBLE1";
case VET_DOUBLE2: return "DOUBLE2";
case VET_DOUBLE3: return "DOUBLE3";
case VET_DOUBLE4: return "DOUBLE4";
case VET_SHORT1: return "SHORT1";
case VET_SHORT2: return "SHORT2";
case VET_SHORT3: return "SHORT3";
case VET_SHORT4: return "SHORT4";
case VET_USHORT1: return "USHORT1";
case VET_USHORT2: return "USHORT2";
case VET_USHORT3: return "USHORT3";
case VET_USHORT4: return "USHORT4";
case VET_INT1: return "INT1";
case VET_INT2: return "INT2";
case VET_INT3: return "INT3";
case VET_INT4: return "INT4";
case VET_UINT1: return "UINT1";
case VET_UINT2: return "UINT2";
case VET_UINT3: return "UINT3";
case VET_UINT4: return "UINT4";
case VET_UBYTE4: return "UBYTE4";
}
return "Uknown_VertexElement::Type";
}
std::string VertexElement::SemanticToString()
{
return SemanticToString(semantic);
}
std::string VertexElement::SemanticToString(Semantic semantic)
{
switch(semantic)
{
case VES_POSITION: return "POSITION";
case VES_BLEND_WEIGHTS: return "BLEND_WEIGHTS";
case VES_BLEND_INDICES: return "BLEND_INDICES";
case VES_NORMAL: return "NORMAL";
case VES_DIFFUSE: return "DIFFUSE";
case VES_SPECULAR: return "SPECULAR";
case VES_TEXTURE_COORDINATES: return "TEXTURE_COORDINATES";
case VES_BINORMAL: return "BINORMAL";
case VES_TANGENT: return "TANGENT";
}
return "Uknown_VertexElement::Semantic";
}
// VertexData
VertexData::VertexData() :
count(0)
{
}
VertexData::~VertexData()
{
Reset();
}
void VertexData::Reset()
{
// Releases shared ptr memory streams.
vertexBindings.clear();
vertexElements.clear();
}
uint32_t VertexData::VertexSize(uint16_t source) const
{
uint32_t size = 0;
for(VertexElementList::const_iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
{
if (iter->source == source)
size += iter->Size();
}
return size;
}
MemoryStream *VertexData::VertexBuffer(uint16_t source)
{
if (vertexBindings.find(source) != vertexBindings.end())
return vertexBindings[source];
return 0;
}
VertexElement *VertexData::GetVertexElement(VertexElement::Semantic semantic, uint16_t index)
{
for(VertexElementList::iterator iter=vertexElements.begin(), end=vertexElements.end(); iter != end; ++iter)
{
VertexElement &element = (*iter);
if (element.semantic == semantic && element.index == index)
return &element;
}
return 0;
}
// IndexData
IndexData::IndexData() :
count(0),
faceCount(0),
is32bit(false)
{
}
IndexData::~IndexData()
{
Reset();
}
void IndexData::Reset()
{
// Release shared ptr memory stream.
buffer.reset();
}
size_t IndexData::IndexSize() const
{
return (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
}
size_t IndexData::FaceSize() const
{
return IndexSize() * 3;
}
// Mesh
Mesh::Mesh() :
sharedVertexData(0),
hasSkeletalAnimations(false)
{
}
Mesh::~Mesh()
{
Reset();
}
void Mesh::Reset()
{
OGRE_SAFE_DELETE(sharedVertexData)
for(size_t i=0, len=subMeshes.size(); i<len; ++i) {
OGRE_SAFE_DELETE(subMeshes[i])
}
subMeshes.clear();
for(size_t i=0, len=animations.size(); i<len; ++i) {
OGRE_SAFE_DELETE(animations[i])
}
animations.clear();
for(size_t i=0, len=poses.size(); i<len; ++i) {
OGRE_SAFE_DELETE(poses[i])
}
poses.clear();
}
size_t Mesh::NumSubMeshes() const
{
return subMeshes.size();
}
SubMesh2 *Mesh::SubMesh(uint16_t index) const
{
for(size_t i=0; i<subMeshes.size(); ++i)
if (subMeshes[i]->index == index)
return subMeshes[i];
return 0;
}
void Mesh::ConvertToAssimpScene(aiScene* dest)
{
// Export meshes
dest->mNumMeshes = NumSubMeshes();
dest->mMeshes = new aiMesh*[dest->mNumMeshes];
// Create root node
dest->mRootNode = new aiNode();
dest->mRootNode->mNumMeshes = dest->mNumMeshes;
dest->mRootNode->mMeshes = new unsigned int[dest->mRootNode->mNumMeshes];
for(size_t i=0; i<dest->mNumMeshes; ++i) {
dest->mMeshes[i] = subMeshes[i]->ConvertToAssimpMesh(this);
dest->mRootNode->mMeshes[i] = i;
}
}
// SubMesh2
SubMesh2::SubMesh2() :
index(0),
vertexData(0),
indexData(new IndexData()),
usesSharedVertexData(false),
operationType(OT_POINT_LIST),
materialIndex(-1)
{
}
SubMesh2::~SubMesh2()
{
Reset();
}
void SubMesh2::Reset()
{
OGRE_SAFE_DELETE(vertexData)
OGRE_SAFE_DELETE(indexData)
}
aiMesh *SubMesh2::ConvertToAssimpMesh(Mesh *parent)
{
if (operationType != OT_TRIANGLE_LIST) {
throw DeadlyImportError(Formatter::format() << "Only mesh operation type OT_TRIANGLE_LIST is supported. Found " << operationType);
}
aiMesh *dest = new aiMesh();
dest->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
if (!name.empty())
dest->mName = name;
// Material index
if (materialIndex != -1)
dest->mMaterialIndex = materialIndex;
// Pick source vertex data from shader geometry or from internal geometry.
VertexData *src = (!usesSharedVertexData ? vertexData : parent->sharedVertexData);
VertexElement *positionsElement = src->GetVertexElement(VertexElement::VES_POSITION);
VertexElement *normalsElement = src->GetVertexElement(VertexElement::VES_NORMAL);
VertexElement *uv1Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 0);
VertexElement *uv2Element = src->GetVertexElement(VertexElement::VES_TEXTURE_COORDINATES, 1);
// Sanity checks
if (!positionsElement) {
throw DeadlyImportError("Failed to import Ogre VertexElement::VES_POSITION. Mesh does not have vertex positions!");
} else if (positionsElement->type != VertexElement::VET_FLOAT3) {
throw DeadlyImportError("Ogre Mesh position vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
} else if (normalsElement && normalsElement->type != VertexElement::VET_FLOAT3) {
throw DeadlyImportError("Ogre Mesh normal vertex element type != VertexElement::VET_FLOAT3. This is not supported.");
}
// Faces
dest->mNumFaces = indexData->faceCount;
dest->mFaces = new aiFace[dest->mNumFaces];
// Assimp required unique vertices, we need to convert from Ogres shared indexing.
size_t uniqueVertexCount = dest->mNumFaces * 3;
dest->mNumVertices = uniqueVertexCount;
dest->mVertices = new aiVector3D[dest->mNumVertices];
// Source streams
MemoryStream *positions = src->VertexBuffer(positionsElement->source);
MemoryStream *normals = (normalsElement ? src->VertexBuffer(normalsElement->source) : 0);
MemoryStream *uv1 = (uv1Element ? src->VertexBuffer(uv1Element->source) : 0);
MemoryStream *uv2 = (uv2Element ? src->VertexBuffer(uv2Element->source) : 0);
// Element size
const size_t sizePosition = positionsElement->Size();
const size_t sizeNormal = (normalsElement ? normalsElement->Size() : 0);
const size_t sizeUv1 = (uv1Element ? uv1Element->Size() : 0);
const size_t sizeUv2 = (uv2Element ? uv2Element->Size() : 0);
// Vertex width
const size_t vWidthPosition = src->VertexSize(positionsElement->source);
const size_t vWidthNormal = (normalsElement ? src->VertexSize(normalsElement->source) : 0);
const size_t vWidthUv1 = (uv1Element ? src->VertexSize(uv1Element->source) : 0);
const size_t vWidthUv2 = (uv2Element ? src->VertexSize(uv2Element->source) : 0);
// Prepare normals
if (normals)
dest->mNormals = new aiVector3D[dest->mNumVertices];
// Prepare UVs, ignoring incompatible UVs.
if (uv1)
{
if (uv1Element->type == VertexElement::VET_FLOAT2 || uv1Element->type == VertexElement::VET_FLOAT3)
{
dest->mNumUVComponents[0] = uv1Element->ComponentCount();
dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices];
}
else
{
DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
uv1 = 0;
}
}
if (uv2)
{
if (uv2Element->type == VertexElement::VET_FLOAT2 || uv2Element->type == VertexElement::VET_FLOAT3)
{
dest->mNumUVComponents[1] = uv2Element->ComponentCount();
dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices];
}
else
{
DefaultLogger::get()->warn(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV.");
uv2 = 0;
}
}
aiVector3D *uv1Dest = (uv1 ? dest->mTextureCoords[0] : 0);
aiVector3D *uv2Dest = (uv2 ? dest->mTextureCoords[1] : 0);
MemoryStream *faces = indexData->buffer.get();
for (size_t fi=0, isize=indexData->IndexSize(), fsize=indexData->FaceSize();
fi<dest->mNumFaces; ++fi)
{
// Source Ogre face
aiFace ogreFace;
ogreFace.mNumIndices = 3;
ogreFace.mIndices = new unsigned int[3];
faces->Seek(fi * fsize, aiOrigin_SET);
if (indexData->is32bit)
{
faces->Read(&ogreFace.mIndices[0], isize, 3);
}
else
{
uint16_t iout = 0;
for (size_t ii=0; ii<3; ++ii)
{
faces->Read(&iout, isize, 1);
ogreFace.mIndices[ii] = static_cast<unsigned int>(iout);
}
}
// Destination Assimp face
aiFace &face = dest->mFaces[fi];
face.mNumIndices = 3;
face.mIndices = new unsigned int[3];
const size_t pos = fi * 3;
for (size_t v=0; v<3; ++v)
{
const size_t newIndex = pos + v;
// Write face index
face.mIndices[v] = newIndex;
// Ogres vertex index to ref into the source buffers.
const size_t ogreVertexIndex = ogreFace.mIndices[v];
// Position
positions->Seek((vWidthPosition * ogreVertexIndex) + positionsElement->offset, aiOrigin_SET);
positions->Read(&dest->mVertices[newIndex], sizePosition, 1);
// Normal
if (normals)
{
normals->Seek((vWidthNormal * ogreVertexIndex) + normalsElement->offset, aiOrigin_SET);
normals->Read(&dest->mNormals[newIndex], sizeNormal, 1);
}
// UV0
if (uv1 && uv1Dest)
{
uv1->Seek((vWidthUv1 * ogreVertexIndex) + uv1Element->offset, aiOrigin_SET);
uv1->Read(&uv1Dest[newIndex], sizeUv1, 1);
}
// UV1
if (uv2 && uv2Dest)
{
uv2->Seek((vWidthUv2 * ogreVertexIndex) + uv2Element->offset, aiOrigin_SET);
uv2->Read(&uv2Dest[newIndex], sizeUv2, 1);
}
/// @todo Bones and bone weights.
}
}
return dest;
}
// Animation2
Animation2::Animation2(Mesh *_parentMesh) :
parentMesh(_parentMesh),
length(0.0f),
baseTime(-1.0f)
{
}
VertexData *Animation2::AssociatedVertexData(VertexAnimationTrack *track) const
{
bool sharedGeom = (track->target == 0);
if (sharedGeom)
return parentMesh->sharedVertexData;
else
return parentMesh->SubMesh(track->target-1)->vertexData;
}
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER

444
code/OgreStructs.h 100644
View File

@ -0,0 +1,444 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef AI_OGRESTRUCTS_H_INC
#define AI_OGRESTRUCTS_H_INC
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "AssimpPCH.h"
#include "MemoryIOWrapper.h"
/** @note Parts of this implementation, for example enums, deserialization constants and logic
has been copied directly with minor modifications from the MIT licensed Ogre3D code base.
See more from https://bitbucket.org/sinbad/ogre. */
namespace Assimp
{
namespace Ogre
{
// Forward decl
class Mesh;
class SubMesh2;
#define OGRE_SAFE_DELETE(p) delete p; p=0;
// Typedefs
typedef Assimp::StreamReaderLE MemoryStreamReader;
typedef Assimp::MemoryIOStream MemoryStream;
typedef boost::shared_ptr<MemoryStream> MemoryStreamPtr;
typedef std::map<uint16_t, MemoryStreamPtr> VertexBufferBindings;
// Ogre Vertex Element
class VertexElement
{
public:
/// Vertex element semantics, used to identify the meaning of vertex buffer contents
enum Semantic {
/// Position, 3 reals per vertex
VES_POSITION = 1,
/// Blending weights
VES_BLEND_WEIGHTS = 2,
/// Blending indices
VES_BLEND_INDICES = 3,
/// Normal, 3 reals per vertex
VES_NORMAL = 4,
/// Diffuse colours
VES_DIFFUSE = 5,
/// Specular colours
VES_SPECULAR = 6,
/// Texture coordinates
VES_TEXTURE_COORDINATES = 7,
/// Binormal (Y axis if normal is Z)
VES_BINORMAL = 8,
/// Tangent (X axis if normal is Z)
VES_TANGENT = 9,
/// The number of VertexElementSemantic elements (note - the first value VES_POSITION is 1)
VES_COUNT = 9
};
/// Vertex element type, used to identify the base types of the vertex contents
enum Type
{
VET_FLOAT1 = 0,
VET_FLOAT2 = 1,
VET_FLOAT3 = 2,
VET_FLOAT4 = 3,
/// alias to more specific colour type - use the current rendersystem's colour packing
VET_COLOUR = 4,
VET_SHORT1 = 5,
VET_SHORT2 = 6,
VET_SHORT3 = 7,
VET_SHORT4 = 8,
VET_UBYTE4 = 9,
/// D3D style compact colour
VET_COLOUR_ARGB = 10,
/// GL style compact colour
VET_COLOUR_ABGR = 11,
VET_DOUBLE1 = 12,
VET_DOUBLE2 = 13,
VET_DOUBLE3 = 14,
VET_DOUBLE4 = 15,
VET_USHORT1 = 16,
VET_USHORT2 = 17,
VET_USHORT3 = 18,
VET_USHORT4 = 19,
VET_INT1 = 20,
VET_INT2 = 21,
VET_INT3 = 22,
VET_INT4 = 23,
VET_UINT1 = 24,
VET_UINT2 = 25,
VET_UINT3 = 26,
VET_UINT4 = 27
};
VertexElement();
/// Size of the vertex element in bytes.
size_t Size() const;
/// Count of components in this element, eg. VET_FLOAT3 return 3.
size_t ComponentCount() const;
/// Type as string.
std::string TypeToString();
/// Semantic as string.
std::string SemanticToString();
static size_t TypeSize(Type type);
static size_t ComponentCount(Type type);
static std::string TypeToString(Type type);
static std::string SemanticToString(Semantic semantic);
uint16_t index;
uint16_t source;
uint16_t offset;
Type type;
Semantic semantic;
};
typedef std::vector<VertexElement> VertexElementList;
// Ogre Vertex Data
class VertexData
{
public:
VertexData();
~VertexData();
/// Releases all memory that this data structure owns.
void Reset();
/// Get vertex size for @c source.
uint32_t VertexSize(uint16_t source) const;
/// Get vertex buffer for @c source.
MemoryStream *VertexBuffer(uint16_t source);
/// Get vertex element for @c semantic for @c index.
VertexElement *GetVertexElement(VertexElement::Semantic semantic, uint16_t index = 0);
/// Vertex count.
uint32_t count;
/// Vertex elements.
VertexElementList vertexElements;
/// Vertex buffers mapped to bind index.
VertexBufferBindings vertexBindings;
};
// Ogre Index Data
class IndexData
{
public:
IndexData();
~IndexData();
/// Releases all memory that this data structure owns.
void Reset();
/// Index size in bytes.
size_t IndexSize() const;
/// Face size in bytes.
size_t FaceSize() const;
/// Index count.
uint32_t count;
/// Face count.
uint32_t faceCount;
/// If has 32-bit indexes.
bool is32bit;
/// Index buffer.
MemoryStreamPtr buffer;
};
/// Ogre Pose
class Pose
{
public:
struct Vertex
{
uint32_t index;
aiVector3D offset;
aiVector3D normal;
};
typedef std::map<uint32_t, Vertex> PoseVertexMap;
Pose() : target(0), hasNormals(false) {}
/// Name.
std::string name;
/// Target.
uint16_t target;
/// Does vertices map have normals.
bool hasNormals;
/// Vertex offset and normals.
PoseVertexMap vertices;
};
/// Ogre Pose Key Frame Ref
struct PoseRef
{
uint16_t index;
float influence;
};
/// Ogre Pose Key Frame
struct PoseKeyFrame
{
/// Time position in the animation.
float timePos;
std::vector<PoseRef> references;
};
/// Ogre Morph Key Frame
struct MorphKeyFrame
{
/// Time position in the animation.
float timePos;
MemoryStreamPtr buffer;
};
/// Ogre Animation Track
struct VertexAnimationTrack
{
enum Type
{
/// No animation
VAT_NONE = 0,
/// Morph animation is made up of many interpolated snapshot keyframes
VAT_MORPH = 1,
/// Pose animation is made up of a single delta pose keyframe
VAT_POSE = 2
};
/// Vertex data target.
/** 0 == shared geometry
>0 == submesh index + 1 */
uint16_t target;
Type type;
std::vector<PoseKeyFrame> poseKeyFrames;
std::vector<MorphKeyFrame> morphKeyFrames;
};
/// Ogre Animation
/** @todo Port OgreImporter::Animation to this and rename this to Animation! */
class Animation2
{
public:
Animation2(Mesh *_parentMesh);
/// Returns the associated vertex data for a track in this animation.
VertexData *AssociatedVertexData(VertexAnimationTrack *track) const;
/// Parent mesh.
Mesh *parentMesh;
/// Animation name.
std::string name;
/// Base animation name.
std::string baseName;
/// Length in seconds.
float length;
/// Base animation key time.
float baseTime;
/// Animation tracks.
std::vector<VertexAnimationTrack> tracks;
};
/// Ogre Vertex Bone Assignment
struct VertexBoneAssignment
{
uint32_t vertexIndex;
uint16_t boneIndex;
float weight;
};
/// Ogre SubMesh
/** @todo Port OgreImporter::SubMesh to this and rename this to SubMesh! */
class SubMesh2
{
public:
/// @note Full list of Ogre types, not all of them are supported and exposed to Assimp.
enum OperationType
{
/// A list of points, 1 vertex per point
OT_POINT_LIST = 1,
/// A list of lines, 2 vertices per line
OT_LINE_LIST = 2,
/// A strip of connected lines, 1 vertex per line plus 1 start vertex
OT_LINE_STRIP = 3,
/// A list of triangles, 3 vertices per triangle
OT_TRIANGLE_LIST = 4,
/// A strip of triangles, 3 vertices for the first triangle, and 1 per triangle after that
OT_TRIANGLE_STRIP = 5,
/// A fan of triangles, 3 vertices for the first triangle, and 1 per triangle after that
OT_TRIANGLE_FAN = 6
};
SubMesh2();
~SubMesh2();
/// Releases all memory that this data structure owns.
/** @note Vertex and index data contains shared ptrs
that are freed automatically. In practice the ref count
should be 0 after this reset. */
void Reset();
/// Covert to Assimp mesh.
aiMesh *ConvertToAssimpMesh(Mesh *parent);
/// SubMesh index.
unsigned int index;
/// SubMesh name.
std::string name;
/// Material used by this submesh.
std::string materialRef;
/// Texture alias information.
std::string textureAliasName;
std::string textureAliasRef;
/// Assimp scene material index used by this submesh.
/** -1 if no material or material could not be imported. */
int materialIndex;
/// Vertex data.
VertexData *vertexData;
/// Index data.
IndexData *indexData;
/// If submesh uses shared geometry from parent mesh.
bool usesSharedVertexData;
/// Operation type.
OperationType operationType;
/// Bone assignments.
std::vector<VertexBoneAssignment> boneAssignments;
};
/// Ogre Mesh
class Mesh
{
public:
Mesh();
~Mesh();
/// Releases all memory that this data structure owns.
void Reset();
/// Returns number of subMeshes.
size_t NumSubMeshes() const;
/// Returns submesh for @c index.
SubMesh2 *SubMesh(uint16_t index) const;
/// Convert mesh to Assimp scene.
void ConvertToAssimpScene(aiScene* dest);
/// Mesh has skeletal animations.
bool hasSkeletalAnimations;
/// Skeleton reference.
std::string skeletonRef;
/// Vertex data
VertexData *sharedVertexData;
/// Sub meshes.
std::vector<SubMesh2*> subMeshes;
/// Animations
std::vector<Animation2*> animations;
/// Bone assignments.
std::vector<VertexBoneAssignment> boneAssignments;
/// Poses
std::vector<Pose*> poses;
};
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGRESTRUCTS_H_INC

View File

@ -0,0 +1,42 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @todo Move XML related serialization from OgreImporter.cpp
here in a similar fashion as OgreBinarySerializer. */

View File

@ -0,0 +1,42 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @todo Move XML related serialization from OgreImporter.cpp
here in a similar fashion as OgreBinarySerializer. */