Merge pull request #3225 from assimp/inhosens-master

Inhosens master
pull/3048/head^2
Kim Kulling 2020-05-15 15:16:47 +02:00 committed by GitHub
commit b7de061749
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 1769 additions and 87 deletions

View File

@ -83,6 +83,18 @@ static const aiImporterDesc desc = {
"dae zae" "dae zae"
}; };
static const float kMillisecondsFromSeconds = 1000.f;
// Add an item of metadata to a node
// Assumes the key is not already in the list
template <typename T>
inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
if (nullptr == node->mMetaData) {
node->mMetaData = new aiMetadata();
}
node->mMetaData->Add(key, value);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ColladaLoader::ColladaLoader() : ColladaLoader::ColladaLoader() :
@ -230,27 +242,15 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
} }
} }
// store all meshes
StoreSceneMeshes(pScene); StoreSceneMeshes(pScene);
// store all materials
StoreSceneMaterials(pScene); StoreSceneMaterials(pScene);
// store all textures
StoreSceneTextures(pScene); StoreSceneTextures(pScene);
// store all lights
StoreSceneLights(pScene); StoreSceneLights(pScene);
// store all cameras
StoreSceneCameras(pScene); StoreSceneCameras(pScene);
// store all animations
StoreAnimations(pScene, parser); StoreAnimations(pScene, parser);
// If no meshes have been loaded, it's probably just an animated skeleton. // If no meshes have been loaded, it's probably just an animated skeleton.
if (0u == pScene->mNumMeshes) { if (0u == pScene->mNumMeshes) {
if (!noSkeletonMesh) { if (!noSkeletonMesh) {
SkeletonMeshBuilder hero(pScene); SkeletonMeshBuilder hero(pScene);
} }
@ -258,15 +258,6 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
} }
} }
// Add an item of metadata to a node
// Assumes the key is not already in the list
template <typename T>
inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
if (nullptr == node->mMetaData)
node->mMetaData = new aiMetadata();
node->mMetaData->Add(key, value);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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) {
@ -277,10 +268,12 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
node->mName.Set(FindNameForNode(pNode)); node->mName.Set(FindNameForNode(pNode));
// if we're not using the unique IDs, hold onto them for reference and export // if we're not using the unique IDs, hold onto them for reference and export
if (useColladaName) { if (useColladaName) {
if (!pNode->mID.empty()) if (!pNode->mID.empty()) {
AddNodeMetaData(node, AI_METADATA_COLLADA_ID, aiString(pNode->mID)); AddNodeMetaData(node, AI_METADATA_COLLADA_ID, aiString(pNode->mID));
if (!pNode->mSID.empty()) }
if (!pNode->mSID.empty()) {
AddNodeMetaData(node, AI_METADATA_COLLADA_SID, aiString(pNode->mSID)); AddNodeMetaData(node, AI_METADATA_COLLADA_SID, aiString(pNode->mSID));
}
} }
// calculate the transformation matrix for it // calculate the transformation matrix for it
@ -305,13 +298,8 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
node->mChildren[pNode->mChildren.size() + a]->mParent = node; node->mChildren[pNode->mChildren.size() + a]->mParent = node;
} }
// construct meshes
BuildMeshesForNode(pParser, pNode, node); BuildMeshesForNode(pParser, pNode, node);
// construct cameras
BuildCamerasForNode(pParser, pNode, node); BuildCamerasForNode(pParser, pNode, node);
// construct lights
BuildLightsForNode(pParser, pNode, node); BuildLightsForNode(pParser, pNode, node);
return node; return node;
@ -347,9 +335,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Col
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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) {
@ -599,6 +585,10 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Find mesh from either meshes or morph target meshes // Find mesh from either meshes or morph target meshes
aiMesh *ColladaLoader::findMesh(const std::string &meshid) { aiMesh *ColladaLoader::findMesh(const std::string &meshid) {
if ( meshid.empty()) {
return nullptr;
}
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];
@ -1386,9 +1376,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
double time = double(mat.d4); // remember? time is stored in mat.d4 double time = double(mat.d4); // remember? time is stored in mat.d4
mat.d4 = 1.0f; mat.d4 = 1.0f;
dstAnim->mPositionKeys[a].mTime = time; dstAnim->mPositionKeys[a].mTime = time * kMillisecondsFromSeconds ;
dstAnim->mRotationKeys[a].mTime = time; dstAnim->mRotationKeys[a].mTime = time * kMillisecondsFromSeconds ;
dstAnim->mScalingKeys[a].mTime = time; dstAnim->mScalingKeys[a].mTime = time * kMillisecondsFromSeconds ;
mat.Decompose(dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue); mat.Decompose(dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
} }
@ -1409,7 +1399,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
if (e.mTargetId.find("morph-weights") != std::string::npos) if (e.mTargetId.find("morph-weights") != std::string::npos)
morphChannels.push_back(e); morphChannels.push_back(e);
} }
if (morphChannels.size() > 0) { if (!morphChannels.empty() ) {
// either 1) morph weight animation count should contain morph target count channels // either 1) morph weight animation count should contain morph target count channels
// or 2) one channel with morph target count arrays // or 2) one channel with morph target count arrays
// assume first // assume first
@ -1418,7 +1408,6 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
morphAnim->mName.Set(nodeName); morphAnim->mName.Set(nodeName);
std::vector<MorphTimeValues> morphTimeValues; std::vector<MorphTimeValues> morphTimeValues;
int morphAnimChannelIndex = 0; int morphAnimChannelIndex = 0;
for (std::vector<Collada::ChannelEntry>::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it) { for (std::vector<Collada::ChannelEntry>::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it) {
Collada::ChannelEntry &e = *it; Collada::ChannelEntry &e = *it;
@ -1430,8 +1419,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// weight target can be in format Weight_M_N, Weight_N, WeightN, or some other way // 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 // 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++) for (unsigned int i = 0; i < e.mTimeData->mValues.size(); i++) {
insertMorphTimeValue(morphTimeValues, e.mTimeData->mValues.at(i), e.mValueData->mValues.at(i), morphAnimChannelIndex); insertMorphTimeValue(morphTimeValues, e.mTimeData->mValues[i], e.mValueData->mValues[i], morphAnimChannelIndex);
}
++morphAnimChannelIndex; ++morphAnimChannelIndex;
} }
@ -1443,8 +1433,8 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
morphAnim->mKeys[key].mValues = new unsigned int[morphChannels.size()]; morphAnim->mKeys[key].mValues = new unsigned int[morphChannels.size()];
morphAnim->mKeys[key].mWeights = new double[morphChannels.size()]; morphAnim->mKeys[key].mWeights = new double[morphChannels.size()];
morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime; morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime * kMillisecondsFromSeconds ;
for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); valueIndex++) { for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); ++valueIndex ) {
morphAnim->mKeys[key].mValues[valueIndex] = valueIndex; morphAnim->mKeys[key].mValues[valueIndex] = valueIndex;
morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex); morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex);
} }
@ -1494,18 +1484,22 @@ void ColladaLoader::AddTexture(aiMaterial &mat, const ColladaParser &pParser,
// mapping mode // mapping mode
int map = aiTextureMapMode_Clamp; int map = aiTextureMapMode_Clamp;
if (sampler.mWrapU) if (sampler.mWrapU) {
map = aiTextureMapMode_Wrap; map = aiTextureMapMode_Wrap;
if (sampler.mWrapU && sampler.mMirrorU) }
if (sampler.mWrapU && sampler.mMirrorU) {
map = aiTextureMapMode_Mirror; map = aiTextureMapMode_Mirror;
}
mat.AddProperty(&map, 1, _AI_MATKEY_MAPPINGMODE_U_BASE, type, idx); mat.AddProperty(&map, 1, _AI_MATKEY_MAPPINGMODE_U_BASE, type, idx);
map = aiTextureMapMode_Clamp; map = aiTextureMapMode_Clamp;
if (sampler.mWrapV) if (sampler.mWrapV) {
map = aiTextureMapMode_Wrap; map = aiTextureMapMode_Wrap;
if (sampler.mWrapV && sampler.mMirrorV) }
if (sampler.mWrapV && sampler.mMirrorV) {
map = aiTextureMapMode_Mirror; map = aiTextureMapMode_Mirror;
}
mat.AddProperty(&map, 1, _AI_MATKEY_MAPPINGMODE_V_BASE, type, idx); mat.AddProperty(&map, 1, _AI_MATKEY_MAPPINGMODE_V_BASE, type, idx);
@ -1526,9 +1520,9 @@ void ColladaLoader::AddTexture(aiMaterial &mat, const ColladaParser &pParser,
// number in the channel name. We assume it is the zero-based index into the // number in the channel name. We assume it is the zero-based index into the
// UV channel array of all corresponding meshes. It could also be one-based // UV channel array of all corresponding meshes. It could also be one-based
// for some exporters, but we won't care of it unless someone complains about. // for some exporters, but we won't care of it unless someone complains about.
if (sampler.mUVId != UINT_MAX) if (sampler.mUVId != UINT_MAX) {
map = sampler.mUVId; map = sampler.mUVId;
else { } else {
map = -1; map = -1;
for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) { for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
if (IsNumeric(*it)) { if (IsNumeric(*it)) {
@ -1553,27 +1547,27 @@ void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pSce
// resolve shading mode // resolve shading mode
int shadeMode; int shadeMode;
if (effect.mFaceted) /* fixme */ if (effect.mFaceted) {
shadeMode = aiShadingMode_Flat; shadeMode = aiShadingMode_Flat;
else { } else {
switch (effect.mShadeType) { switch (effect.mShadeType) {
case Collada::Shade_Constant: case Collada::Shade_Constant:
shadeMode = aiShadingMode_NoShading; shadeMode = aiShadingMode_NoShading;
break; break;
case Collada::Shade_Lambert: case Collada::Shade_Lambert:
shadeMode = aiShadingMode_Gouraud; shadeMode = aiShadingMode_Gouraud;
break; break;
case Collada::Shade_Blinn: case Collada::Shade_Blinn:
shadeMode = aiShadingMode_Blinn; shadeMode = aiShadingMode_Blinn;
break; break;
case Collada::Shade_Phong: case Collada::Shade_Phong:
shadeMode = aiShadingMode_Phong; shadeMode = aiShadingMode_Phong;
break; break;
default: default:
ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading"); ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
shadeMode = aiShadingMode_Gouraud; shadeMode = aiShadingMode_Gouraud;
break; break;
} }
} }
mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL); mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
@ -1679,23 +1673,6 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
// ScenePreprocessor generates a default material automatically if none is there. // ScenePreprocessor generates a default material automatically if none is there.
// All further code here in this loader works well without a valid material so // All further code here in this loader works well without a valid material so
// we can safely let it to ScenePreprocessor. // we can safely let it to ScenePreprocessor.
#if 0
if (newMats.size() == 0)
{
aiMaterial* mat = new aiMaterial;
aiString name(AI_DEFAULT_MATERIAL_NAME);
mat->AddProperty(&name, AI_MATKEY_NAME);
const int shadeMode = aiShadingMode_Phong;
mat->AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor4D colAmbient(0.2, 0.2, 0.2, 1.0), colDiffuse(0.8, 0.8, 0.8, 1.0), colSpecular(0.5, 0.5, 0.5, 0.5);
mat->AddProperty(&colAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty(&colDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty(&colSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
const ai_real specExp = 5.0;
mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS);
}
#endif
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1755,20 +1732,21 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// and add this texture to the list // and add this texture to the list
mTextures.push_back(tex); mTextures.push_back(tex);
} else { return result;
if (imIt->second.mFileName.empty()) {
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
}
result.Set(imIt->second.mFileName);
} }
if (imIt->second.mFileName.empty()) {
throw DeadlyImportError("Collada: Invalid texture, no data or file reference given");
}
result.Set(imIt->second.mFileName);
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array. // Reads a float value from an accessor and its data array.
ai_real ColladaLoader::ReadFloat(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex, size_t pOffset) const { ai_real ColladaLoader::ReadFloat(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex, size_t pOffset) const {
// FIXME: (thom) Test for data type here in every access? For the moment, I leave this to the caller
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset; size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size()); ai_assert(pos < pData.mValues.size());
return pData.mValues[pos]; return pData.mValues[pos];

File diff suppressed because it is too large Load Diff