diff --git a/Engine/source/ts/assimp/assimpAppMesh.cpp b/Engine/source/ts/assimp/assimpAppMesh.cpp index cad5f5f55..eaabde89f 100644 --- a/Engine/source/ts/assimp/assimpAppMesh.cpp +++ b/Engine/source/ts/assimp/assimpAppMesh.cpp @@ -123,6 +123,10 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset) bool flipNormals = ColladaUtils::getOptions().invertNormals; + MatrixF normalMat(objOffset); + normalMat.inverse(); + normalMat.transpose(); + bool noUVFound = false; for (U32 i = 0; i < mMeshData->mNumVertices; i++) { @@ -144,6 +148,10 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset) objOffset.mulP(tmpVert); + normalMat.mulV(tmpNormal); + if (mMeshData->HasNormals()) + tmpNormal.normalize(); + points.push_back(tmpVert); if (mMeshData->HasTextureCoords(0)) diff --git a/Engine/source/ts/assimp/assimpAppNode.cpp b/Engine/source/ts/assimp/assimpAppNode.cpp index 4fbd7779e..3cfb66f1e 100644 --- a/Engine/source/ts/assimp/assimpAppNode.cpp +++ b/Engine/source/ts/assimp/assimpAppNode.cpp @@ -131,7 +131,9 @@ void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animS for (U32 k = 0; k < animSeq->mNumChannels; ++k) { const aiNodeAnim* nodeAnim = animSeq->mChannels[k]; - if (dStrcmp(mName, nodeAnim->mNodeName.C_Str()) != 0) + String m_node_name = mName; + String ai_node_name = nodeAnim->mNodeName.C_Str(); + if (!ai_node_name.equal(m_node_name)) continue; Point3F translation(Point3F::Zero); @@ -277,6 +279,37 @@ MatrixF AssimpAppNode::getNodeTransform(F32 time) } } +MatrixF AssimpAppNode::getBoundsReferenceTransform(F32 time) +{ + // Deliberately independent of this node's own raw local data (rotation, + // scale) and of axisCorrectionMat + MatrixF mat(true); + mat.scale(ColladaUtils::getOptions().unit * ColladaUtils::getOptions().formatScaleFactor); + + if (mScene && mScene->mRootNode) + { + MatrixF sceneRootMat(true); + assimpToTorqueMat(mScene->mRootNode->mTransformation, sceneRootMat); + mat.mulL(sceneRootMat); + } + + return mat; +} + +MatrixF AssimpAppNode::getOwnRotationOnly(F32 time) +{ + // This node's own raw mNodeTransform + MatrixF rotOnly(mNodeTransform); + Point3F rawScale = rotOnly.getScale(); + Point3F invScale( + rawScale.x ? 1.0f / rawScale.x : 0.0f, + rawScale.y ? 1.0f / rawScale.y : 0.0f, + rawScale.z ? 1.0f / rawScale.z : 0.0f); + rotOnly.scale(invScale); + rotOnly.setPosition(Point3F::Zero); + return rotOnly; +} + void AssimpAppNode::assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat) { outMat.setRow(0, Point4F((F32)inAssimpMat.a1, (F32)inAssimpMat.a2, diff --git a/Engine/source/ts/assimp/assimpAppNode.h b/Engine/source/ts/assimp/assimpAppNode.h index 62c7e0c49..1d61c6b02 100644 --- a/Engine/source/ts/assimp/assimpAppNode.h +++ b/Engine/source/ts/assimp/assimpAppNode.h @@ -122,6 +122,8 @@ public: } MatrixF getNodeTransform(F32 time) override; + MatrixF getBoundsReferenceTransform(F32 time) override; + MatrixF getOwnRotationOnly(F32 time) override; bool animatesTransform(const AppSequence* appSeq) override; bool isParentRoot() override { return (appParent == NULL); } diff --git a/Engine/source/ts/assimp/assimpShapeLoader.cpp b/Engine/source/ts/assimp/assimpShapeLoader.cpp index b8e42e7ec..7a3d5ae8a 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.cpp +++ b/Engine/source/ts/assimp/assimpShapeLoader.cpp @@ -91,9 +91,9 @@ static struct _privateRegisterAssimp { const String& ext = tokens[t]; if (ext.isEmpty() || - ext.equal("dae", String::NoCase) || // filter out collada importer formats (for now). - ext.equal("zae", String::NoCase) || - ext.equal("xml", String::NoCase) + ext.equal("dae", String::NoCase) || // filter out collada importer formats (for now). + ext.equal("zae", String::NoCase) || + ext.equal("xml", String::NoCase) ) continue; @@ -135,7 +135,7 @@ static struct _privateRegisterAssimp //----------------------------------------------------------------------------- -AssimpShapeLoader::AssimpShapeLoader() +AssimpShapeLoader::AssimpShapeLoader() { mScene = NULL; } @@ -275,8 +275,6 @@ void AssimpShapeLoader::enumerateScene() } } - ColladaUtils::getOptions().upAxis = UPAXISTYPE_Z_UP; - // Compute & apply axis conversion matrix getRootAxisTransform(); for (U32 i = 0; i < mScene->mNumTextures; ++i) { @@ -311,11 +309,9 @@ void AssimpShapeLoader::enumerateScene() } } - // Add a bounds node if none exists if (!boundsNode) { - aiNode* reqNode = new aiNode("bounds"); - reqNode->mTransformation = aiMatrix4x4();// *sceneRoot; + reqNode->mTransformation = aiMatrix4x4(); AssimpAppNode* appBoundsNode = new AssimpAppNode(mScene, reqNode); if (!processNode(appBoundsNode)) { delete appBoundsNode; @@ -383,34 +379,42 @@ void AssimpShapeLoader::configureImportUnits() { void AssimpShapeLoader::getRootAxisTransform() { - aiMetadata* meta = mScene->mMetaData; - if (!meta) - { - // assume y up - ColladaUtils::getOptions().upAxis = UPAXISTYPE_Y_UP; - return; - } - - // Fetch metadata values int upAxis = 1, upSign = 1; int frontAxis = 2, frontSign = -1; int coordAxis = 0, coordSign = 1; - meta->Get("UpAxis", upAxis); - meta->Get("UpAxisSign", upSign); - meta->Get("FrontAxis", frontAxis); - meta->Get("FrontAxisSign", frontSign); - meta->Get("CoordAxis", coordAxis); - meta->Get("CoordAxisSign", coordSign); - - switch (upAxis) + aiMetadata* meta = mScene->mMetaData; + if (meta) { - case 0: ColladaUtils::getOptions().upAxis = UPAXISTYPE_X_UP; break; - case 1: ColladaUtils::getOptions().upAxis = UPAXISTYPE_Y_UP; break; - case 2: ColladaUtils::getOptions().upAxis = UPAXISTYPE_Z_UP; break; - default: ColladaUtils::getOptions().upAxis = UPAXISTYPE_Y_UP; break; + meta->Get("UpAxis", upAxis); + meta->Get("UpAxisSign", upSign); + meta->Get("FrontAxis", frontAxis); + meta->Get("FrontAxisSign", frontSign); + meta->Get("CoordAxis", coordAxis); + meta->Get("CoordAxisSign", coordSign); } + if (ColladaUtils::getOptions().upAxis != UPAXISTYPE_COUNT) + { + switch (ColladaUtils::getOptions().upAxis) + { + case UPAXISTYPE_X_UP: upAxis = 0; break; + case UPAXISTYPE_Y_UP: upAxis = 1; break; + case UPAXISTYPE_Z_UP: upAxis = 2; break; + default: break; + } + } + + domUpAxisType canonicalAxis; + switch (upAxis) + { + case 0: canonicalAxis = UPAXISTYPE_X_UP; break; + case 1: canonicalAxis = UPAXISTYPE_Y_UP; break; + case 2: canonicalAxis = UPAXISTYPE_Z_UP; break; + default: canonicalAxis = UPAXISTYPE_Y_UP; break; + } + + ColladaUtils::getOptions().upAxis = canonicalAxis; MatrixF rot(true); // Build source basis @@ -531,7 +535,7 @@ void AssimpShapeLoader::computeBounds(Box3F& bounds) { for (S32 iFrame = 0; iFrame < seq.numKeyframes; iFrame++) { - S32 index = seq.baseTranslation + seq.translationMatters.count(iNode)*seq.numKeyframes + iFrame; + S32 index = seq.baseTranslation + seq.translationMatters.count(iNode) * seq.numKeyframes + iFrame; shape->nodeTranslations[index] += shapeOffset; } } @@ -682,7 +686,7 @@ bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path) FileTime daeModifyTime; if (!Platform::getFileTimes(path.getFullPath(), NULL, &daeModifyTime) || - (!forceLoad && (Platform::compareFileTimes(cachedModifyTime, daeModifyTime) >= 0) )) + (!forceLoad && (Platform::compareFileTimes(cachedModifyTime, daeModifyTime) >= 0))) { // Original file not found, or cached DTS is newer return true; @@ -770,7 +774,7 @@ void AssimpShapeLoader::extractTexture(U32 index, aiTexture* pTex) if (pTex->mHeight == 0) { // Compressed format, write the data directly to disc texPath.setExtension(pTex->achFormatHint); - FileStream *outputStream; + FileStream* outputStream; if ((outputStream = FileStream::createAndOpen(texPath.getFullPath(), Torque::FS::File::Write, FileStream::AsyncMode::Background)) != NULL) { outputStream->setPosition(0); @@ -784,7 +788,7 @@ void AssimpShapeLoader::extractTexture(U32 index, aiTexture* pTex) GFXTexHandle shapeTex; shapeTex.set(pTex->mWidth, pTex->mHeight, GFXFormatR8G8B8A8_SRGB, &GFXDynamicTextureSRGBProfile, String::ToString("AssimpShapeLoader (%s:%i)", __FILE__, __LINE__), 1, 0); - GFXLockedRect *rect = shapeTex.lock(); + GFXLockedRect* rect = shapeTex.lock(); for (U32 y = 0; y < pTex->mHeight; ++y) { @@ -970,7 +974,7 @@ bool AssimpShapeLoader::getMetaString(const char* key, String& stringVal) } //----------------------------------------------------------------------------- /// This function is invoked by the resource manager based on file extension. -static bool sReadAssimp(const Torque::Path &path, TSShape*& res_shape) +static bool sReadAssimp(const Torque::Path& path, TSShape*& res_shape) { if (!Torque::FS::IsFile(path)) { @@ -991,11 +995,9 @@ static bool sReadAssimp(const Torque::Path &path, TSShape*& res_shape) AssimpShapeLoader loader; TSShape* tss = loader.generateShape(path); + // override default options with the ones provided by the assimp import. if (tscon && autoDetectUpAxis) - { tscon->mOptions = ColladaUtils::getOptions(); - } - if (tss) { TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Import complete"); diff --git a/Engine/source/ts/loader/appNode.h b/Engine/source/ts/loader/appNode.h index 65ef92e40..2b6f14cab 100644 --- a/Engine/source/ts/loader/appNode.h +++ b/Engine/source/ts/loader/appNode.h @@ -65,6 +65,14 @@ public: virtual MatrixF getNodeTransform(F32 time) = 0; + /// The transform TSShapeLoader::getLocalNodeMatrix() uses as the bounds + /// reference frame when this node is the shape's bounds node. + virtual MatrixF getBoundsReferenceTransform(F32 time) { return getNodeTransform(time); } + + /// This node's own raw local rotation only (no parent chain, no axis + /// correction, scale zapped out). + virtual MatrixF getOwnRotationOnly(F32 time) { return MatrixF(true); } + virtual bool isEqual(AppNode* node) = 0; virtual bool animatesTransform(const AppSequence* appSeq) = 0;