|
@@ -3,7 +3,8 @@
|
|
Open Asset Import Library (assimp)
|
|
Open Asset Import Library (assimp)
|
|
---------------------------------------------------------------------------
|
|
---------------------------------------------------------------------------
|
|
|
|
|
|
-Copyright (c) 2006-2016, assimp team
|
|
|
|
|
|
+Copyright (c) 2006-2017, assimp team
|
|
|
|
+
|
|
|
|
|
|
All rights reserved.
|
|
All rights reserved.
|
|
|
|
|
|
@@ -49,18 +50,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#include <assimp/scene.h>
|
|
#include <assimp/scene.h>
|
|
#include <assimp/DefaultLogger.hpp>
|
|
#include <assimp/DefaultLogger.hpp>
|
|
#include <assimp/Importer.hpp>
|
|
#include <assimp/Importer.hpp>
|
|
-#include "ColladaParser.h"
|
|
|
|
|
|
+#include <assimp/importerdesc.h>
|
|
|
|
|
|
|
|
+#include "ColladaParser.h"
|
|
#include "fast_atof.h"
|
|
#include "fast_atof.h"
|
|
#include "ParsingUtils.h"
|
|
#include "ParsingUtils.h"
|
|
#include "SkeletonMeshBuilder.h"
|
|
#include "SkeletonMeshBuilder.h"
|
|
-#include "Defines.h"
|
|
|
|
|
|
+#include "CreateAnimMesh.h"
|
|
|
|
|
|
#include "time.h"
|
|
#include "time.h"
|
|
#include "math.h"
|
|
#include "math.h"
|
|
|
|
+#include <algorithm>
|
|
#include <numeric>
|
|
#include <numeric>
|
|
-#include "Defines.h"
|
|
|
|
-
|
|
|
|
|
|
+#include <assimp/Defines.h>
|
|
|
|
|
|
using namespace Assimp;
|
|
using namespace Assimp;
|
|
using namespace Assimp::Formatter;
|
|
using namespace Assimp::Formatter;
|
|
@@ -148,6 +150,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
|
mMeshIndexByID.clear();
|
|
mMeshIndexByID.clear();
|
|
mMaterialIndexByName.clear();
|
|
mMaterialIndexByName.clear();
|
|
mMeshes.clear();
|
|
mMeshes.clear();
|
|
|
|
+ mTargetMeshes.clear();
|
|
newMats.clear();
|
|
newMats.clear();
|
|
mLights.clear();
|
|
mLights.clear();
|
|
mCameras.clear();
|
|
mCameras.clear();
|
|
@@ -240,7 +243,7 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
|
|
ResolveNodeInstances(pParser,pNode,instances);
|
|
ResolveNodeInstances(pParser,pNode,instances);
|
|
|
|
|
|
// add children. first the *real* ones
|
|
// add children. first the *real* ones
|
|
- node->mNumChildren = pNode->mChildren.size()+instances.size();
|
|
|
|
|
|
+ node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size()+instances.size());
|
|
node->mChildren = new aiNode*[node->mNumChildren];
|
|
node->mChildren = new aiNode*[node->mNumChildren];
|
|
|
|
|
|
for( size_t a = 0; a < pNode->mChildren.size(); a++)
|
|
for( size_t a = 0; a < pNode->mChildren.size(); a++)
|
|
@@ -420,13 +423,13 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
|
|
out->mHorizontalFOV = srcCamera->mHorFov;
|
|
out->mHorizontalFOV = srcCamera->mHorFov;
|
|
|
|
|
|
if (srcCamera->mVerFov != 10e10f && srcCamera->mAspect == 10e10f) {
|
|
if (srcCamera->mVerFov != 10e10f && srcCamera->mAspect == 10e10f) {
|
|
- out->mAspect = tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
|
|
|
|
- tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
|
|
|
|
|
|
+ out->mAspect = std::tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) /
|
|
|
|
+ std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
|
|
else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) {
|
|
- out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(atan(srcCamera->mAspect *
|
|
|
|
- tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
|
|
|
|
|
|
+ out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(std::atan(srcCamera->mAspect *
|
|
|
|
+ std::tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f)));
|
|
}
|
|
}
|
|
|
|
|
|
// Collada uses degrees, we use radians
|
|
// Collada uses degrees, we use radians
|
|
@@ -506,7 +509,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
|
|
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
|
|
unsigned int matIdx;
|
|
unsigned int matIdx;
|
|
if( matIt != mMaterialIndexByName.end())
|
|
if( matIt != mMaterialIndexByName.end())
|
|
- matIdx = matIt->second;
|
|
|
|
|
|
+ matIdx = static_cast<unsigned int>(matIt->second);
|
|
else
|
|
else
|
|
matIdx = 0;
|
|
matIdx = 0;
|
|
|
|
|
|
@@ -553,14 +556,37 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|
}
|
|
}
|
|
|
|
|
|
// now place all mesh references we gathered in the target node
|
|
// now place all mesh references we gathered in the target node
|
|
- pTarget->mNumMeshes = newMeshRefs.size();
|
|
|
|
|
|
+ pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
|
|
if( newMeshRefs.size())
|
|
if( newMeshRefs.size())
|
|
{
|
|
{
|
|
|
|
+ struct UIntTypeConverter
|
|
|
|
+ {
|
|
|
|
+ unsigned int operator()(const size_t& v) const
|
|
|
|
+ {
|
|
|
|
+ return static_cast<unsigned int>(v);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
pTarget->mMeshes = new unsigned int[pTarget->mNumMeshes];
|
|
pTarget->mMeshes = new unsigned int[pTarget->mNumMeshes];
|
|
- std::copy( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes);
|
|
|
|
|
|
+ std::transform( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes, UIntTypeConverter());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// ------------------------------------------------------------------------------------------------
|
|
|
|
+// Find mesh from either meshes or morph target meshes
|
|
|
|
+aiMesh *ColladaLoader::findMesh(std::string meshid)
|
|
|
|
+{
|
|
|
|
+ for (unsigned int i = 0; i < mMeshes.size(); i++)
|
|
|
|
+ if (std::string(mMeshes[i]->mName.data) == meshid)
|
|
|
|
+ return mMeshes[i];
|
|
|
|
+
|
|
|
|
+ for (unsigned int i = 0; i < mTargetMeshes.size(); i++)
|
|
|
|
+ if (std::string(mTargetMeshes[i]->mName.data) == meshid)
|
|
|
|
+ return mTargetMeshes[i];
|
|
|
|
+
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
// ------------------------------------------------------------------------------------------------
|
|
// ------------------------------------------------------------------------------------------------
|
|
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
|
|
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
|
|
aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
|
|
aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
|
|
@@ -572,10 +598,10 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|
|
|
|
|
// count the vertices addressed by its faces
|
|
// count the vertices addressed by its faces
|
|
const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace,
|
|
const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace,
|
|
- pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, 0);
|
|
|
|
|
|
+ pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0));
|
|
|
|
|
|
// copy positions
|
|
// copy positions
|
|
- dstMesh->mNumVertices = numVertices;
|
|
|
|
|
|
+ dstMesh->mNumVertices = static_cast<unsigned int>(numVertices);
|
|
dstMesh->mVertices = new aiVector3D[numVertices];
|
|
dstMesh->mVertices = new aiVector3D[numVertices];
|
|
std::copy( pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() +
|
|
std::copy( pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() +
|
|
pStartVertex + numVertices, dstMesh->mVertices);
|
|
pStartVertex + numVertices, dstMesh->mVertices);
|
|
@@ -634,20 +660,82 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|
|
|
|
|
// create faces. Due to the fact that each face uses unique vertices, we can simply count up on each vertex
|
|
// create faces. Due to the fact that each face uses unique vertices, we can simply count up on each vertex
|
|
size_t vertex = 0;
|
|
size_t vertex = 0;
|
|
- dstMesh->mNumFaces = pSubMesh.mNumFaces;
|
|
|
|
|
|
+ dstMesh->mNumFaces = static_cast<unsigned int>(pSubMesh.mNumFaces);
|
|
dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
|
|
dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
|
|
for( size_t a = 0; a < dstMesh->mNumFaces; ++a)
|
|
for( size_t a = 0; a < dstMesh->mNumFaces; ++a)
|
|
{
|
|
{
|
|
size_t s = pSrcMesh->mFaceSize[ pStartFace + a];
|
|
size_t s = pSrcMesh->mFaceSize[ pStartFace + a];
|
|
aiFace& face = dstMesh->mFaces[a];
|
|
aiFace& face = dstMesh->mFaces[a];
|
|
- face.mNumIndices = s;
|
|
|
|
|
|
+ face.mNumIndices = static_cast<unsigned int>(s);
|
|
face.mIndices = new unsigned int[s];
|
|
face.mIndices = new unsigned int[s];
|
|
for( size_t b = 0; b < s; ++b)
|
|
for( size_t b = 0; b < s; ++b)
|
|
- face.mIndices[b] = vertex++;
|
|
|
|
|
|
+ face.mIndices[b] = static_cast<unsigned int>(vertex++);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // create morph target meshes if any
|
|
|
|
+ std::vector<aiMesh*> targetMeshes;
|
|
|
|
+ std::vector<float> targetWeights;
|
|
|
|
+ Collada::MorphMethod method;
|
|
|
|
+
|
|
|
|
+ for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
|
|
|
|
+ it != pParser.mControllerLibrary.end(); it++)
|
|
|
|
+ {
|
|
|
|
+ const Collada::Controller &c = it->second;
|
|
|
|
+ const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId);
|
|
|
|
+
|
|
|
|
+ if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName)
|
|
|
|
+ {
|
|
|
|
+ const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget);
|
|
|
|
+ const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight);
|
|
|
|
+ const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource);
|
|
|
|
+ const Collada::Data& weightData = pParser.ResolveLibraryReference( pParser.mDataLibrary, weightAccessor.mSource);
|
|
|
|
+
|
|
|
|
+ // take method
|
|
|
|
+ method = c.mMethod;
|
|
|
|
+
|
|
|
|
+ if (!targetData.mIsStringArray)
|
|
|
|
+ throw DeadlyImportError( "target data must contain id. ");
|
|
|
|
+ if (weightData.mIsStringArray)
|
|
|
|
+ throw DeadlyImportError( "target weight data must not be textual ");
|
|
|
|
+
|
|
|
|
+ for (unsigned int i = 0; i < targetData.mStrings.size(); ++i)
|
|
|
|
+ {
|
|
|
|
+ const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i));
|
|
|
|
+
|
|
|
|
+ aiMesh *aimesh = findMesh(targetMesh->mName);
|
|
|
|
+ if (!aimesh)
|
|
|
|
+ {
|
|
|
|
+ if (targetMesh->mSubMeshes.size() > 1)
|
|
|
|
+ throw DeadlyImportError( "Morhing target mesh must be a single");
|
|
|
|
+ aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0);
|
|
|
|
+ mTargetMeshes.push_back(aimesh);
|
|
|
|
+ }
|
|
|
|
+ targetMeshes.push_back(aimesh);
|
|
|
|
+ }
|
|
|
|
+ for (unsigned int i = 0; i < weightData.mValues.size(); ++i)
|
|
|
|
+ targetWeights.push_back(weightData.mValues.at(i));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size())
|
|
|
|
+ {
|
|
|
|
+ std::vector<aiAnimMesh*> animMeshes;
|
|
|
|
+ for (unsigned int i = 0; i < targetMeshes.size(); i++)
|
|
|
|
+ {
|
|
|
|
+ aiAnimMesh *animMesh = aiCreateAnimMesh(targetMeshes.at(i));
|
|
|
|
+ animMesh->mWeight = targetWeights[i];
|
|
|
|
+ animMeshes.push_back(animMesh);
|
|
|
|
+ }
|
|
|
|
+ dstMesh->mMethod = (method == Collada::Relative)
|
|
|
|
+ ? aiMorphingMethod_MORPH_RELATIVE
|
|
|
|
+ : aiMorphingMethod_MORPH_NORMALIZED;
|
|
|
|
+ dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
|
|
|
|
+ dstMesh->mNumAnimMeshes = animMeshes.size();
|
|
|
|
+ for (unsigned int i = 0; i < animMeshes.size(); i++)
|
|
|
|
+ dstMesh->mAnimMeshes[i] = animMeshes.at(i);
|
|
}
|
|
}
|
|
|
|
|
|
// create bones if given
|
|
// create bones if given
|
|
- if( pSrcController)
|
|
|
|
|
|
+ if( pSrcController && pSrcController->mType == Collada::Skin)
|
|
{
|
|
{
|
|
// refuse if the vertex count does not match
|
|
// refuse if the vertex count does not match
|
|
// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
|
|
// if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
|
|
@@ -710,7 +798,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|
if( weight > 0.0f)
|
|
if( weight > 0.0f)
|
|
{
|
|
{
|
|
aiVertexWeight w;
|
|
aiVertexWeight w;
|
|
- w.mVertexId = a - pStartVertex;
|
|
|
|
|
|
+ w.mVertexId = static_cast<unsigned int>(a - pStartVertex);
|
|
w.mWeight = weight;
|
|
w.mWeight = weight;
|
|
dstBones[jointIndex].push_back( w);
|
|
dstBones[jointIndex].push_back( w);
|
|
}
|
|
}
|
|
@@ -724,7 +812,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|
numRemainingBones++;
|
|
numRemainingBones++;
|
|
|
|
|
|
// create bone array and copy bone weights one by one
|
|
// create bone array and copy bone weights one by one
|
|
- dstMesh->mNumBones = numRemainingBones;
|
|
|
|
|
|
+ dstMesh->mNumBones = static_cast<unsigned int>(numRemainingBones);
|
|
dstMesh->mBones = new aiBone*[numRemainingBones];
|
|
dstMesh->mBones = new aiBone*[numRemainingBones];
|
|
size_t boneCount = 0;
|
|
size_t boneCount = 0;
|
|
for( size_t a = 0; a < numBones; ++a)
|
|
for( size_t a = 0; a < numBones; ++a)
|
|
@@ -748,7 +836,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|
bone->mOffsetMatrix.c2 = ReadFloat( jointMatrixAcc, jointMatrices, a, 9);
|
|
bone->mOffsetMatrix.c2 = ReadFloat( jointMatrixAcc, jointMatrices, a, 9);
|
|
bone->mOffsetMatrix.c3 = ReadFloat( jointMatrixAcc, jointMatrices, a, 10);
|
|
bone->mOffsetMatrix.c3 = ReadFloat( jointMatrixAcc, jointMatrices, a, 10);
|
|
bone->mOffsetMatrix.c4 = ReadFloat( jointMatrixAcc, jointMatrices, a, 11);
|
|
bone->mOffsetMatrix.c4 = ReadFloat( jointMatrixAcc, jointMatrices, a, 11);
|
|
- bone->mNumWeights = dstBones[a].size();
|
|
|
|
|
|
+ bone->mNumWeights = static_cast<unsigned int>(dstBones[a].size());
|
|
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
|
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
|
std::copy( dstBones[a].begin(), dstBones[a].end(), bone->mWeights);
|
|
std::copy( dstBones[a].begin(), dstBones[a].end(), bone->mWeights);
|
|
|
|
|
|
@@ -798,7 +886,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|
// Stores all meshes in the given scene
|
|
// Stores all meshes in the given scene
|
|
void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
|
|
void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
|
|
{
|
|
{
|
|
- pScene->mNumMeshes = mMeshes.size();
|
|
|
|
|
|
+ pScene->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
|
|
if( mMeshes.size() > 0)
|
|
if( mMeshes.size() > 0)
|
|
{
|
|
{
|
|
pScene->mMeshes = new aiMesh*[mMeshes.size()];
|
|
pScene->mMeshes = new aiMesh*[mMeshes.size()];
|
|
@@ -811,7 +899,7 @@ void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
|
|
// Stores all cameras in the given scene
|
|
// Stores all cameras in the given scene
|
|
void ColladaLoader::StoreSceneCameras( aiScene* pScene)
|
|
void ColladaLoader::StoreSceneCameras( aiScene* pScene)
|
|
{
|
|
{
|
|
- pScene->mNumCameras = mCameras.size();
|
|
|
|
|
|
+ pScene->mNumCameras = static_cast<unsigned int>(mCameras.size());
|
|
if( mCameras.size() > 0)
|
|
if( mCameras.size() > 0)
|
|
{
|
|
{
|
|
pScene->mCameras = new aiCamera*[mCameras.size()];
|
|
pScene->mCameras = new aiCamera*[mCameras.size()];
|
|
@@ -824,7 +912,7 @@ void ColladaLoader::StoreSceneCameras( aiScene* pScene)
|
|
// Stores all lights in the given scene
|
|
// Stores all lights in the given scene
|
|
void ColladaLoader::StoreSceneLights( aiScene* pScene)
|
|
void ColladaLoader::StoreSceneLights( aiScene* pScene)
|
|
{
|
|
{
|
|
- pScene->mNumLights = mLights.size();
|
|
|
|
|
|
+ pScene->mNumLights = static_cast<unsigned int>(mLights.size());
|
|
if( mLights.size() > 0)
|
|
if( mLights.size() > 0)
|
|
{
|
|
{
|
|
pScene->mLights = new aiLight*[mLights.size()];
|
|
pScene->mLights = new aiLight*[mLights.size()];
|
|
@@ -837,7 +925,7 @@ void ColladaLoader::StoreSceneLights( aiScene* pScene)
|
|
// Stores all textures in the given scene
|
|
// Stores all textures in the given scene
|
|
void ColladaLoader::StoreSceneTextures( aiScene* pScene)
|
|
void ColladaLoader::StoreSceneTextures( aiScene* pScene)
|
|
{
|
|
{
|
|
- pScene->mNumTextures = mTextures.size();
|
|
|
|
|
|
+ pScene->mNumTextures = static_cast<unsigned int>(mTextures.size());
|
|
if( mTextures.size() > 0)
|
|
if( mTextures.size() > 0)
|
|
{
|
|
{
|
|
pScene->mTextures = new aiTexture*[mTextures.size()];
|
|
pScene->mTextures = new aiTexture*[mTextures.size()];
|
|
@@ -850,7 +938,7 @@ void ColladaLoader::StoreSceneTextures( aiScene* pScene)
|
|
// Stores all materials in the given scene
|
|
// Stores all materials in the given scene
|
|
void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
|
|
void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
|
|
{
|
|
{
|
|
- pScene->mNumMaterials = newMats.size();
|
|
|
|
|
|
+ pScene->mNumMaterials = static_cast<unsigned int>(newMats.size());
|
|
|
|
|
|
if (newMats.size() > 0) {
|
|
if (newMats.size() > 0) {
|
|
pScene->mMaterials = new aiMaterial*[newMats.size()];
|
|
pScene->mMaterials = new aiMaterial*[newMats.size()];
|
|
@@ -891,7 +979,7 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
|
|
combinedAnim->mName = aiString( std::string( "combinedAnim_") + char( '0' + a));
|
|
combinedAnim->mName = aiString( std::string( "combinedAnim_") + char( '0' + a));
|
|
combinedAnim->mDuration = templateAnim->mDuration;
|
|
combinedAnim->mDuration = templateAnim->mDuration;
|
|
combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
|
|
combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
|
|
- combinedAnim->mNumChannels = collectedAnimIndices.size() + 1;
|
|
|
|
|
|
+ combinedAnim->mNumChannels = static_cast<unsigned int>(collectedAnimIndices.size() + 1);
|
|
combinedAnim->mChannels = new aiNodeAnim*[combinedAnim->mNumChannels];
|
|
combinedAnim->mChannels = new aiNodeAnim*[combinedAnim->mNumChannels];
|
|
// add the template anim as first channel by moving its aiNodeAnim to the combined animation
|
|
// add the template anim as first channel by moving its aiNodeAnim to the combined animation
|
|
combinedAnim->mChannels[0] = templateAnim->mChannels[0];
|
|
combinedAnim->mChannels[0] = templateAnim->mChannels[0];
|
|
@@ -923,7 +1011,7 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
|
|
// now store all anims in the scene
|
|
// now store all anims in the scene
|
|
if( !mAnims.empty())
|
|
if( !mAnims.empty())
|
|
{
|
|
{
|
|
- pScene->mNumAnimations = mAnims.size();
|
|
|
|
|
|
+ pScene->mNumAnimations = static_cast<unsigned int>(mAnims.size());
|
|
pScene->mAnimations = new aiAnimation*[mAnims.size()];
|
|
pScene->mAnimations = new aiAnimation*[mAnims.size()];
|
|
std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
|
|
std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
|
|
}
|
|
}
|
|
@@ -946,6 +1034,68 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
|
|
CreateAnimation( pScene, pParser, pSrcAnim, animName);
|
|
CreateAnimation( pScene, pParser, pSrcAnim, animName);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct MorphTimeValues
|
|
|
|
+{
|
|
|
|
+ float mTime;
|
|
|
|
+ struct key
|
|
|
|
+ {
|
|
|
|
+ float mWeight;
|
|
|
|
+ unsigned int mValue;
|
|
|
|
+ };
|
|
|
|
+ std::vector<key> mKeys;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, float weight, unsigned int value)
|
|
|
|
+{
|
|
|
|
+ MorphTimeValues::key k;
|
|
|
|
+ k.mValue = value;
|
|
|
|
+ k.mWeight = weight;
|
|
|
|
+ if (values.size() == 0 || time < values[0].mTime)
|
|
|
|
+ {
|
|
|
|
+ MorphTimeValues val;
|
|
|
|
+ val.mTime = time;
|
|
|
|
+ val.mKeys.push_back(k);
|
|
|
|
+ values.insert(values.begin(), val);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (time > values.back().mTime)
|
|
|
|
+ {
|
|
|
|
+ MorphTimeValues val;
|
|
|
|
+ val.mTime = time;
|
|
|
|
+ val.mKeys.push_back(k);
|
|
|
|
+ values.insert(values.end(), val);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ for (unsigned int i = 0; i < values.size(); i++)
|
|
|
|
+ {
|
|
|
|
+ if (std::abs(time - values[i].mTime) < 1e-6f)
|
|
|
|
+ {
|
|
|
|
+ values[i].mKeys.push_back(k);
|
|
|
|
+ return;
|
|
|
|
+ } else if (time > values[i].mTime && time < values[i+1].mTime)
|
|
|
|
+ {
|
|
|
|
+ MorphTimeValues val;
|
|
|
|
+ val.mTime = time;
|
|
|
|
+ val.mKeys.push_back(k);
|
|
|
|
+ values.insert(values.begin() + i, val);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // should not get here
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key, unsigned int value)
|
|
|
|
+{
|
|
|
|
+ for (unsigned int i = 0; i < values[key].mKeys.size(); i++)
|
|
|
|
+ {
|
|
|
|
+ if (values[key].mKeys[i].mValue == value)
|
|
|
|
+ return values[key].mKeys[i].mWeight;
|
|
|
|
+ }
|
|
|
|
+ // no value at key found, try to interpolate if present at other keys. if not, return zero
|
|
|
|
+ // TODO: interpolation
|
|
|
|
+ return 0.0f;
|
|
|
|
+}
|
|
|
|
+
|
|
// ------------------------------------------------------------------------------------------------
|
|
// ------------------------------------------------------------------------------------------------
|
|
// Constructs the animation for the given source anim
|
|
// Constructs the animation for the given source anim
|
|
void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName)
|
|
void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName)
|
|
@@ -955,6 +1105,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|
CollectNodes( pScene->mRootNode, nodes);
|
|
CollectNodes( pScene->mRootNode, nodes);
|
|
|
|
|
|
std::vector<aiNodeAnim*> anims;
|
|
std::vector<aiNodeAnim*> anims;
|
|
|
|
+ std::vector<aiMeshMorphAnim*> morphAnims;
|
|
|
|
+
|
|
for( std::vector<const aiNode*>::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit)
|
|
for( std::vector<const aiNode*>::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit)
|
|
{
|
|
{
|
|
// find all the collada anim channels which refer to the current node
|
|
// find all the collada anim channels which refer to the current node
|
|
@@ -978,7 +1130,20 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|
// find the slash that separates the node name - there should be only one
|
|
// find the slash that separates the node name - there should be only one
|
|
std::string::size_type slashPos = srcChannel.mTarget.find( '/');
|
|
std::string::size_type slashPos = srcChannel.mTarget.find( '/');
|
|
if( slashPos == std::string::npos)
|
|
if( slashPos == std::string::npos)
|
|
|
|
+ {
|
|
|
|
+ std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID);
|
|
|
|
+ if (targetPos == std::string::npos)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ // not node transform, but something else. store as unknown animation channel for now
|
|
|
|
+ entry.mChannel = &(*cit);
|
|
|
|
+ entry.mTargetId = srcChannel.mTarget.substr(targetPos + pSrcAnim->mName.length(),
|
|
|
|
+ srcChannel.mTarget.length() - targetPos - pSrcAnim->mName.length());
|
|
|
|
+ if (entry.mTargetId.front() == '-')
|
|
|
|
+ entry.mTargetId = entry.mTargetId.substr(1);
|
|
|
|
+ entries.push_back(entry);
|
|
continue;
|
|
continue;
|
|
|
|
+ }
|
|
if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
|
|
if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
|
|
continue;
|
|
continue;
|
|
std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
|
|
std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
|
|
@@ -1058,8 +1223,14 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|
if( srcNode->mTransforms[a].mID == entry.mTransformId)
|
|
if( srcNode->mTransforms[a].mID == entry.mTransformId)
|
|
entry.mTransformIndex = a;
|
|
entry.mTransformIndex = a;
|
|
|
|
|
|
- if( entry.mTransformIndex == SIZE_MAX) {
|
|
|
|
- continue;
|
|
|
|
|
|
+ if( entry.mTransformIndex == SIZE_MAX)
|
|
|
|
+ {
|
|
|
|
+ if (entry.mTransformId.find("morph-weights") != std::string::npos)
|
|
|
|
+ {
|
|
|
|
+ entry.mTargetId = entry.mTransformId;
|
|
|
|
+ entry.mTransformId = "";
|
|
|
|
+ } else
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
|
|
|
|
entry.mChannel = &(*cit);
|
|
entry.mChannel = &(*cit);
|
|
@@ -1071,7 +1242,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|
continue;
|
|
continue;
|
|
|
|
|
|
// resolve the data pointers for all anim channels. Find the minimum time while we're at it
|
|
// resolve the data pointers for all anim channels. Find the minimum time while we're at it
|
|
- ai_real startTime = 1e20, endTime = -1e20;
|
|
|
|
|
|
+ ai_real startTime = ai_real( 1e20 ), endTime = ai_real( -1e20 );
|
|
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
|
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
|
{
|
|
{
|
|
Collada::ChannelEntry& e = *it;
|
|
Collada::ChannelEntry& e = *it;
|
|
@@ -1152,7 +1323,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|
resultTrafos.push_back( mat);
|
|
resultTrafos.push_back( mat);
|
|
|
|
|
|
// find next point in time to evaluate. That's the closest frame larger than the current in any channel
|
|
// find next point in time to evaluate. That's the closest frame larger than the current in any channel
|
|
- ai_real nextTime = 1e20;
|
|
|
|
|
|
+ ai_real nextTime = ai_real( 1e20 );
|
|
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
|
for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
|
{
|
|
{
|
|
Collada::ChannelEntry& channelElement = *it;
|
|
Collada::ChannelEntry& channelElement = *it;
|
|
@@ -1181,7 +1352,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|
const ai_real last_eval_angle = last_key_angle + (cur_key_angle - last_key_angle) * (time - last_key_time) / (cur_key_time - last_key_time);
|
|
const ai_real last_eval_angle = last_key_angle + (cur_key_angle - last_key_angle) * (time - last_key_time) / (cur_key_time - last_key_time);
|
|
const ai_real delta = std::abs(cur_key_angle - last_eval_angle);
|
|
const ai_real delta = std::abs(cur_key_angle - last_eval_angle);
|
|
if (delta >= 180.0) {
|
|
if (delta >= 180.0) {
|
|
- const int subSampleCount = static_cast<int>(floorf(delta / 90.0));
|
|
|
|
|
|
+ const int subSampleCount = static_cast<int>(std::floor(delta / 90.0));
|
|
if (cur_key_time != time) {
|
|
if (cur_key_time != time) {
|
|
const ai_real nextSampleTime = time + (cur_key_time - time) / subSampleCount;
|
|
const ai_real nextSampleTime = time + (cur_key_time - time) / subSampleCount;
|
|
nextTime = std::min(nextTime, nextSampleTime);
|
|
nextTime = std::min(nextTime, nextSampleTime);
|
|
@@ -1203,49 +1374,125 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|
// ai_assert( resultTrafos.size() > 0);
|
|
// ai_assert( resultTrafos.size() > 0);
|
|
|
|
|
|
// build an animation channel for the given node out of these trafo keys
|
|
// build an animation channel for the given node out of these trafo keys
|
|
- if( !resultTrafos.empty() )
|
|
|
|
- {
|
|
|
|
- aiNodeAnim* dstAnim = new aiNodeAnim;
|
|
|
|
- dstAnim->mNodeName = nodeName;
|
|
|
|
- dstAnim->mNumPositionKeys = resultTrafos.size();
|
|
|
|
- dstAnim->mNumRotationKeys= resultTrafos.size();
|
|
|
|
- dstAnim->mNumScalingKeys = resultTrafos.size();
|
|
|
|
- dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
|
|
|
|
- dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
|
|
|
|
- dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
|
|
|
|
-
|
|
|
|
- for( size_t a = 0; a < resultTrafos.size(); ++a)
|
|
|
|
- {
|
|
|
|
- aiMatrix4x4 mat = resultTrafos[a];
|
|
|
|
- double time = double( mat.d4); // remember? time is stored in mat.d4
|
|
|
|
- mat.d4 = 1.0f;
|
|
|
|
-
|
|
|
|
- dstAnim->mPositionKeys[a].mTime = time;
|
|
|
|
- dstAnim->mRotationKeys[a].mTime = time;
|
|
|
|
- dstAnim->mScalingKeys[a].mTime = time;
|
|
|
|
- mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
|
|
|
|
- }
|
|
|
|
|
|
+ if( !resultTrafos.empty() )
|
|
|
|
+ {
|
|
|
|
+ aiNodeAnim* dstAnim = new aiNodeAnim;
|
|
|
|
+ dstAnim->mNodeName = nodeName;
|
|
|
|
+ dstAnim->mNumPositionKeys = resultTrafos.size();
|
|
|
|
+ dstAnim->mNumRotationKeys= resultTrafos.size();
|
|
|
|
+ dstAnim->mNumScalingKeys = resultTrafos.size();
|
|
|
|
+ dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
|
|
|
|
+ dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
|
|
|
|
+ dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
|
|
|
|
+
|
|
|
|
+ for( size_t a = 0; a < resultTrafos.size(); ++a)
|
|
|
|
+ {
|
|
|
|
+ aiMatrix4x4 mat = resultTrafos[a];
|
|
|
|
+ double time = double( mat.d4); // remember? time is stored in mat.d4
|
|
|
|
+ mat.d4 = 1.0f;
|
|
|
|
+
|
|
|
|
+ dstAnim->mPositionKeys[a].mTime = time;
|
|
|
|
+ dstAnim->mRotationKeys[a].mTime = time;
|
|
|
|
+ dstAnim->mScalingKeys[a].mTime = time;
|
|
|
|
+ mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
|
|
|
|
+ }
|
|
|
|
|
|
- anims.push_back( dstAnim);
|
|
|
|
- } else
|
|
|
|
- {
|
|
|
|
- DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
|
|
|
- }
|
|
|
|
|
|
+ anims.push_back( dstAnim);
|
|
|
|
+ } else
|
|
|
|
+ {
|
|
|
|
+ DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
|
|
|
|
+ {
|
|
|
|
+ std::vector<Collada::ChannelEntry> morphChannels;
|
|
|
|
+ for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
|
|
|
|
+ {
|
|
|
|
+ Collada::ChannelEntry& e = *it;
|
|
|
|
+
|
|
|
|
+ // skip non-transform types
|
|
|
|
+ if (e.mTargetId.empty())
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (e.mTargetId.find("morph-weights") != std::string::npos)
|
|
|
|
+ morphChannels.push_back(e);
|
|
|
|
+ }
|
|
|
|
+ if (morphChannels.size() > 0)
|
|
|
|
+ {
|
|
|
|
+ // either 1) morph weight animation count should contain morph target count channels
|
|
|
|
+ // or 2) one channel with morph target count arrays
|
|
|
|
+ // assume first
|
|
|
|
+
|
|
|
|
+ aiMeshMorphAnim *morphAnim = new aiMeshMorphAnim;
|
|
|
|
+ morphAnim->mName.Set(nodeName);
|
|
|
|
+
|
|
|
|
+ std::vector<MorphTimeValues> morphTimeValues;
|
|
|
|
+
|
|
|
|
+ int morphAnimChannelIndex = 0;
|
|
|
|
+ for( std::vector<Collada::ChannelEntry>::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it)
|
|
|
|
+ {
|
|
|
|
+ Collada::ChannelEntry& e = *it;
|
|
|
|
+ std::string::size_type apos = e.mTargetId.find('(');
|
|
|
|
+ std::string::size_type bpos = e.mTargetId.find(')');
|
|
|
|
+ if (apos == std::string::npos || bpos == std::string::npos)
|
|
|
|
+ // unknown way to specify weight -> ignore this animation
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ // weight target can be in format Weight_M_N, Weight_N, WeightN, or some other way
|
|
|
|
+ // we ignore the name and just assume the channels are in the right order
|
|
|
|
+ for (unsigned int i = 0; i < e.mTimeData->mValues.size(); i++)
|
|
|
|
+ insertMorphTimeValue(morphTimeValues, e.mTimeData->mValues.at(i), e.mValueData->mValues.at(i), morphAnimChannelIndex);
|
|
|
|
+
|
|
|
|
+ ++morphAnimChannelIndex;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ morphAnim->mNumKeys = morphTimeValues.size();
|
|
|
|
+ morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys];
|
|
|
|
+ for (unsigned int key = 0; key < morphAnim->mNumKeys; key++)
|
|
|
|
+ {
|
|
|
|
+ morphAnim->mKeys[key].mNumValuesAndWeights = morphChannels.size();
|
|
|
|
+ morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()];
|
|
|
|
+ morphAnim->mKeys[key].mWeights = new double [morphChannels.size()];
|
|
|
|
+
|
|
|
|
+ morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime;
|
|
|
|
+ for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); valueIndex++)
|
|
|
|
+ {
|
|
|
|
+ morphAnim->mKeys[key].mValues[valueIndex] = valueIndex;
|
|
|
|
+ morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ morphAnims.push_back(morphAnim);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- if( !anims.empty())
|
|
|
|
|
|
+ if( !anims.empty() || !morphAnims.empty())
|
|
{
|
|
{
|
|
aiAnimation* anim = new aiAnimation;
|
|
aiAnimation* anim = new aiAnimation;
|
|
anim->mName.Set( pName);
|
|
anim->mName.Set( pName);
|
|
anim->mNumChannels = anims.size();
|
|
anim->mNumChannels = anims.size();
|
|
- anim->mChannels = new aiNodeAnim*[anims.size()];
|
|
|
|
- std::copy( anims.begin(), anims.end(), anim->mChannels);
|
|
|
|
|
|
+ if (anim->mNumChannels > 0)
|
|
|
|
+ {
|
|
|
|
+ anim->mChannels = new aiNodeAnim*[anims.size()];
|
|
|
|
+ std::copy( anims.begin(), anims.end(), anim->mChannels);
|
|
|
|
+ }
|
|
|
|
+ anim->mNumMorphMeshChannels = morphAnims.size();
|
|
|
|
+ if (anim->mNumMorphMeshChannels > 0)
|
|
|
|
+ {
|
|
|
|
+ anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels];
|
|
|
|
+ std::copy( morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels);
|
|
|
|
+ }
|
|
anim->mDuration = 0.0f;
|
|
anim->mDuration = 0.0f;
|
|
for( size_t a = 0; a < anims.size(); ++a)
|
|
for( size_t a = 0; a < anims.size(); ++a)
|
|
{
|
|
{
|
|
- anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime);
|
|
|
|
- anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime);
|
|
|
|
- anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime);
|
|
|
|
|
|
+ anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime);
|
|
|
|
+ anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime);
|
|
|
|
+ anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime);
|
|
|
|
+ }
|
|
|
|
+ for (size_t a = 0; a < morphAnims.size(); ++a)
|
|
|
|
+ {
|
|
|
|
+ anim->mDuration = std::max(anim->mDuration, morphAnims[a]->mKeys[morphAnims[a]->mNumKeys-1].mTime);
|
|
}
|
|
}
|
|
anim->mTicksPerSecond = 1;
|
|
anim->mTicksPerSecond = 1;
|
|
mAnims.push_back( anim);
|
|
mAnims.push_back( anim);
|
|
@@ -1479,6 +1726,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
|
|
aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
|
|
aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
|
|
const Collada::Effect& pEffect, const std::string& pName)
|
|
const Collada::Effect& pEffect, const std::string& pName)
|
|
{
|
|
{
|
|
|
|
+ aiString result;
|
|
|
|
+
|
|
// recurse through the param references until we end up at an image
|
|
// recurse through the param references until we end up at an image
|
|
std::string name = pName;
|
|
std::string name = pName;
|
|
while( 1)
|
|
while( 1)
|
|
@@ -1497,11 +1746,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
|
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
|
|
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
|
|
if( imIt == pParser.mImageLibrary.end())
|
|
if( imIt == pParser.mImageLibrary.end())
|
|
{
|
|
{
|
|
- throw DeadlyImportError( format() <<
|
|
|
|
- "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
|
|
|
|
- }
|
|
|
|
|
|
+ //missing texture should not stop the conversion
|
|
|
|
+ //throw DeadlyImportError( format() <<
|
|
|
|
+ // "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
|
|
|
|
|
|
- aiString result;
|
|
|
|
|
|
+ DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
|
|
|
|
+
|
|
|
|
+ //set default texture file name
|
|
|
|
+ result.Set(name + ".jpg");
|
|
|
|
+ ConvertPath(result);
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
|
|
// if this is an embedded texture image setup an aiTexture for it
|
|
// if this is an embedded texture image setup an aiTexture for it
|
|
if (imIt->second.mFileName.empty())
|
|
if (imIt->second.mFileName.empty())
|
|
@@ -1520,13 +1775,13 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
|
|
|
|
|
// and copy texture data
|
|
// and copy texture data
|
|
tex->mHeight = 0;
|
|
tex->mHeight = 0;
|
|
- tex->mWidth = imIt->second.mImageData.size();
|
|
|
|
|
|
+ tex->mWidth = static_cast<unsigned int>(imIt->second.mImageData.size());
|
|
tex->pcData = (aiTexel*)new char[tex->mWidth];
|
|
tex->pcData = (aiTexel*)new char[tex->mWidth];
|
|
memcpy(tex->pcData,&imIt->second.mImageData[0],tex->mWidth);
|
|
memcpy(tex->pcData,&imIt->second.mImageData[0],tex->mWidth);
|
|
|
|
|
|
// setup texture reference string
|
|
// setup texture reference string
|
|
result.data[0] = '*';
|
|
result.data[0] = '*';
|
|
- result.length = 1 + ASSIMP_itoa10(result.data+1,MAXLEN-1,mTextures.size());
|
|
|
|
|
|
+ result.length = 1 + ASSIMP_itoa10(result.data+1,static_cast<unsigned int>(MAXLEN-1),static_cast<int32_t>(mTextures.size()));
|
|
|
|
|
|
// and add this texture to the list
|
|
// and add this texture to the list
|
|
mTextures.push_back(tex);
|
|
mTextures.push_back(tex);
|