Model loading and texturing

This commit is contained in:
Dane Johnson
2021-01-18 18:25:47 -06:00
parent 66bf7776c7
commit 155b572aca
1283 changed files with 533814 additions and 42 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,423 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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"
#include <assimp/StreamReader.h>
namespace Assimp
{
namespace Ogre
{
typedef Assimp::StreamReaderLE MemoryStreamReader;
typedef std::shared_ptr<MemoryStreamReader> MemoryStreamReaderPtr;
class OgreBinarySerializer
{
public:
/// Imports mesh and returns the result.
/** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
static Mesh *ImportMesh(MemoryStreamReader *reader);
/// Imports skeleton to @c mesh into Mesh::skeleton.
/** If mesh does not have a skeleton reference or the skeleton file
cannot be found it is not a fatal DeadlyImportError.
@return If skeleton import was successful. */
static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
private:
enum AssetMode
{
AM_Mesh,
AM_Skeleton
};
OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
m_currentLen(0),
m_reader(reader),
assetMode(mode)
{
}
static MemoryStreamReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
// Header
uint16_t ReadHeader(bool readLen = true);
void RollbackHeader();
// Mesh
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(SubMesh *submesh);
void ReadSubMeshTextureAlias(SubMesh *submesh);
void ReadBoneAssignment(VertexData *dest);
void ReadGeometry(VertexData *dest);
void ReadGeometryVertexDeclaration(VertexData *dest);
void ReadGeometryVertexElement(VertexData *dest);
void ReadGeometryVertexBuffer(VertexData *dest);
void ReadEdgeList(Mesh *mesh);
void ReadPoses(Mesh *mesh);
void ReadPoseVertices(Pose *pose);
void ReadAnimations(Mesh *mesh);
void ReadAnimation(Animation *anim);
void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track);
void NormalizeBoneWeights(VertexData *vertexData) const;
// Skeleton
void ReadSkeleton(Skeleton *skeleton);
void ReadBone(Skeleton *skeleton);
void ReadBoneParent(Skeleton *skeleton);
void ReadSkeletonAnimation(Skeleton *skeleton);
void ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest);
void ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest);
void ReadSkeletonAnimationLink(Skeleton *skeleton);
// Reader utils
bool AtEnd() const;
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);
void ReadQuaternion(aiQuaternion &quat);
std::string ReadString(size_t len);
std::string ReadLine();
void SkipBytes(size_t numBytes);
uint32_t m_currentLen;
MemoryStreamReader *m_reader;
AssetMode assetMode;
};
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 "Unknown_MeshChunkId";
}
*/
enum SkeletonChunkId
{
SKELETON_HEADER = 0x1000,
// char* version : Version number check
SKELETON_BLENDMODE = 0x1010, // optional
// unsigned short blendmode : SkeletonAnimationBlendMode
SKELETON_BONE = 0x2000,
// Repeating section defining each bone in the system.
// Bones are assigned indexes automatically based on their order of declaration
// starting with 0.
// char* name : name of the bone
// unsigned short handle : handle of the bone, should be contiguous & start at 0
// Vector3 position : position of this bone relative to parent
// Quaternion orientation : orientation of this bone relative to parent
// Vector3 scale : scale of this bone relative to parent
SKELETON_BONE_PARENT = 0x3000,
// Record of the parent of a single bone, used to build the node tree
// Repeating section, listed in Bone Index order, one per Bone
// unsigned short handle : child bone
// unsigned short parentHandle : parent bone
SKELETON_ANIMATION = 0x4000,
// A single animation for this skeleton
// char* name : Name of the animation
// float length : Length of the animation in seconds
SKELETON_ANIMATION_BASEINFO = 0x4010,
// [Optional] base keyframe information
// char* baseAnimationName (blank for self)
// float baseKeyFrameTime
SKELETON_ANIMATION_TRACK = 0x4100,
// A single animation track (relates to a single bone)
// Repeating section (within SKELETON_ANIMATION)
// unsigned short boneIndex : Index of bone to apply to
SKELETON_ANIMATION_TRACK_KEYFRAME = 0x4110,
// A single keyframe within the track
// Repeating section
// float time : The time position (seconds)
// Quaternion rotate : Rotation to apply at this keyframe
// Vector3 translate : Translation to apply at this keyframe
// Vector3 scale : Scale to apply at this keyframe
SKELETON_ANIMATION_LINK = 0x5000
// Link to another skeleton, to re-use its animations
// char* skeletonName : name of skeleton to get animations from
// float scale : scale to apply to trans/scale keys
};
/*
static std::string SkeletonHeaderToString(SkeletonChunkId id)
{
switch(id)
{
case SKELETON_HEADER: return "HEADER";
case SKELETON_BLENDMODE: return "BLENDMODE";
case SKELETON_BONE: return "BONE";
case SKELETON_BONE_PARENT: return "BONE_PARENT";
case SKELETON_ANIMATION: return "ANIMATION";
case SKELETON_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
case SKELETON_ANIMATION_TRACK: return "ANIMATION_TRACK";
case SKELETON_ANIMATION_TRACK_KEYFRAME: return "ANIMATION_TRACK_KEYFRAME";
case SKELETON_ANIMATION_LINK: return "ANIMATION_LINK";
}
return "Unknown_SkeletonChunkId";
}
*/
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGREBINARYSERIALIZER_H_INC

View File

@@ -0,0 +1,150 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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 "OgreImporter.h"
#include "OgreBinarySerializer.h"
#include "OgreXmlSerializer.h"
#include <assimp/Importer.hpp>
#include <assimp/importerdesc.h>
#include <memory>
static const aiImporterDesc desc = {
"Ogre3D Mesh Importer",
"",
"",
"",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour,
0,
0,
0,
0,
"mesh mesh.xml"
};
namespace Assimp
{
namespace Ogre
{
const aiImporterDesc* OgreImporter::GetInfo() const
{
return &desc;
}
void OgreImporter::SetupProperties(const Importer* pImp)
{
m_userDefinedMaterialLibFile = pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material");
m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
}
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const
{
if (!checkSig) {
return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false);
}
if (EndsWith(pFile, ".mesh.xml", false))
{
const char* tokens[] = { "<mesh>" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
else
{
/// @todo Read and validate first header chunk?
return EndsWith(pFile, ".mesh", false);
}
}
void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler)
{
// Open source file
IOStream *f = pIOHandler->Open(pFile, "rb");
if (!f) {
throw DeadlyImportError("Failed to open file " + pFile);
}
// Binary .mesh import
if (EndsWith(pFile, ".mesh", false))
{
/// @note MemoryStreamReader takes ownership of f.
MemoryStreamReader reader(f);
// Import mesh
std::unique_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader));
// Import skeleton
OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get());
// Import mesh referenced materials
ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
// Convert to Assimp
mesh->ConvertToAssimpScene(pScene);
}
// XML .mesh.xml import
else
{
/// @note XmlReader does not take ownership of f, hence the scoped ptr.
std::unique_ptr<IOStream> scopedFile(f);
std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(scopedFile.get()));
std::unique_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
// Import mesh
std::unique_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get()));
// Import skeleton
OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get());
// Import mesh referenced materials
ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
// Convert to Assimp
mesh->ConvertToAssimpScene(pScene);
}
}
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER

View File

@@ -0,0 +1,102 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include <assimp/BaseImporter.h>
#include "OgreStructs.h"
#include "OgreParsingUtils.h"
#include <assimp/material.h>
namespace Assimp
{
namespace Ogre
{
/** Importer for Ogre mesh, skeleton and material formats.
@todo Support vertex colors.
@todo Support poses/animations from the mesh file.
Currently only skeleton file animations are supported. */
class OgreImporter : public BaseImporter
{
public:
/// BaseImporter override.
virtual bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
/// BaseImporter override.
virtual void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
/// BaseImporter override.
virtual const aiImporterDesc *GetInfo() const;
/// BaseImporter override.
virtual void SetupProperties(const Importer *pImp);
private:
/// Read materials referenced by the @c mesh to @c pScene.
void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh);
void ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh);
void AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials);
/// Reads material
aiMaterial* ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string &MaterialName);
// These functions parse blocks from a material file from @c ss. Starting parsing from "{" and ending it to "}".
bool ReadTechnique(const std::string &techniqueName, std::stringstream &ss, aiMaterial *material);
bool ReadPass(const std::string &passName, std::stringstream &ss, aiMaterial *material);
bool ReadTextureUnit(const std::string &textureUnitName, std::stringstream &ss, aiMaterial *material);
std::string m_userDefinedMaterialLibFile;
bool m_detectTextureTypeFromFilename;
std::map<aiTextureType, unsigned int> m_textures;
};
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGREIMPORTER_H_INC

View File

@@ -0,0 +1,596 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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 "OgreImporter.h"
#include <assimp/TinyFormatter.h>
#include <assimp/material.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/fast_atof.h>
#include <vector>
#include <sstream>
#include <memory>
using namespace std;
namespace Assimp
{
namespace Ogre
{
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)
{
SubMesh *submesh = mesh->GetSubMesh(i);
if (submesh && !submesh->materialRef.empty())
{
aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
if (material)
{
submesh->materialIndex = static_cast<int>(materials.size());
materials.push_back(material);
}
}
}
AssignMaterials(pScene, materials);
}
void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *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)
{
SubMeshXml *submesh = mesh->GetSubMesh( static_cast<uint16_t>(i));
if (submesh && !submesh->materialRef.empty())
{
aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef);
if (material)
{
submesh->materialIndex = static_cast<int>(materials.size());
materials.push_back(material);
}
}
}
AssignMaterials(pScene, materials);
}
void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial*> &materials)
{
pScene->mNumMaterials = static_cast<unsigned int>(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)
{
if (materialName.empty()) {
return 0;
}
// Full reference and examples of Ogre Material Script
// can be found from http://www.ogre3d.org/docs/manual/manual_14.html
/*and here is another one:
import * from abstract_base_passes_depth.material
import * from abstract_base.material
import * from mat_shadow_caster.material
import * from mat_character_singlepass.material
material hero/hair/caster : mat_shadow_caster_skin_areject
{
set $diffuse_map "hero_hair_alpha_c.dds"
}
material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights
{
set $diffuse_map "hero_hair_alpha_c.dds"
set $specular_map "hero_hair_alpha_s.dds"
set $normal_map "hero_hair_alpha_n.dds"
set $light_map "black_lightmap.dds"
set $shadow_caster_material "hero/hair/caster"
}
*/
stringstream ss;
// Scope for scopre_ptr auto release
{
/* There are three .material options in priority order:
1) File with the material name (materialName)
2) File with the mesh files base name (pFile)
3) Optional user defined material library file (m_userDefinedMaterialLibFile) */
std::vector<string> potentialFiles;
potentialFiles.push_back(materialName + ".material");
potentialFiles.push_back(pFile.substr(0, pFile.rfind(".mesh")) + ".material");
if (!m_userDefinedMaterialLibFile.empty())
potentialFiles.push_back(m_userDefinedMaterialLibFile);
IOStream *materialFile = 0;
for(size_t i=0; i<potentialFiles.size(); ++i)
{
materialFile = pIOHandler->Open(potentialFiles[i]);
if (materialFile) {
break;
}
ASSIMP_LOG_DEBUG_F( "Source file for material '", materialName, "' ", potentialFiles[i], " does not exist");
}
if (!materialFile)
{
ASSIMP_LOG_ERROR_F( "Failed to find source file for material '", materialName, "'");
return 0;
}
std::unique_ptr<IOStream> stream(materialFile);
if (stream->FileSize() == 0)
{
ASSIMP_LOG_WARN_F( "Source file for material '", materialName, "' is empty (size is 0 bytes)");
return 0;
}
// Read bytes
vector<char> data(stream->FileSize());
stream->Read(&data[0], stream->FileSize(), 1);
// Convert to UTF-8 and terminate the string for ss
BaseImporter::ConvertToUTF8(data);
data.push_back('\0');
ss << &data[0];
}
ASSIMP_LOG_DEBUG_F("Reading material '", materialName, "'");
aiMaterial *material = new aiMaterial();
m_textures.clear();
aiString ts(materialName);
material->AddProperty(&ts, AI_MATKEY_NAME);
// The stringstream will push words from a line until newline.
// It will also trim whitespace from line start and between words.
string linePart;
ss >> linePart;
const string partMaterial = "material";
const string partTechnique = "technique";
while(!ss.eof())
{
// Skip commented lines
if (linePart == partComment)
{
NextAfterNewLine(ss, linePart);
continue;
}
if (linePart != partMaterial)
{
ss >> linePart;
continue;
}
ss >> linePart;
if (linePart != materialName)
{
ss >> linePart;
continue;
}
NextAfterNewLine(ss, linePart);
if (linePart != partBlockStart)
{
ASSIMP_LOG_ERROR_F( "Invalid material: block start missing near index ", ss.tellg());
return material;
}
ASSIMP_LOG_DEBUG_F("material '", materialName, "'");
while(linePart != partBlockEnd)
{
// Proceed to the first technique
ss >> linePart;
if (linePart == partTechnique)
{
string techniqueName = SkipLine(ss);
ReadTechnique(Trim(techniqueName), ss, material);
}
// Read information from a custom material
/** @todo This "set $x y" does not seem to be a official Ogre material system feature.
Materials can inherit other materials and override texture units by using the (unique)
parent texture unit name in your cloned material.
This is not yet supported and below code is probably some hack from the original
author of this Ogre importer. Should be removed? */
if (linePart=="set")
{
ss >> linePart;
if (linePart=="$specular")//todo load this values:
{
}
else if (linePart=="$diffuse")
{
}
else if (linePart=="$ambient")
{
}
else if (linePart=="$colormap")
{
ss >> linePart;
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
}
else if (linePart=="$normalmap")
{
ss >> linePart;
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
}
else if (linePart=="$shininess_strength")
{
ss >> linePart;
float Shininess = fast_atof(linePart.c_str());
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
}
else if (linePart=="$shininess_exponent")
{
ss >> linePart;
float Shininess = fast_atof(linePart.c_str());
material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS);
}
//Properties from Venetica:
else if (linePart=="$diffuse_map")
{
ss >> linePart;
if (linePart[0] == '"')// "file" -> file
linePart = linePart.substr(1, linePart.size()-2);
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
}
else if (linePart=="$specular_map")
{
ss >> linePart;
if (linePart[0] == '"')// "file" -> file
linePart = linePart.substr(1, linePart.size()-2);
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0));
}
else if (linePart=="$normal_map")
{
ss >> linePart;
if (linePart[0]=='"')// "file" -> file
linePart = linePart.substr(1, linePart.size()-2);
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0));
}
else if (linePart=="$light_map")
{
ss >> linePart;
if (linePart[0]=='"') {
linePart = linePart.substr(1, linePart.size() - 2);
}
aiString ts(linePart);
material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0));
}
}
}
ss >> linePart;
}
return material;
}
bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream &ss, aiMaterial *material)
{
string linePart;
ss >> linePart;
if (linePart != partBlockStart)
{
ASSIMP_LOG_ERROR_F( "Invalid material: Technique block start missing near index ", ss.tellg());
return false;
}
ASSIMP_LOG_DEBUG_F(" technique '", techniqueName, "'");
const string partPass = "pass";
while(linePart != partBlockEnd)
{
ss >> linePart;
// Skip commented lines
if (linePart == partComment)
{
SkipLine(ss);
continue;
}
/// @todo Techniques have other attributes than just passes.
if (linePart == partPass)
{
string passName = SkipLine(ss);
ReadPass(Trim(passName), ss, material);
}
}
return true;
}
bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMaterial *material)
{
string linePart;
ss >> linePart;
if (linePart != partBlockStart)
{
ASSIMP_LOG_ERROR_F( "Invalid material: Pass block start missing near index ", ss.tellg());
return false;
}
ASSIMP_LOG_DEBUG_F(" pass '", passName, "'");
const string partAmbient = "ambient";
const string partDiffuse = "diffuse";
const string partSpecular = "specular";
const string partEmissive = "emissive";
const string partTextureUnit = "texture_unit";
while(linePart != partBlockEnd)
{
ss >> linePart;
// Skip commented lines
if (linePart == partComment)
{
SkipLine(ss);
continue;
}
// Colors
/// @todo Support alpha via aiColor4D.
if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive)
{
float r, g, b;
ss >> r >> g >> b;
const aiColor3D color(r, g, b);
ASSIMP_LOG_DEBUG_F( " ", linePart, " ", r, " ", g, " ", b);
if (linePart == partAmbient)
{
material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT);
}
else if (linePart == partDiffuse)
{
material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
}
else if (linePart == partSpecular)
{
material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR);
}
else if (linePart == partEmissive)
{
material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE);
}
}
else if (linePart == partTextureUnit)
{
string textureUnitName = SkipLine(ss);
ReadTextureUnit(Trim(textureUnitName), ss, material);
}
}
return true;
}
bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstream &ss, aiMaterial *material)
{
string linePart;
ss >> linePart;
if (linePart != partBlockStart)
{
ASSIMP_LOG_ERROR_F( "Invalid material: Texture unit block start missing near index ", ss.tellg());
return false;
}
ASSIMP_LOG_DEBUG_F(" texture_unit '", textureUnitName, "'");
const string partTexture = "texture";
const string partTextCoordSet = "tex_coord_set";
const string partColorOp = "colour_op";
aiTextureType textureType = aiTextureType_NONE;
std::string textureRef;
int uvCoord = 0;
while(linePart != partBlockEnd)
{
ss >> linePart;
// Skip commented lines
if (linePart == partComment)
{
SkipLine(ss);
continue;
}
if (linePart == partTexture)
{
ss >> linePart;
textureRef = linePart;
// User defined Assimp config property to detect texture type from filename.
if (m_detectTextureTypeFromFilename)
{
size_t posSuffix = textureRef.find_last_of(".");
size_t posUnderscore = textureRef.find_last_of("_");
if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore)
{
string identifier = Ogre::ToLower(textureRef.substr(posUnderscore, posSuffix - posUnderscore));
ASSIMP_LOG_DEBUG_F( "Detecting texture type from filename postfix '", identifier, "'");
if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap")
{
textureType = aiTextureType_NORMALS;
}
else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap")
{
textureType = aiTextureType_SPECULAR;
}
else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion")
{
textureType = aiTextureType_LIGHTMAP;
}
else if (identifier == "_disp" || identifier == "_displacement")
{
textureType = aiTextureType_DISPLACEMENT;
}
else
{
textureType = aiTextureType_DIFFUSE;
}
}
else
{
textureType = aiTextureType_DIFFUSE;
}
}
// Detect from texture unit name. This cannot be too broad as
// authors might give names like "LightSaber" or "NormalNinja".
else
{
string unitNameLower = Ogre::ToLower(textureUnitName);
if (unitNameLower.find("normalmap") != string::npos)
{
textureType = aiTextureType_NORMALS;
}
else if (unitNameLower.find("specularmap") != string::npos)
{
textureType = aiTextureType_SPECULAR;
}
else if (unitNameLower.find("lightmap") != string::npos)
{
textureType = aiTextureType_LIGHTMAP;
}
else if (unitNameLower.find("displacementmap") != string::npos)
{
textureType = aiTextureType_DISPLACEMENT;
}
else
{
textureType = aiTextureType_DIFFUSE;
}
}
}
else if (linePart == partTextCoordSet)
{
ss >> uvCoord;
}
/// @todo Implement
else if(linePart == partColorOp)
{
/*
ss >> linePart;
if("replace"==linePart)//I don't think, assimp has something for this...
{
}
else if("modulate"==linePart)
{
//TODO: set value
//material->AddProperty(aiTextureOp_Multiply)
}
*/
}
}
if (textureRef.empty())
{
ASSIMP_LOG_WARN("Texture reference is empty, ignoring texture_unit.");
return false;
}
if (textureType == aiTextureType_NONE)
{
ASSIMP_LOG_WARN("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit.");
return false;
}
unsigned int textureTypeIndex = m_textures[textureType];
m_textures[textureType]++;
ASSIMP_LOG_DEBUG_F( " texture '", textureRef, "' type ", textureType,
" index ", textureTypeIndex, " UV ", uvCoord);
aiString assimpTextureRef(textureRef);
material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex));
material->AddProperty(&uvCoord, 1, AI_MATKEY_UVWSRC(textureType, textureTypeIndex));
return true;
}
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER

View File

@@ -0,0 +1,136 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include <assimp/ParsingUtils.h>
#include <functional>
#include <algorithm>
#include <stdint.h>
#include <sstream>
#include <cctype>
namespace Assimp {
namespace Ogre {
/// Returns a lower cased copy of @s.
static AI_FORCE_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 AI_FORCE_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 AI_FORCE_INLINE
std::string &TrimLeft(std::string &s, bool newlines = true) {
if (!newlines) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace<char>(c); }));
} else {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
}
return s;
}
/// Trim from end
static AI_FORCE_INLINE
std::string &TrimRight(std::string &s, bool newlines = true) {
if (!newlines) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace<char>(c); }).base(),s.end());
} else {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine<char>(c); }));
}
return s;
}
/// Trim from both ends
static AI_FORCE_INLINE
std::string &Trim(std::string &s, bool newlines = true) {
return TrimLeft(TrimRight(s, newlines), newlines);
}
/// Skips a line from current @ss position until a newline. Returns the skipped part.
static AI_FORCE_INLINE
std::string SkipLine(std::stringstream &ss) {
std::string skipped;
getline(ss, skipped);
return skipped;
}
/// Skips a line and reads next element from @c ss to @c nextElement.
/** @return Skipped line content until newline. */
static AI_FORCE_INLINE
std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) {
std::string skipped = SkipLine(ss);
ss >> nextElement;
return skipped;
}
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGREPARSINGUTILS_H_INC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,696 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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 <assimp/MemoryIOWrapper.h>
#include <memory>
#include <assimp/mesh.h>
#include <map>
#include <vector>
#include <set>
struct aiNodeAnim;
struct aiAnimation;
struct aiNode;
struct aiMaterial;
struct aiScene;
/** @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 MeshXml;
class SubMesh;
class SubMeshXml;
class Skeleton;
#define OGRE_SAFE_DELETE(p) delete p; p=0;
// Typedefs
typedef Assimp::MemoryIOStream MemoryStream;
typedef std::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 Bone Assignment
struct VertexBoneAssignment
{
uint32_t vertexIndex;
uint16_t boneIndex;
float weight;
};
typedef std::vector<VertexBoneAssignment> VertexBoneAssignmentList;
typedef std::map<uint32_t, VertexBoneAssignmentList > VertexBoneAssignmentsMap;
typedef std::map<uint16_t, std::vector<aiVertexWeight> > AssimpVertexBoneWeightList;
// Ogre Vertex Data interface, inherited by the binary and XML implementations.
class IVertexData
{
public:
IVertexData();
/// Returns if bone assignments are available.
bool HasBoneAssignments() const;
/// Add vertex mapping from old to new index.
void AddVertexMapping(uint32_t oldIndex, uint32_t newIndex);
/// Returns re-mapped bone assignments.
/** @note Uses mappings added via AddVertexMapping. */
AssimpVertexBoneWeightList AssimpBoneWeights(size_t vertices);
/// Returns a set of bone indexes that are referenced by bone assignments (weights).
std::set<uint16_t> ReferencedBonesByWeights() const;
/// Vertex count.
uint32_t count;
/// Bone assignments.
VertexBoneAssignmentList boneAssignments;
private:
void BoneAssignmentsForVertex(uint32_t currentIndex, uint32_t newIndex, VertexBoneAssignmentList &dest) const;
std::map<uint32_t, std::vector<uint32_t> > vertexIndexMapping;
VertexBoneAssignmentsMap boneAssignmentsMap;
};
// Ogre Vertex Data
class VertexData : public IVertexData
{
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 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;
};
typedef std::vector<Pose*> PoseList;
/// Ogre Pose Key Frame Ref
struct PoseRef
{
uint16_t index;
float influence;
};
typedef std::vector<PoseRef> PoseRefList;
/// Ogre Pose Key Frame
struct PoseKeyFrame
{
/// Time position in the animation.
float timePos;
PoseRefList references;
};
typedef std::vector<PoseKeyFrame> PoseKeyFrameList;
/// Ogre Morph Key Frame
struct MorphKeyFrame
{
/// Time position in the animation.
float timePos;
MemoryStreamPtr buffer;
};
typedef std::vector<MorphKeyFrame> MorphKeyFrameList;
/// Ogre animation key frame
struct TransformKeyFrame
{
TransformKeyFrame();
aiMatrix4x4 Transform();
float timePos;
aiQuaternion rotation;
aiVector3D position;
aiVector3D scale;
};
typedef std::vector<TransformKeyFrame> TransformKeyFrameList;
/// 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,
/// Keyframe that has its on pos, rot and scale for a time position
VAT_TRANSFORM = 3
};
VertexAnimationTrack();
/// Convert to Assimp node animation.
aiNodeAnim *ConvertToAssimpAnimationNode(Skeleton *skeleton);
// Animation type.
Type type;
/// Vertex data target.
/** 0 == shared geometry
>0 == submesh index + 1 */
uint16_t target;
/// Only valid for VAT_TRANSFORM.
std::string boneName;
/// Only one of these will contain key frames, depending on the type enum.
PoseKeyFrameList poseKeyFrames;
MorphKeyFrameList morphKeyFrames;
TransformKeyFrameList transformKeyFrames;
};
typedef std::vector<VertexAnimationTrack> VertexAnimationTrackList;
/// Ogre Animation
class Animation
{
public:
explicit Animation(Skeleton *parent);
explicit Animation(Mesh *parent);
/// Returns the associated vertex data for a track in this animation.
/** @note Only valid to call when parent Mesh is set. */
VertexData *AssociatedVertexData(VertexAnimationTrack *track) const;
/// Convert to Assimp animation.
aiAnimation *ConvertToAssimpAnimation();
/// Parent mesh.
/** @note Set only when animation is read from a mesh. */
Mesh *parentMesh;
/// Parent skeleton.
/** @note Set only when animation is read from a skeleton. */
Skeleton *parentSkeleton;
/// Animation name.
std::string name;
/// Base animation name.
std::string baseName;
/// Length in seconds.
float length;
/// Base animation key time.
float baseTime;
/// Animation tracks.
VertexAnimationTrackList tracks;
};
typedef std::vector<Animation*> AnimationList;
/// Ogre Bone
class Bone
{
public:
Bone();
/// Returns if this bone is parented.
bool IsParented() const;
/// Parent index as uint16_t. Internally int32_t as -1 means unparented.
uint16_t ParentId() const;
/// Add child bone.
void AddChild(Bone *bone);
/// Calculates the world matrix for bone and its children.
void CalculateWorldMatrixAndDefaultPose(Skeleton *skeleton);
/// Convert to Assimp node (animation nodes).
aiNode *ConvertToAssimpNode(Skeleton *parent, aiNode *parentNode = 0);
/// Convert to Assimp bone (mesh bones).
aiBone *ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights);
uint16_t id;
std::string name;
Bone *parent;
int32_t parentId;
std::vector<uint16_t> children;
aiVector3D position;
aiQuaternion rotation;
aiVector3D scale;
aiMatrix4x4 worldMatrix;
aiMatrix4x4 defaultPose;
};
typedef std::vector<Bone*> BoneList;
/// Ogre Skeleton
class Skeleton
{
public:
enum BlendMode
{
/// Animations are applied by calculating a weighted average of all animations
ANIMBLEND_AVERAGE = 0,
/// Animations are applied by calculating a weighted cumulative total
ANIMBLEND_CUMULATIVE = 1
};
Skeleton();
~Skeleton();
/// Releases all memory that this data structure owns.
void Reset();
/// Returns unparented root bones.
BoneList RootBones() const;
/// Returns number of unparented root bones.
size_t NumRootBones() const;
/// Get bone by name.
Bone *BoneByName(const std::string &name) const;
/// Get bone by id.
Bone *BoneById(uint16_t id) const;
BoneList bones;
AnimationList animations;
/// @todo Take blend mode into account, but where?
BlendMode blendMode;
};
/// Ogre Sub Mesh interface, inherited by the binary and XML implementations.
class ISubMesh
{
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
};
ISubMesh();
/// 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;
/// If submesh uses shared geometry from parent mesh.
bool usesSharedVertexData;
/// Operation type.
OperationType operationType;
};
/// Ogre SubMesh
class SubMesh : public ISubMesh
{
public:
SubMesh();
~SubMesh();
/// 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);
/// Vertex data.
VertexData *vertexData;
/// Index data.
IndexData *indexData;
};
typedef std::vector<SubMesh*> SubMeshList;
/// Ogre Mesh
class Mesh
{
public:
/// Constructor.
Mesh();
/// Destructor.
~Mesh();
/// Releases all memory that this data structure owns.
void Reset();
/// Returns number of subMeshes.
size_t NumSubMeshes() const;
/// Returns submesh for @c index.
SubMesh *GetSubMesh( size_t index) const;
/// Convert mesh to Assimp scene.
void ConvertToAssimpScene(aiScene* dest);
/// Mesh has skeletal animations.
bool hasSkeletalAnimations;
/// Skeleton reference.
std::string skeletonRef;
/// Skeleton.
Skeleton *skeleton;
/// Vertex data
VertexData *sharedVertexData;
/// Sub meshes.
SubMeshList subMeshes;
/// Animations
AnimationList animations;
/// Poses
PoseList poses;
};
/// Ogre XML Vertex Data
class VertexDataXml : public IVertexData
{
public:
VertexDataXml();
bool HasPositions() const;
bool HasNormals() const;
bool HasTangents() const;
bool HasUvs() const;
size_t NumUvs() const;
std::vector<aiVector3D> positions;
std::vector<aiVector3D> normals;
std::vector<aiVector3D> tangents;
std::vector<std::vector<aiVector3D> > uvs;
};
/// Ogre XML Index Data
class IndexDataXml
{
public:
IndexDataXml() : faceCount(0) {}
/// Face count.
uint32_t faceCount;
std::vector<aiFace> faces;
};
/// Ogre XML SubMesh
class SubMeshXml : public ISubMesh
{
public:
SubMeshXml();
~SubMeshXml();
/// Releases all memory that this data structure owns.
void Reset();
aiMesh *ConvertToAssimpMesh(MeshXml *parent);
IndexDataXml *indexData;
VertexDataXml *vertexData;
};
typedef std::vector<SubMeshXml*> SubMeshXmlList;
/// Ogre XML Mesh
class MeshXml
{
public:
MeshXml();
~MeshXml();
/// Releases all memory that this data structure owns.
void Reset();
/// Returns number of subMeshes.
size_t NumSubMeshes() const;
/// Returns submesh for @c index.
SubMeshXml *GetSubMesh(uint16_t index) const;
/// Convert mesh to Assimp scene.
void ConvertToAssimpScene(aiScene* dest);
/// Skeleton reference.
std::string skeletonRef;
/// Skeleton.
Skeleton *skeleton;
/// Vertex data
VertexDataXml *sharedVertexData;
/// Sub meshes.
SubMeshXmlList subMeshes;
};
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGRESTRUCTS_H_INC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,118 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2019, 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_OGREXMLSERIALIZER_H_INC
#define AI_OGREXMLSERIALIZER_H_INC
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "OgreStructs.h"
#include <assimp/irrXMLWrapper.h>
namespace Assimp
{
namespace Ogre
{
typedef irr::io::IrrXMLReader XmlReader;
typedef std::shared_ptr<XmlReader> XmlReaderPtr;
class OgreXmlSerializer
{
public:
/// Imports mesh and returns the result.
/** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
static MeshXml *ImportMesh(XmlReader *reader);
/// Imports skeleton to @c mesh.
/** If mesh does not have a skeleton reference or the skeleton file
cannot be found it is not a fatal DeadlyImportError.
@return If skeleton import was successful. */
static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
private:
explicit OgreXmlSerializer(XmlReader *reader) :
m_reader(reader)
{
}
static XmlReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
// Mesh
void ReadMesh(MeshXml *mesh);
void ReadSubMesh(MeshXml *mesh);
void ReadGeometry(VertexDataXml *dest);
void ReadGeometryVertexBuffer(VertexDataXml *dest);
void ReadBoneAssignments(VertexDataXml *dest);
// Skeleton
void ReadSkeleton(Skeleton *skeleton);
void ReadBones(Skeleton *skeleton);
void ReadBoneHierarchy(Skeleton *skeleton);
void ReadAnimations(Skeleton *skeleton);
void ReadAnimationTracks(Animation *dest);
void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest);
template<typename T>
T ReadAttribute(const char *name) const;
bool HasAttribute(const char *name) const;
std::string &NextNode();
std::string &SkipCurrentNode();
bool CurrentNodeNameEquals(const std::string &name) const;
std::string CurrentNodeName(bool forceRead = false);
XmlReader *m_reader;
std::string m_currentNodeName;
};
} // Ogre
} // Assimp
#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
#endif // AI_OGREXMLSERIALIZER_H_INC