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.
parent
36c08a0a7d
commit
4b16b182be
|
@ -322,8 +322,14 @@ SOURCE_GROUP( Obj FILES ${Obj_SRCS})
|
|||
|
||||
SET( Ogre_SRCS
|
||||
OgreImporter.h
|
||||
OgreStructs.h
|
||||
OgreParsingUtils.h
|
||||
OgreBinarySerializer.h
|
||||
OgreXmlSerializer.h
|
||||
OgreImporter.cpp
|
||||
OgreStructs.cpp
|
||||
OgreBinarySerializer.cpp
|
||||
OgreXmlSerializer.cpp
|
||||
OgreMaterial.cpp
|
||||
OgreMesh.cpp
|
||||
OgreSkeleton.cpp
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <istream>
|
||||
|
||||
#include "OgreImporter.h"
|
||||
#include "OgreBinarySerializer.h"
|
||||
|
||||
#include "TinyFormatter.h"
|
||||
#include "irrXMLWrapper.h"
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Ogre XML Mesh Importer",
|
||||
"Ogre3D Mesh Importer",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
aiImporterFlags_SupportTextFlavour,
|
||||
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"mesh.xml"
|
||||
"mesh mesh.xml"
|
||||
};
|
||||
|
||||
using namespace std;
|
||||
|
@ -83,11 +86,18 @@ void OgreImporter::SetupProperties(const Importer* pImp)
|
|||
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
|
||||
{
|
||||
if (!checkSig) {
|
||||
return EndsWith(pFile, ".mesh.xml", false);
|
||||
return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false);
|
||||
}
|
||||
|
||||
const char* tokens[] = { "<mesh>" };
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
|
||||
if (EndsWith(pFile, ".mesh.xml", false))
|
||||
{
|
||||
const char* tokens[] = { "<mesh>" };
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return EndsWith(pFile, ".mesh", false);
|
||||
}
|
||||
}
|
||||
|
||||
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
|
||||
|
@ -95,12 +105,30 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
|||
// -------------------- Initial file and XML operations --------------------
|
||||
|
||||
// Open
|
||||
boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile));
|
||||
if (!file.get()) {
|
||||
IOStream *f = pIOHandler->Open(pFile, "rb");
|
||||
if (!f) {
|
||||
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
|
||||
boost::scoped_ptr<IOStream> file(f);
|
||||
boost::scoped_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(file.get()));
|
||||
boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
|
||||
if (!reader) {
|
||||
|
@ -153,18 +181,19 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
|||
SubMesh* submesh = new SubMesh();
|
||||
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.
|
||||
Does Assimp require there to be a valid material index for each mesh,
|
||||
even if its a dummy material. */
|
||||
aiMaterial* material = ReadMaterial(pFile, pIOHandler, submesh->MaterialName);
|
||||
materials.push_back(material);
|
||||
if (!material)
|
||||
material = new aiMaterial();
|
||||
if (material)
|
||||
{
|
||||
submesh->MaterialIndex = materials.size();
|
||||
materials.push_back(material);
|
||||
}
|
||||
|
||||
subMeshes.push_back(boost::shared_ptr<SubMesh>(submesh));
|
||||
}
|
||||
|
||||
if (subMeshes.empty()) {
|
||||
|
@ -223,10 +252,12 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
|||
// -------------------- Apply to aiScene --------------------
|
||||
|
||||
// Materials
|
||||
pScene->mMaterials = new aiMaterial*[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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
#define AI_OGREIMPORTER_H_INC
|
||||
|
@ -5,6 +44,8 @@
|
|||
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
|
||||
|
||||
#include "BaseImporter.h"
|
||||
|
||||
#include "OgreStructs.h"
|
||||
#include "OgreParsingUtils.h"
|
||||
|
||||
namespace Assimp
|
||||
|
@ -114,6 +155,9 @@ private:
|
|||
|
||||
//-------------------------------- 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
|
||||
aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string MaterialName);
|
||||
|
||||
|
|
|
@ -59,11 +59,40 @@ static const string partComment = "//";
|
|||
static const string partBlockStart = "{";
|
||||
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)
|
||||
{
|
||||
/// @todo Should we return null ptr here or a empty material?
|
||||
if (materialName.empty()) {
|
||||
return new aiMaterial();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Full reference and examples of Ogre Material Script
|
||||
|
@ -117,17 +146,15 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
|
|||
}
|
||||
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 << "'");
|
||||
return new aiMaterial();
|
||||
return 0;
|
||||
}
|
||||
|
||||
boost::scoped_ptr<IOStream> stream(materialFile);
|
||||
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)");
|
||||
return new aiMaterial();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read bytes
|
||||
|
|
|
@ -469,7 +469,8 @@ aiMesh *OgreImporter::CreateAssimpSubMesh(aiScene *pScene, const SubMesh& submes
|
|||
aiMesh *dest = new aiMesh();
|
||||
|
||||
// Material
|
||||
dest->mMaterialIndex = submesh.MaterialIndex;
|
||||
if (submesh.MaterialIndex != -1)
|
||||
dest->mMaterialIndex = submesh.MaterialIndex;
|
||||
|
||||
// Positions
|
||||
dest->mVertices = new aiVector3D[submesh.Positions.size()];
|
||||
|
|
|
@ -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
|
||||
#define AI_OGREPARSINGUTILS_H_INC
|
||||
|
@ -13,6 +52,70 @@ namespace Assimp
|
|||
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;
|
||||
|
||||
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<>
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
|
@ -143,70 +246,6 @@ static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &n
|
|||
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
|
||||
} // Assimp
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ Open Asset Import Library (assimp)
|
|||
Copyright (c) 2006-2012, assimp team
|
||||
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
|
||||
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
|
||||
following disclaimer.
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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. */
|
|
@ -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. */
|
Loading…
Reference in New Issue