2014-05-18 08:57:44 +00:00
/*
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 " ;
}
2014-05-20 01:52:53 +00:00
// IVertexData
2014-05-18 08:57:44 +00:00
2014-05-20 01:52:53 +00:00
IVertexData : : IVertexData ( ) :
2014-05-18 08:57:44 +00:00
count ( 0 )
{
}
2014-05-20 01:52:53 +00:00
bool IVertexData : : HasBoneAssignments ( ) const
{
return ! boneAssignments . empty ( ) ;
}
void IVertexData : : AddVertexMapping ( uint32_t oldIndex , uint32_t newIndex )
{
BoneAssignmentsForVertex ( oldIndex , newIndex , boneAssignmentsMap [ newIndex ] ) ;
vertexIndexMapping [ oldIndex ] . push_back ( newIndex ) ;
}
void IVertexData : : BoneAssignmentsForVertex ( uint32_t currentIndex , uint32_t newIndex , VertexBoneAssignmentList & dest ) const
{
for ( VertexBoneAssignmentList : : const_iterator iter = boneAssignments . begin ( ) , end = boneAssignments . end ( ) ;
iter ! = end ; + + iter )
{
if ( iter - > vertexIndex = = currentIndex )
{
VertexBoneAssignment a = ( * iter ) ;
a . vertexIndex = newIndex ;
dest . push_back ( a ) ;
}
}
}
AssimpVertexBoneWeightList IVertexData : : AssimpBoneWeights ( size_t vertices )
{
AssimpVertexBoneWeightList weights ;
for ( size_t vi = 0 ; vi < vertices ; + + vi )
{
VertexBoneAssignmentList & vertexWeights = boneAssignmentsMap [ vi ] ;
for ( VertexBoneAssignmentList : : const_iterator iter = vertexWeights . begin ( ) , end = vertexWeights . end ( ) ;
iter ! = end ; + + iter )
{
std : : vector < aiVertexWeight > & boneWeights = weights [ iter - > boneIndex ] ;
boneWeights . push_back ( aiVertexWeight ( vi , iter - > weight ) ) ;
}
}
return weights ;
}
std : : set < uint16_t > IVertexData : : ReferencedBonesByWeights ( ) const
{
std : : set < uint16_t > referenced ;
for ( VertexBoneAssignmentList : : const_iterator iter = boneAssignments . begin ( ) , end = boneAssignments . end ( ) ;
iter ! = end ; + + iter )
{
referenced . insert ( iter - > boneIndex ) ;
}
return referenced ;
}
// VertexData
VertexData : : VertexData ( )
{
}
2014-05-18 08:57:44 +00:00
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 ( ) )
2014-06-10 16:58:02 +00:00
return vertexBindings [ source ] . get ( ) ;
2014-05-18 08:57:44 +00:00
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 ;
}
2014-05-20 01:52:53 +00:00
// VertexDataXml
VertexDataXml : : VertexDataXml ( )
{
}
2014-05-21 01:37:45 +00:00
bool VertexDataXml : : HasPositions ( ) const
{
return ! positions . empty ( ) ;
}
2014-05-20 01:52:53 +00:00
bool VertexDataXml : : HasNormals ( ) const
{
return ! normals . empty ( ) ;
}
bool VertexDataXml : : HasTangents ( ) const
{
return ! tangents . empty ( ) ;
}
bool VertexDataXml : : HasUvs ( ) const
{
return ! uvs . empty ( ) ;
}
size_t VertexDataXml : : NumUvs ( ) const
{
return uvs . size ( ) ;
}
2014-05-18 08:57:44 +00:00
// 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 ) ,
2014-05-20 01:52:53 +00:00
skeleton ( 0 ) ,
2014-05-18 08:57:44 +00:00
hasSkeletalAnimations ( false )
{
}
Mesh : : ~ Mesh ( )
{
Reset ( ) ;
}
void Mesh : : Reset ( )
{
2014-05-20 01:52:53 +00:00
OGRE_SAFE_DELETE ( skeleton )
2014-05-18 08:57:44 +00:00
OGRE_SAFE_DELETE ( sharedVertexData )
2014-05-18 09:30:16 +00:00
2014-05-18 08:57:44 +00:00
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 ( ) ;
}
2014-05-20 01:52:53 +00:00
SubMesh * Mesh : : GetSubMesh ( uint16_t index ) const
2014-05-18 08:57:44 +00:00
{
for ( size_t i = 0 ; i < subMeshes . size ( ) ; + + i )
if ( subMeshes [ i ] - > index = = index )
return subMeshes [ i ] ;
return 0 ;
}
void Mesh : : ConvertToAssimpScene ( aiScene * dest )
{
2014-05-20 01:52:53 +00:00
// Setup
2014-05-18 08:57:44 +00:00
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 ] ;
2014-05-20 01:52:53 +00:00
// Export meshes
for ( size_t i = 0 ; i < dest - > mNumMeshes ; + + i )
{
2014-05-18 08:57:44 +00:00
dest - > mMeshes [ i ] = subMeshes [ i ] - > ConvertToAssimpMesh ( this ) ;
dest - > mRootNode - > mMeshes [ i ] = i ;
}
2014-05-21 01:00:11 +00:00
// Export skeleton
if ( skeleton )
{
// Bones
if ( ! skeleton - > bones . empty ( ) )
{
BoneList rootBones = skeleton - > RootBones ( ) ;
dest - > mRootNode - > mNumChildren = rootBones . size ( ) ;
dest - > mRootNode - > mChildren = new aiNode * [ dest - > mRootNode - > mNumChildren ] ;
for ( size_t i = 0 , len = rootBones . size ( ) ; i < len ; + + i )
{
dest - > mRootNode - > mChildren [ i ] = rootBones [ i ] - > ConvertToAssimpNode ( skeleton , dest - > mRootNode ) ;
}
}
// Animations
if ( ! skeleton - > animations . empty ( ) )
{
dest - > mNumAnimations = skeleton - > animations . size ( ) ;
dest - > mAnimations = new aiAnimation * [ dest - > mNumAnimations ] ;
for ( size_t i = 0 , len = skeleton - > animations . size ( ) ; i < len ; + + i )
{
dest - > mAnimations [ i ] = skeleton - > animations [ i ] - > ConvertToAssimpAnimation ( ) ;
}
}
}
2014-05-18 08:57:44 +00:00
}
2014-05-20 01:52:53 +00:00
// ISubMesh
2014-05-18 08:57:44 +00:00
2014-05-20 01:52:53 +00:00
ISubMesh : : ISubMesh ( ) :
2014-05-18 08:57:44 +00:00
index ( 0 ) ,
2014-05-20 01:52:53 +00:00
materialIndex ( - 1 ) ,
2014-05-18 08:57:44 +00:00
usesSharedVertexData ( false ) ,
2014-05-20 01:52:53 +00:00
operationType ( OT_POINT_LIST )
{
}
// SubMesh
SubMesh : : SubMesh ( ) :
vertexData ( 0 ) ,
indexData ( new IndexData ( ) )
2014-05-18 08:57:44 +00:00
{
}
2014-05-20 01:52:53 +00:00
SubMesh : : ~ SubMesh ( )
2014-05-18 08:57:44 +00:00
{
Reset ( ) ;
}
2014-05-20 01:52:53 +00:00
void SubMesh : : Reset ( )
2014-05-18 08:57:44 +00:00
{
OGRE_SAFE_DELETE ( vertexData )
OGRE_SAFE_DELETE ( indexData )
}
2014-05-20 01:52:53 +00:00
aiMesh * SubMesh : : ConvertToAssimpMesh ( Mesh * parent )
2014-05-18 08:57:44 +00:00
{
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 ) ;
2014-05-20 01:52:53 +00:00
bool boneAssignments = src - > HasBoneAssignments ( ) ;
2014-05-18 08:57:44 +00:00
// 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 ] ;
2014-05-20 01:52:53 +00:00
src - > AddVertexMapping ( ogreVertexIndex , newIndex ) ;
2014-05-18 08:57:44 +00:00
// 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 ) ;
2014-05-21 01:37:45 +00:00
uv1Dest [ newIndex ] . y = ( uv1Dest [ newIndex ] . y * - 1 ) + 1 ; // Flip UV from Ogre to Assimp form
2014-05-18 08:57:44 +00:00
}
// UV1
if ( uv2 & & uv2Dest )
{
uv2 - > Seek ( ( vWidthUv2 * ogreVertexIndex ) + uv2Element - > offset , aiOrigin_SET ) ;
uv2 - > Read ( & uv2Dest [ newIndex ] , sizeUv2 , 1 ) ;
2014-05-21 01:37:45 +00:00
uv2Dest [ newIndex ] . y = ( uv2Dest [ newIndex ] . y * - 1 ) + 1 ; // Flip UV from Ogre to Assimp form
2014-05-18 08:57:44 +00:00
}
2014-05-20 01:52:53 +00:00
}
}
2014-05-21 01:00:11 +00:00
2014-05-20 01:52:53 +00:00
// Bones and bone weights
if ( parent - > skeleton & & boneAssignments )
{
AssimpVertexBoneWeightList weights = src - > AssimpBoneWeights ( dest - > mNumVertices ) ;
std : : set < uint16_t > referencedBones = src - > ReferencedBonesByWeights ( ) ;
dest - > mNumBones = referencedBones . size ( ) ;
dest - > mBones = new aiBone * [ dest - > mNumBones ] ;
size_t assimpBoneIndex = 0 ;
for ( std : : set < uint16_t > : : const_iterator rbIter = referencedBones . begin ( ) , rbEnd = referencedBones . end ( ) ; rbIter ! = rbEnd ; + + rbIter , + + assimpBoneIndex )
{
Bone * bone = parent - > skeleton - > BoneById ( ( * rbIter ) ) ;
dest - > mBones [ assimpBoneIndex ] = bone - > ConvertToAssimpBone ( parent - > skeleton , weights [ bone - > id ] ) ;
}
}
return dest ;
}
// MeshXml
MeshXml : : MeshXml ( ) :
sharedVertexData ( 0 ) ,
skeleton ( 0 )
{
}
MeshXml : : ~ MeshXml ( )
{
Reset ( ) ;
}
void MeshXml : : Reset ( )
{
OGRE_SAFE_DELETE ( skeleton )
OGRE_SAFE_DELETE ( sharedVertexData )
for ( size_t i = 0 , len = subMeshes . size ( ) ; i < len ; + + i ) {
OGRE_SAFE_DELETE ( subMeshes [ i ] )
}
subMeshes . clear ( ) ;
}
size_t MeshXml : : NumSubMeshes ( ) const
{
return subMeshes . size ( ) ;
}
SubMeshXml * MeshXml : : GetSubMesh ( uint16_t index ) const
{
for ( size_t i = 0 ; i < subMeshes . size ( ) ; + + i )
if ( subMeshes [ i ] - > index = = index )
return subMeshes [ i ] ;
return 0 ;
}
void MeshXml : : ConvertToAssimpScene ( aiScene * dest )
{
// Setup
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 ] ;
// Export meshes
for ( size_t i = 0 ; i < dest - > mNumMeshes ; + + i )
{
dest - > mMeshes [ i ] = subMeshes [ i ] - > ConvertToAssimpMesh ( this ) ;
dest - > mRootNode - > mMeshes [ i ] = i ;
}
// Export skeleton
if ( skeleton )
{
// Bones
if ( ! skeleton - > bones . empty ( ) )
{
BoneList rootBones = skeleton - > RootBones ( ) ;
dest - > mRootNode - > mNumChildren = rootBones . size ( ) ;
dest - > mRootNode - > mChildren = new aiNode * [ dest - > mRootNode - > mNumChildren ] ;
for ( size_t i = 0 , len = rootBones . size ( ) ; i < len ; + + i )
{
dest - > mRootNode - > mChildren [ i ] = rootBones [ i ] - > ConvertToAssimpNode ( skeleton , dest - > mRootNode ) ;
}
}
// Animations
if ( ! skeleton - > animations . empty ( ) )
{
dest - > mNumAnimations = skeleton - > animations . size ( ) ;
dest - > mAnimations = new aiAnimation * [ dest - > mNumAnimations ] ;
for ( size_t i = 0 , len = skeleton - > animations . size ( ) ; i < len ; + + i )
{
dest - > mAnimations [ i ] = skeleton - > animations [ i ] - > ConvertToAssimpAnimation ( ) ;
}
}
}
}
// SubMeshXml
SubMeshXml : : SubMeshXml ( ) :
vertexData ( 0 ) ,
indexData ( new IndexDataXml ( ) )
{
}
SubMeshXml : : ~ SubMeshXml ( )
{
Reset ( ) ;
}
void SubMeshXml : : Reset ( )
{
OGRE_SAFE_DELETE ( indexData )
OGRE_SAFE_DELETE ( vertexData )
}
aiMesh * SubMeshXml : : ConvertToAssimpMesh ( MeshXml * parent )
{
aiMesh * dest = new aiMesh ( ) ;
dest - > mPrimitiveTypes = aiPrimitiveType_TRIANGLE ;
if ( ! name . empty ( ) )
dest - > mName = name ;
// Material index
if ( materialIndex ! = - 1 )
dest - > mMaterialIndex = materialIndex ;
// 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 ] ;
VertexDataXml * src = ( ! usesSharedVertexData ? vertexData : parent - > sharedVertexData ) ;
bool boneAssignments = src - > HasBoneAssignments ( ) ;
bool normals = src - > HasNormals ( ) ;
size_t uvs = src - > NumUvs ( ) ;
// Prepare normals
if ( normals )
dest - > mNormals = new aiVector3D [ dest - > mNumVertices ] ;
// Prepare UVs
for ( size_t uvi = 0 ; uvi < uvs ; + + uvi )
{
dest - > mNumUVComponents [ uvi ] = 2 ;
dest - > mTextureCoords [ uvi ] = new aiVector3D [ dest - > mNumVertices ] ;
}
for ( size_t fi = 0 ; fi < dest - > mNumFaces ; + + fi )
{
// Source Ogre face
aiFace & ogreFace = indexData - > faces [ fi ] ;
// 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 ] ;
src - > AddVertexMapping ( ogreVertexIndex , newIndex ) ;
2014-05-18 08:57:44 +00:00
2014-05-20 01:52:53 +00:00
// Position
dest - > mVertices [ newIndex ] = src - > positions [ ogreVertexIndex ] ;
// Normal
if ( normals )
dest - > mNormals [ newIndex ] = src - > normals [ ogreVertexIndex ] ;
// UVs
for ( size_t uvi = 0 ; uvi < uvs ; + + uvi )
{
aiVector3D * uvDest = dest - > mTextureCoords [ uvi ] ;
std : : vector < aiVector3D > & uvSrc = src - > uvs [ uvi ] ;
uvDest [ newIndex ] = uvSrc [ ogreVertexIndex ] ;
}
2014-05-18 08:57:44 +00:00
}
2014-05-20 01:52:53 +00:00
}
// Bones and bone weights
if ( parent - > skeleton & & boneAssignments )
{
AssimpVertexBoneWeightList weights = src - > AssimpBoneWeights ( dest - > mNumVertices ) ;
std : : set < uint16_t > referencedBones = src - > ReferencedBonesByWeights ( ) ;
dest - > mNumBones = referencedBones . size ( ) ;
dest - > mBones = new aiBone * [ dest - > mNumBones ] ;
size_t assimpBoneIndex = 0 ;
for ( std : : set < uint16_t > : : const_iterator rbIter = referencedBones . begin ( ) , rbEnd = referencedBones . end ( ) ; rbIter ! = rbEnd ; + + rbIter , + + assimpBoneIndex )
{
Bone * bone = parent - > skeleton - > BoneById ( ( * rbIter ) ) ;
dest - > mBones [ assimpBoneIndex ] = bone - > ConvertToAssimpBone ( parent - > skeleton , weights [ bone - > id ] ) ;
}
}
2014-05-18 08:57:44 +00:00
return dest ;
}
2014-05-20 01:52:53 +00:00
// Animation
Animation : : Animation ( Skeleton * parent ) :
parentSkeleton ( parent ) ,
parentMesh ( 0 ) ,
length ( 0.0f ) ,
baseTime ( - 1.0f )
{
}
2014-05-18 08:57:44 +00:00
2014-05-20 01:52:53 +00:00
Animation : : Animation ( Mesh * parent ) :
parentMesh ( parent ) ,
parentSkeleton ( 0 ) ,
2014-05-18 08:57:44 +00:00
length ( 0.0f ) ,
baseTime ( - 1.0f )
{
}
2014-05-20 01:52:53 +00:00
VertexData * Animation : : AssociatedVertexData ( VertexAnimationTrack * track ) const
2014-05-18 08:57:44 +00:00
{
2014-05-20 01:52:53 +00:00
if ( ! parentMesh )
return 0 ;
2014-05-18 08:57:44 +00:00
bool sharedGeom = ( track - > target = = 0 ) ;
if ( sharedGeom )
return parentMesh - > sharedVertexData ;
else
2014-05-20 01:52:53 +00:00
return parentMesh - > GetSubMesh ( track - > target - 1 ) - > vertexData ;
}
aiAnimation * Animation : : ConvertToAssimpAnimation ( )
{
aiAnimation * anim = new aiAnimation ( ) ;
anim - > mName = name ;
anim - > mDuration = static_cast < double > ( length ) ;
anim - > mTicksPerSecond = 1.0 ;
// Tracks
if ( ! tracks . empty ( ) )
{
anim - > mNumChannels = tracks . size ( ) ;
anim - > mChannels = new aiNodeAnim * [ anim - > mNumChannels ] ;
for ( size_t i = 0 , len = tracks . size ( ) ; i < len ; + + i )
{
anim - > mChannels [ i ] = tracks [ i ] . ConvertToAssimpAnimationNode ( parentSkeleton ) ;
}
}
return anim ;
}
// Skeleton
2014-05-21 01:00:11 +00:00
Skeleton : : Skeleton ( ) :
2014-07-31 13:09:49 +00:00
bones ( ) ,
animations ( ) ,
2014-05-21 01:00:11 +00:00
blendMode ( ANIMBLEND_AVERAGE )
2014-05-20 01:52:53 +00:00
{
}
Skeleton : : ~ Skeleton ( )
{
Reset ( ) ;
}
void Skeleton : : Reset ( )
{
for ( size_t i = 0 , len = bones . size ( ) ; i < len ; + + i ) {
OGRE_SAFE_DELETE ( bones [ i ] )
}
bones . clear ( ) ;
for ( size_t i = 0 , len = animations . size ( ) ; i < len ; + + i ) {
OGRE_SAFE_DELETE ( animations [ i ] )
}
animations . clear ( ) ;
}
BoneList Skeleton : : RootBones ( ) const
{
BoneList rootBones ;
for ( BoneList : : const_iterator iter = bones . begin ( ) ; iter ! = bones . end ( ) ; + + iter )
{
if ( ! ( * iter ) - > IsParented ( ) )
rootBones . push_back ( ( * iter ) ) ;
}
return rootBones ;
}
size_t Skeleton : : NumRootBones ( ) const
{
size_t num = 0 ;
for ( BoneList : : const_iterator iter = bones . begin ( ) ; iter ! = bones . end ( ) ; + + iter )
{
if ( ! ( * iter ) - > IsParented ( ) )
num + + ;
}
return num ;
}
Bone * Skeleton : : BoneByName ( const std : : string & name ) const
{
for ( BoneList : : const_iterator iter = bones . begin ( ) ; iter ! = bones . end ( ) ; + + iter )
{
if ( ( * iter ) - > name = = name )
return ( * iter ) ;
}
return 0 ;
}
Bone * Skeleton : : BoneById ( uint16_t id ) const
{
for ( BoneList : : const_iterator iter = bones . begin ( ) ; iter ! = bones . end ( ) ; + + iter )
{
if ( ( * iter ) - > id = = id )
return ( * iter ) ;
}
return 0 ;
}
// Bone
Bone : : Bone ( ) :
id ( 0 ) ,
parent ( 0 ) ,
parentId ( - 1 ) ,
2014-05-20 21:09:30 +00:00
scale ( 1.0f , 1.0f , 1.0f )
2014-05-20 01:52:53 +00:00
{
}
bool Bone : : IsParented ( ) const
{
return ( parentId ! = - 1 & & parent ! = 0 ) ;
}
uint16_t Bone : : ParentId ( ) const
{
return static_cast < uint16_t > ( parentId ) ;
}
void Bone : : AddChild ( Bone * bone )
{
if ( ! bone )
return ;
if ( bone - > IsParented ( ) )
throw DeadlyImportError ( " Attaching child Bone that is already parented: " + bone - > name ) ;
bone - > parent = this ;
bone - > parentId = id ;
children . push_back ( bone - > id ) ;
}
void Bone : : CalculateWorldMatrixAndDefaultPose ( Skeleton * skeleton )
{
if ( ! IsParented ( ) )
2014-05-21 01:00:11 +00:00
worldMatrix = aiMatrix4x4 ( scale , rotation , position ) . Inverse ( ) ;
2014-05-20 01:52:53 +00:00
else
2014-05-21 01:00:11 +00:00
worldMatrix = aiMatrix4x4 ( scale , rotation , position ) . Inverse ( ) * parent - > worldMatrix ;
2014-05-20 01:52:53 +00:00
2014-05-21 01:00:11 +00:00
defaultPose = aiMatrix4x4 ( scale , rotation , position ) ;
2014-05-20 01:52:53 +00:00
// Recursively for all children now that the parent matrix has been calculated.
for ( size_t i = 0 , len = children . size ( ) ; i < len ; + + i )
{
Bone * child = skeleton - > BoneById ( children [ i ] ) ;
if ( ! child ) {
throw DeadlyImportError ( Formatter : : format ( ) < < " CalculateWorldMatrixAndDefaultPose: Failed to find child bone " < < children [ i ] < < " for parent " < < id < < " " < < name ) ;
}
child - > CalculateWorldMatrixAndDefaultPose ( skeleton ) ;
}
}
aiNode * Bone : : ConvertToAssimpNode ( Skeleton * skeleton , aiNode * parentNode )
{
// Bone node
aiNode * node = new aiNode ( name ) ;
node - > mParent = parentNode ;
node - > mTransformation = defaultPose ;
// Children
if ( ! children . empty ( ) )
{
node - > mNumChildren = children . size ( ) ;
node - > mChildren = new aiNode * [ node - > mNumChildren ] ;
for ( size_t i = 0 , len = children . size ( ) ; i < len ; + + i )
{
Bone * child = skeleton - > BoneById ( children [ i ] ) ;
if ( ! child ) {
throw DeadlyImportError ( Formatter : : format ( ) < < " ConvertToAssimpNode: Failed to find child bone " < < children [ i ] < < " for parent " < < id < < " " < < name ) ;
}
node - > mChildren [ i ] = child - > ConvertToAssimpNode ( skeleton , node ) ;
}
}
return node ;
}
aiBone * Bone : : ConvertToAssimpBone ( Skeleton * parent , const std : : vector < aiVertexWeight > & boneWeights )
{
aiBone * bone = new aiBone ( ) ;
bone - > mName = name ;
bone - > mOffsetMatrix = worldMatrix ;
if ( ! boneWeights . empty ( ) )
{
bone - > mNumWeights = boneWeights . size ( ) ;
bone - > mWeights = new aiVertexWeight [ boneWeights . size ( ) ] ;
memcpy ( bone - > mWeights , & boneWeights [ 0 ] , boneWeights . size ( ) * sizeof ( aiVertexWeight ) ) ;
}
return bone ;
}
// VertexAnimationTrack
VertexAnimationTrack : : VertexAnimationTrack ( ) :
target ( 0 ) ,
type ( VAT_NONE )
{
}
aiNodeAnim * VertexAnimationTrack : : ConvertToAssimpAnimationNode ( Skeleton * skeleton )
{
if ( boneName . empty ( ) | | type ! = VAT_TRANSFORM ) {
throw DeadlyImportError ( " VertexAnimationTrack::ConvertToAssimpAnimationNode: Cannot convert track that has no target bone name or is not type of VAT_TRANSFORM " ) ;
}
aiNodeAnim * nodeAnim = new aiNodeAnim ( ) ;
nodeAnim - > mNodeName = boneName ;
Bone * bone = skeleton - > BoneByName ( boneName ) ;
if ( ! bone ) {
throw DeadlyImportError ( " VertexAnimationTrack::ConvertToAssimpAnimationNode: Failed to find bone " + boneName + " from parent Skeleton " ) ;
}
// Keyframes
size_t numKeyframes = transformKeyFrames . size ( ) ;
nodeAnim - > mPositionKeys = new aiVectorKey [ numKeyframes ] ;
nodeAnim - > mRotationKeys = new aiQuatKey [ numKeyframes ] ;
nodeAnim - > mScalingKeys = new aiVectorKey [ numKeyframes ] ;
nodeAnim - > mNumPositionKeys = numKeyframes ;
nodeAnim - > mNumRotationKeys = numKeyframes ;
nodeAnim - > mNumScalingKeys = numKeyframes ;
for ( size_t kfi = 0 ; kfi < numKeyframes ; + + kfi )
{
2014-05-21 01:00:11 +00:00
TransformKeyFrame & kfSource = transformKeyFrames [ kfi ] ;
2014-05-20 01:52:53 +00:00
// Calculate the complete transformation from world space to bone space
2014-05-21 01:00:11 +00:00
aiVector3D pos ; aiQuaternion rot ; aiVector3D scale ;
2014-05-20 01:52:53 +00:00
2014-05-21 01:00:11 +00:00
aiMatrix4x4 finalTransform = bone - > defaultPose * kfSource . Transform ( ) ;
finalTransform . Decompose ( scale , rot , pos ) ;
2014-05-20 01:52:53 +00:00
double t = static_cast < double > ( kfSource . timePos ) ;
nodeAnim - > mPositionKeys [ kfi ] . mTime = t ;
nodeAnim - > mRotationKeys [ kfi ] . mTime = t ;
nodeAnim - > mScalingKeys [ kfi ] . mTime = t ;
2014-05-21 01:00:11 +00:00
nodeAnim - > mPositionKeys [ kfi ] . mValue = pos ;
nodeAnim - > mRotationKeys [ kfi ] . mValue = rot ;
nodeAnim - > mScalingKeys [ kfi ] . mValue = scale ;
2014-05-20 01:52:53 +00:00
}
return nodeAnim ;
2014-05-18 08:57:44 +00:00
}
2014-05-21 01:00:11 +00:00
// TransformKeyFrame
TransformKeyFrame : : TransformKeyFrame ( ) :
timePos ( 0.0f ) ,
scale ( 1.0f , 1.0f , 1.0f )
{
}
aiMatrix4x4 TransformKeyFrame : : Transform ( )
{
return aiMatrix4x4 ( scale , rotation , position ) ;
}
2014-05-18 08:57:44 +00:00
} // Ogre
} // Assimp
# endif // ASSIMP_BUILD_NO_OGRE_IMPORTER