Merge pull request #2535 from assimp/issue_2182
closes code/Collada/ColladaLoader.cpp: fix possible memleak when thro…pull/2546/head
commit
bc8f85eeae
|
@ -65,6 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
using namespace Assimp::Formatter;
|
using namespace Assimp::Formatter;
|
||||||
|
@ -126,7 +127,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
|
||||||
if (!pIOHandler) {
|
if (!pIOHandler) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const char* tokens[] = {"<collada"};
|
static const char* tokens[] = {"<collada"};
|
||||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,8 +135,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ColladaLoader::SetupProperties(const Importer* pImp)
|
void ColladaLoader::SetupProperties(const Importer* pImp) {
|
||||||
{
|
|
||||||
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
|
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
|
||||||
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
|
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
|
||||||
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0;
|
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0;
|
||||||
|
@ -143,8 +143,7 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Get file extension list
|
// Get file extension list
|
||||||
const aiImporterDesc* ColladaLoader::GetInfo () const
|
const aiImporterDesc* ColladaLoader::GetInfo () const {
|
||||||
{
|
|
||||||
return &desc;
|
return &desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,8 +245,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Recursively constructs a scene node for the given parser node and returns it.
|
// Recursively constructs a scene node for the given parser node and returns it.
|
||||||
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode)
|
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode) {
|
||||||
{
|
|
||||||
// create a node for it
|
// create a node for it
|
||||||
aiNode* node = new aiNode();
|
aiNode* node = new aiNode();
|
||||||
|
|
||||||
|
@ -265,15 +263,13 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
|
||||||
node->mNumChildren = static_cast<unsigned int>(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) {
|
||||||
{
|
|
||||||
node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]);
|
node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]);
|
||||||
node->mChildren[a]->mParent = node;
|
node->mChildren[a]->mParent = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... and finally the resolved node instances
|
// ... and finally the resolved node instances
|
||||||
for( size_t a = 0; a < instances.size(); a++)
|
for( size_t a = 0; a < instances.size(); ++a) {
|
||||||
{
|
|
||||||
node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]);
|
node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]);
|
||||||
node->mChildren[pNode->mChildren.size() + a]->mParent = node;
|
node->mChildren[pNode->mChildren.size() + a]->mParent = node;
|
||||||
}
|
}
|
||||||
|
@ -286,20 +282,19 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
|
||||||
|
|
||||||
// construct lights
|
// construct lights
|
||||||
BuildLightsForNode(pParser, pNode, node);
|
BuildLightsForNode(pParser, pNode, node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Resolve node instances
|
// Resolve node instances
|
||||||
void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
|
void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
|
||||||
std::vector<const Collada::Node*>& resolved)
|
std::vector<const Collada::Node*>& resolved) {
|
||||||
{
|
|
||||||
// reserve enough storage
|
// reserve enough storage
|
||||||
resolved.reserve(pNode->mNodeInstances.size());
|
resolved.reserve(pNode->mNodeInstances.size());
|
||||||
|
|
||||||
// ... and iterate through all nodes to be instanced as children of pNode
|
// ... and iterate through all nodes to be instanced as children of pNode
|
||||||
for (const auto &nodeInst: pNode->mNodeInstances)
|
for (const auto &nodeInst: pNode->mNodeInstances) {
|
||||||
{
|
|
||||||
// find the corresponding node in the library
|
// find the corresponding node in the library
|
||||||
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
|
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
|
||||||
const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second;
|
const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second;
|
||||||
|
@ -323,12 +318,12 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Resolve UV channels
|
// Resolve UV channels
|
||||||
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
|
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
|
||||||
const Collada::SemanticMappingTable& table)
|
const Collada::SemanticMappingTable& table) {
|
||||||
{
|
|
||||||
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
|
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
|
||||||
if (it != table.mMap.end()) {
|
if (it != table.mMap.end()) {
|
||||||
if (it->second.mType != Collada::IT_Texcoord)
|
if (it->second.mType != Collada::IT_Texcoord) {
|
||||||
ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
|
ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
|
||||||
|
}
|
||||||
|
|
||||||
sampler.mUVId = it->second.mSet;
|
sampler.mUVId = it->second.mSet;
|
||||||
}
|
}
|
||||||
|
@ -336,14 +331,11 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Builds lights for the given node and references them
|
// Builds lights for the given node and references them
|
||||||
void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
|
void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
|
||||||
{
|
for( const Collada::LightInstance& lid : pNode->mLights) {
|
||||||
for( const Collada::LightInstance& lid : pNode->mLights)
|
|
||||||
{
|
|
||||||
// find the referred light
|
// find the referred light
|
||||||
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
|
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
|
||||||
if( srcLightIt == pParser.mLightLibrary.end())
|
if( srcLightIt == pParser.mLightLibrary.end()) {
|
||||||
{
|
|
||||||
ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping.");
|
ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -365,8 +357,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
|
||||||
if (out->mType == aiLightSource_AMBIENT) {
|
if (out->mType == aiLightSource_AMBIENT) {
|
||||||
out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0);
|
out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0);
|
||||||
out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
|
out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// collada doesn't differentiate between these color types
|
// collada doesn't differentiate between these color types
|
||||||
out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity;
|
out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity;
|
||||||
out->mColorAmbient = aiColor3D(0, 0, 0);
|
out->mColorAmbient = aiColor3D(0, 0, 0);
|
||||||
|
@ -374,27 +365,24 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
|
||||||
|
|
||||||
// convert falloff angle and falloff exponent in our representation, if given
|
// convert falloff angle and falloff exponent in our representation, if given
|
||||||
if (out->mType == aiLightSource_SPOT) {
|
if (out->mType == aiLightSource_SPOT) {
|
||||||
|
|
||||||
out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle );
|
out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle );
|
||||||
|
|
||||||
// ... some extension magic.
|
// ... some extension magic.
|
||||||
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
|
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) {
|
||||||
{
|
|
||||||
// ... some deprecation magic.
|
// ... some deprecation magic.
|
||||||
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f))
|
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) {
|
||||||
{
|
|
||||||
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
|
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
|
||||||
// epsilon chosen to be 0.1
|
// epsilon chosen to be 0.1
|
||||||
out->mAngleOuterCone = std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
|
out->mAngleOuterCone = std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
|
||||||
out->mAngleInnerCone;
|
out->mAngleInnerCone;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle );
|
out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle );
|
||||||
if (out->mAngleOuterCone < out->mAngleInnerCone)
|
if (out->mAngleOuterCone < out->mAngleInnerCone)
|
||||||
std::swap(out->mAngleInnerCone,out->mAngleOuterCone);
|
std::swap(out->mAngleInnerCone,out->mAngleOuterCone);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
|
||||||
}
|
}
|
||||||
else out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to light list
|
// add to light list
|
||||||
|
@ -404,14 +392,11 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Builds cameras for the given node and references them
|
// Builds cameras for the given node and references them
|
||||||
void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
|
void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
|
||||||
{
|
for( const Collada::CameraInstance& cid : pNode->mCameras) {
|
||||||
for( const Collada::CameraInstance& cid : pNode->mCameras)
|
|
||||||
{
|
|
||||||
// find the referred light
|
// find the referred light
|
||||||
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
|
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
|
||||||
if( srcCameraIt == pParser.mCameraLibrary.end())
|
if( srcCameraIt == pParser.mCameraLibrary.end()) {
|
||||||
{
|
|
||||||
ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping.");
|
ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -435,8 +420,9 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
|
||||||
|
|
||||||
// ... but for the rest some values are optional
|
// ... but for the rest some values are optional
|
||||||
// and we need to compute the others in any combination.
|
// and we need to compute the others in any combination.
|
||||||
if (srcCamera->mAspect != 10e10f)
|
if (srcCamera->mAspect != 10e10f) {
|
||||||
out->mAspect = srcCamera->mAspect;
|
out->mAspect = srcCamera->mAspect;
|
||||||
|
}
|
||||||
|
|
||||||
if (srcCamera->mHorFov != 10e10f) {
|
if (srcCamera->mHorFov != 10e10f) {
|
||||||
out->mHorizontalFOV = srcCamera->mHorFov;
|
out->mHorizontalFOV = srcCamera->mHorFov;
|
||||||
|
@ -461,77 +447,69 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Builds meshes for the given node and references them
|
// Builds meshes for the given node and references them
|
||||||
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
|
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
|
||||||
{
|
|
||||||
// accumulated mesh references by this node
|
// accumulated mesh references by this node
|
||||||
std::vector<size_t> newMeshRefs;
|
std::vector<size_t> newMeshRefs;
|
||||||
newMeshRefs.reserve(pNode->mMeshes.size());
|
newMeshRefs.reserve(pNode->mMeshes.size());
|
||||||
|
|
||||||
// add a mesh for each subgroup in each collada mesh
|
// add a mesh for each subgroup in each collada mesh
|
||||||
for( const Collada::MeshInstance& mid : pNode->mMeshes)
|
for( const Collada::MeshInstance& mid : pNode->mMeshes) {
|
||||||
{
|
const Collada::Mesh* srcMesh = nullptr;
|
||||||
const Collada::Mesh* srcMesh = NULL;
|
const Collada::Controller* srcController = nullptr;
|
||||||
const Collada::Controller* srcController = NULL;
|
|
||||||
|
|
||||||
// find the referred mesh
|
// find the referred mesh
|
||||||
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController);
|
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController);
|
||||||
if( srcMeshIt == pParser.mMeshLibrary.end())
|
if( srcMeshIt == pParser.mMeshLibrary.end()) {
|
||||||
{
|
|
||||||
// if not found in the mesh-library, it might also be a controller referring to a mesh
|
// if not found in the mesh-library, it might also be a controller referring to a mesh
|
||||||
ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController);
|
ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController);
|
||||||
if( srcContrIt != pParser.mControllerLibrary.end())
|
if( srcContrIt != pParser.mControllerLibrary.end()) {
|
||||||
{
|
|
||||||
srcController = &srcContrIt->second;
|
srcController = &srcContrIt->second;
|
||||||
srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId);
|
srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId);
|
||||||
if( srcMeshIt != pParser.mMeshLibrary.end())
|
if( srcMeshIt != pParser.mMeshLibrary.end()) {
|
||||||
srcMesh = srcMeshIt->second;
|
srcMesh = srcMeshIt->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !srcMesh)
|
if( !srcMesh) {
|
||||||
{
|
|
||||||
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
|
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
// ID found in the mesh library -> direct reference to an unskinned mesh
|
// ID found in the mesh library -> direct reference to an unskinned mesh
|
||||||
srcMesh = srcMeshIt->second;
|
srcMesh = srcMeshIt->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a mesh for each of its subgroups
|
// build a mesh for each of its subgroups
|
||||||
size_t vertexStart = 0, faceStart = 0;
|
size_t vertexStart = 0, faceStart = 0;
|
||||||
for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm)
|
for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm) {
|
||||||
{
|
|
||||||
const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm];
|
const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm];
|
||||||
if( submesh.mNumFaces == 0)
|
if( submesh.mNumFaces == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// find material assigned to this submesh
|
// find material assigned to this submesh
|
||||||
std::string meshMaterial;
|
std::string meshMaterial;
|
||||||
std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial);
|
std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial);
|
||||||
|
|
||||||
const Collada::SemanticMappingTable* table = NULL;
|
const Collada::SemanticMappingTable* table = nullptr;
|
||||||
if( meshMatIt != mid.mMaterials.end())
|
if( meshMatIt != mid.mMaterials.end()) {
|
||||||
{
|
|
||||||
table = &meshMatIt->second;
|
table = &meshMatIt->second;
|
||||||
meshMaterial = table->mMatName;
|
meshMaterial = table->mMatName;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
|
ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
|
||||||
mid.mMeshOrController, ">." );
|
mid.mMeshOrController, ">." );
|
||||||
if( !mid.mMaterials.empty() )
|
if( !mid.mMaterials.empty() ) {
|
||||||
meshMaterial = mid.mMaterials.begin()->second.mMatName;
|
meshMaterial = mid.mMaterials.begin()->second.mMatName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
|
// OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
|
||||||
// given. The only mapping stuff which we do actually support is the UV channel.
|
// given. The only mapping stuff which we do actually support is the UV channel.
|
||||||
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 = 0;
|
||||||
if( matIt != mMaterialIndexByName.end())
|
if( matIt != mMaterialIndexByName.end()) {
|
||||||
matIdx = static_cast<unsigned int>(matIt->second);
|
matIdx = static_cast<unsigned int>(matIt->second);
|
||||||
else
|
}
|
||||||
matIdx = 0;
|
|
||||||
|
|
||||||
if (table && !table->mMap.empty() ) {
|
if (table && !table->mMap.empty() ) {
|
||||||
std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx];
|
std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx];
|
||||||
|
@ -553,9 +531,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
||||||
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index);
|
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index);
|
||||||
if( dstMeshIt != mMeshIndexByID.end()) {
|
if( dstMeshIt != mMeshIndexByID.end()) {
|
||||||
newMeshRefs.push_back( dstMeshIt->second);
|
newMeshRefs.push_back( dstMeshIt->second);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// else we have to add the mesh to the collection and store its newly assigned index at the node
|
// else we have to add the mesh to the collection and store its newly assigned index at the node
|
||||||
aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
|
aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
|
||||||
|
|
||||||
|
@ -567,22 +543,18 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
||||||
|
|
||||||
// assign the material index
|
// assign the material index
|
||||||
dstMesh->mMaterialIndex = matIdx;
|
dstMesh->mMaterialIndex = matIdx;
|
||||||
if(dstMesh->mName.length == 0)
|
if(dstMesh->mName.length == 0) {
|
||||||
{
|
|
||||||
dstMesh->mName = mid.mMeshOrController;
|
dstMesh->mName = mid.mMeshOrController;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now place all mesh references we gathered in the target node
|
// now place all mesh references we gathered in the target node
|
||||||
pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
|
pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
|
||||||
if( newMeshRefs.size())
|
if( newMeshRefs.size()) {
|
||||||
{
|
struct UIntTypeConverter {
|
||||||
struct UIntTypeConverter
|
unsigned int operator()(const size_t& v) const {
|
||||||
{
|
|
||||||
unsigned int operator()(const size_t& v) const
|
|
||||||
{
|
|
||||||
return static_cast<unsigned int>(v);
|
return static_cast<unsigned int>(v);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -594,25 +566,27 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Find mesh from either meshes or morph target meshes
|
// Find mesh from either meshes or morph target meshes
|
||||||
aiMesh *ColladaLoader::findMesh(std::string meshid)
|
aiMesh *ColladaLoader::findMesh(std::string meshid) {
|
||||||
{
|
for (unsigned int i = 0; i < mMeshes.size(); ++i ) {
|
||||||
for (unsigned int i = 0; i < mMeshes.size(); i++)
|
if (std::string(mMeshes[i]->mName.data) == meshid) {
|
||||||
if (std::string(mMeshes[i]->mName.data) == meshid)
|
|
||||||
return mMeshes[i];
|
return mMeshes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mTargetMeshes.size(); i++)
|
for (unsigned int i = 0; i < mTargetMeshes.size(); ++i ) {
|
||||||
if (std::string(mTargetMeshes[i]->mName.data) == meshid)
|
if (std::string(mTargetMeshes[i]->mName.data) == meshid) {
|
||||||
return mTargetMeshes[i];
|
return mTargetMeshes[i];
|
||||||
|
}
|
||||||
return NULL;
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// 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,
|
||||||
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
|
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace) {
|
||||||
{
|
std::unique_ptr<aiMesh> dstMesh(new aiMesh);
|
||||||
aiMesh* dstMesh = new aiMesh;
|
|
||||||
|
|
||||||
dstMesh->mName = pSrcMesh->mName;
|
dstMesh->mName = pSrcMesh->mName;
|
||||||
|
|
||||||
|
@ -629,24 +603,21 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
// normals, if given. HACK: (thom) Due to the glorious Collada spec we never
|
// normals, if given. HACK: (thom) Due to the glorious Collada spec we never
|
||||||
// know if we have the same number of normals as there are positions. So we
|
// know if we have the same number of normals as there are positions. So we
|
||||||
// also ignore any vertex attribute if it has a different count
|
// also ignore any vertex attribute if it has a different count
|
||||||
if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices)
|
if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices) {
|
||||||
{
|
|
||||||
dstMesh->mNormals = new aiVector3D[numVertices];
|
dstMesh->mNormals = new aiVector3D[numVertices];
|
||||||
std::copy( pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() +
|
std::copy( pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() +
|
||||||
pStartVertex + numVertices, dstMesh->mNormals);
|
pStartVertex + numVertices, dstMesh->mNormals);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tangents, if given.
|
// tangents, if given.
|
||||||
if( pSrcMesh->mTangents.size() >= pStartVertex + numVertices)
|
if( pSrcMesh->mTangents.size() >= pStartVertex + numVertices) {
|
||||||
{
|
|
||||||
dstMesh->mTangents = new aiVector3D[numVertices];
|
dstMesh->mTangents = new aiVector3D[numVertices];
|
||||||
std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() +
|
std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() +
|
||||||
pStartVertex + numVertices, dstMesh->mTangents);
|
pStartVertex + numVertices, dstMesh->mTangents);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bitangents, if given.
|
// bitangents, if given.
|
||||||
if( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices)
|
if( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) {
|
||||||
{
|
|
||||||
dstMesh->mBitangents = new aiVector3D[numVertices];
|
dstMesh->mBitangents = new aiVector3D[numVertices];
|
||||||
std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() +
|
std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() +
|
||||||
pStartVertex + numVertices, dstMesh->mBitangents);
|
pStartVertex + numVertices, dstMesh->mBitangents);
|
||||||
|
@ -654,13 +625,12 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
|
|
||||||
// same for texturecoords, as many as we have
|
// same for texturecoords, as many as we have
|
||||||
// empty slots are not allowed, need to pack and adjust UV indexes accordingly
|
// empty slots are not allowed, need to pack and adjust UV indexes accordingly
|
||||||
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
|
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) {
|
||||||
{
|
if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
|
||||||
if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices)
|
|
||||||
{
|
|
||||||
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
|
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
|
||||||
for( size_t b = 0; b < numVertices; ++b)
|
for( size_t b = 0; b < numVertices; ++b) {
|
||||||
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b];
|
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b];
|
||||||
|
}
|
||||||
|
|
||||||
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
|
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
|
||||||
++real;
|
++real;
|
||||||
|
@ -668,10 +638,8 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
}
|
}
|
||||||
|
|
||||||
// same for vertex colors, as many as we have. again the same packing to avoid empty slots
|
// same for vertex colors, as many as we have. again the same packing to avoid empty slots
|
||||||
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
|
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) {
|
||||||
{
|
if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices) {
|
||||||
if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices)
|
|
||||||
{
|
|
||||||
dstMesh->mColors[real] = new aiColor4D[numVertices];
|
dstMesh->mColors[real] = new aiColor4D[numVertices];
|
||||||
std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]);
|
std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]);
|
||||||
++real;
|
++real;
|
||||||
|
@ -682,14 +650,14 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
size_t vertex = 0;
|
size_t vertex = 0;
|
||||||
dstMesh->mNumFaces = static_cast<unsigned int>(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 = static_cast<unsigned int>(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] = static_cast<unsigned int>(vertex++);
|
face.mIndices[b] = static_cast<unsigned int>(vertex++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create morph target meshes if any
|
// create morph target meshes if any
|
||||||
|
@ -697,14 +665,12 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
std::vector<float> targetWeights;
|
std::vector<float> targetWeights;
|
||||||
Collada::MorphMethod method = Collada::Normalized;
|
Collada::MorphMethod method = Collada::Normalized;
|
||||||
|
|
||||||
for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
|
for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
|
||||||
it != pParser.mControllerLibrary.end(); it++)
|
it != pParser.mControllerLibrary.end(); it++) {
|
||||||
{
|
|
||||||
const Collada::Controller &c = it->second;
|
const Collada::Controller &c = it->second;
|
||||||
const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId);
|
const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId);
|
||||||
|
|
||||||
if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName)
|
if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) {
|
||||||
{
|
|
||||||
const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget);
|
const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget);
|
||||||
const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight);
|
const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight);
|
||||||
const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource);
|
const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource);
|
||||||
|
@ -713,34 +679,34 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
// take method
|
// take method
|
||||||
method = c.mMethod;
|
method = c.mMethod;
|
||||||
|
|
||||||
if (!targetData.mIsStringArray)
|
if (!targetData.mIsStringArray) {
|
||||||
throw DeadlyImportError( "target data must contain id. ");
|
throw DeadlyImportError( "target data must contain id. ");
|
||||||
if (weightData.mIsStringArray)
|
}
|
||||||
|
if (weightData.mIsStringArray) {
|
||||||
throw DeadlyImportError( "target weight data must not be textual ");
|
throw DeadlyImportError( "target weight data must not be textual ");
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < targetData.mStrings.size(); ++i)
|
for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) {
|
||||||
{
|
|
||||||
const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i));
|
const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i));
|
||||||
|
|
||||||
aiMesh *aimesh = findMesh(targetMesh->mName);
|
aiMesh *aimesh = findMesh(targetMesh->mName);
|
||||||
if (!aimesh)
|
if (!aimesh) {
|
||||||
{
|
if (targetMesh->mSubMeshes.size() > 1) {
|
||||||
if (targetMesh->mSubMeshes.size() > 1)
|
|
||||||
throw DeadlyImportError( "Morhing target mesh must be a single");
|
throw DeadlyImportError( "Morhing target mesh must be a single");
|
||||||
|
}
|
||||||
aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0);
|
aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0);
|
||||||
mTargetMeshes.push_back(aimesh);
|
mTargetMeshes.push_back(aimesh);
|
||||||
}
|
}
|
||||||
targetMeshes.push_back(aimesh);
|
targetMeshes.push_back(aimesh);
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i < weightData.mValues.size(); ++i)
|
for (unsigned int i = 0; i < weightData.mValues.size(); ++i) {
|
||||||
targetWeights.push_back(weightData.mValues.at(i));
|
targetWeights.push_back(weightData.mValues.at(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size())
|
if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size()) {
|
||||||
{
|
|
||||||
std::vector<aiAnimMesh*> animMeshes;
|
std::vector<aiAnimMesh*> animMeshes;
|
||||||
for (unsigned int i = 0; i < targetMeshes.size(); i++)
|
for (unsigned int i = 0; i < targetMeshes.size(); ++i ) {
|
||||||
{
|
|
||||||
aiMesh* targetMesh = targetMeshes.at(i);
|
aiMesh* targetMesh = targetMeshes.at(i);
|
||||||
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh);
|
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh);
|
||||||
float weight = targetWeights[i];
|
float weight = targetWeights[i];
|
||||||
|
@ -753,13 +719,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
: aiMorphingMethod_MORPH_NORMALIZED;
|
: aiMorphingMethod_MORPH_NORMALIZED;
|
||||||
dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
|
dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
|
||||||
dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
|
dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
|
||||||
for (unsigned int i = 0; i < animMeshes.size(); i++)
|
for (unsigned int i = 0; i < animMeshes.size(); ++i ) {
|
||||||
dstMesh->mAnimMeshes[i] = animMeshes.at(i);
|
dstMesh->mAnimMeshes[i] = animMeshes.at(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create bones if given
|
// create bones if given
|
||||||
if( pSrcController && pSrcController->mType == Collada::Skin)
|
if( pSrcController && pSrcController->mType == Collada::Skin) {
|
||||||
{
|
|
||||||
// resolve references - joint names
|
// resolve references - joint names
|
||||||
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
|
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
|
||||||
const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
|
const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
|
||||||
|
@ -790,15 +756,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(),pSrcController->mWeights.end());
|
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(),pSrcController->mWeights.end());
|
||||||
|
|
||||||
IndexPairVector::const_iterator pit = pSrcController->mWeights.begin();
|
IndexPairVector::const_iterator pit = pSrcController->mWeights.begin();
|
||||||
for( size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a)
|
for( size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) {
|
||||||
{
|
|
||||||
weightStartPerVertex[a] = pit;
|
weightStartPerVertex[a] = pit;
|
||||||
pit += pSrcController->mWeightCounts[a];
|
pit += pSrcController->mWeightCounts[a];
|
||||||
}
|
}
|
||||||
|
|
||||||
// now for each vertex put the corresponding vertex weights into each bone's weight collection
|
// now for each vertex put the corresponding vertex weights into each bone's weight collection
|
||||||
for( size_t a = pStartVertex; a < pStartVertex + numVertices; ++a)
|
for( size_t a = pStartVertex; a < pStartVertex + numVertices; ++a) {
|
||||||
{
|
|
||||||
// which position index was responsible for this vertex? that's also the index by which
|
// which position index was responsible for this vertex? that's also the index by which
|
||||||
// the controller assigns the vertex weights
|
// the controller assigns the vertex weights
|
||||||
size_t orgIndex = pSrcMesh->mFacePosIndices[a];
|
size_t orgIndex = pSrcMesh->mFacePosIndices[a];
|
||||||
|
@ -898,7 +862,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dstMesh;
|
return dstMesh.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue