From dc8aa598ed7f6f25eabdb8fb3a15753363217081 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sat, 27 Jun 2026 01:51:07 +0100 Subject: [PATCH] more fix attempts --- Engine/source/ts/assimp/assimpAppMesh.cpp | 32 +------------- Engine/source/ts/assimp/assimpAppMesh.h | 1 - Engine/source/ts/assimp/assimpAppNode.cpp | 43 +------------------ Engine/source/ts/assimp/assimpAppNode.h | 18 ++++++-- Engine/source/ts/assimp/assimpShapeLoader.cpp | 40 +++++++++++------ Engine/source/ts/loader/appNode.h | 8 ---- 6 files changed, 46 insertions(+), 96 deletions(-) diff --git a/Engine/source/ts/assimp/assimpAppMesh.cpp b/Engine/source/ts/assimp/assimpAppMesh.cpp index eaabde89f..0394f1559 100644 --- a/Engine/source/ts/assimp/assimpAppMesh.cpp +++ b/Engine/source/ts/assimp/assimpAppMesh.cpp @@ -79,37 +79,7 @@ const char* AssimpAppMesh::getName(bool allowFixed) MatrixF AssimpAppMesh::getMeshTransform(F32 time) { - MatrixF transform = appNode->getNodeTransform(time); - - // AssimpAppNode::getTransform() deliberately skips axis correction for the - // bounds node itself, since its (uncorrected) transform is used elsewhere - // as the reference frame the rest of the shape gets normalized against - // (see TSShapeLoader::getLocalNodeMatrix). But if this mesh's geometry was - // hand-modeled as part of the source scene (as opposed to the empty, - // auto-generated bounds node added when none exists), it lives in the same - // source up-axis space as every other mesh and needs the same correction - // baked into its locked vertex data - otherwise it ends up sitting in the - // model's original, unrotated space instead of Torque's Z-up space. - if (appNode->isBounds()) - { - MatrixF axisFix = ColladaUtils::getOptions().axisCorrectionMat; - transform.mulL(axisFix); - } - - return transform; -} - -void AssimpAppMesh::computeBounds(Box3F& bounds) -{ - if (appNode->isBounds()) - { - bounds = Box3F::Invalid; - for (S32 iVert = 0; iVert < points.size(); iVert++) - bounds.extend(points[iVert]); - return; - } - - Parent::computeBounds(bounds); + return appNode->getNodeTransform(time); } void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset) diff --git a/Engine/source/ts/assimp/assimpAppMesh.h b/Engine/source/ts/assimp/assimpAppMesh.h index e0e87add3..2215b1140 100644 --- a/Engine/source/ts/assimp/assimpAppMesh.h +++ b/Engine/source/ts/assimp/assimpAppMesh.h @@ -119,7 +119,6 @@ public: /// @return The mesh transform at the specified time MatrixF getMeshTransform(F32 time) override; F32 getVisValue(F32 t) override; - void computeBounds(Box3F& bounds) override; static Vector sMaterialRemap; }; diff --git a/Engine/source/ts/assimp/assimpAppNode.cpp b/Engine/source/ts/assimp/assimpAppNode.cpp index 3cfb66f1e..177b3ee0e 100644 --- a/Engine/source/ts/assimp/assimpAppNode.cpp +++ b/Engine/source/ts/assimp/assimpAppNode.cpp @@ -49,7 +49,7 @@ F32 AssimpAppNode::sTimeMultiplier = 1.0f; AssimpAppNode::AssimpAppNode(const aiScene* scene, const aiNode* node, AssimpAppNode* parentNode) : mScene(scene), - mNode(node ? node : scene->mRootNode), + mNode(node), mInvertMeshes(false), mLastTransformTime(TSShapeLoader::DefaultTime - 1), mDefaultTransformValid(false) @@ -62,7 +62,7 @@ AssimpAppNode::AssimpAppNode(const aiScene* scene, const aiNode* node, AssimpApp const char* defaultName = "null"; mName = dStrdup(defaultName); } - mParentName = dStrdup(parentNode ? parentNode->mName : "ROOT"); + mParentName = dStrdup(parentNode ? parentNode->mName : "DUMMY"); // Convert transformation matrix assimpToTorqueMat(node->mTransformation, mNodeTransform); Con::printf("[ASSIMP] Node Created: %s, Parent: %s", mName, mParentName); @@ -84,14 +84,6 @@ MatrixF AssimpAppNode::getTransform(F32 time) // no parent (ie. root level) => scale by global shape mLastTransform.identity(); mLastTransform.scale(ColladaUtils::getOptions().unit * ColladaUtils::getOptions().formatScaleFactor); - - if (mScene && mScene->mRootNode) - { - MatrixF sceneRootMat(true); - assimpToTorqueMat(mScene->mRootNode->mTransformation, sceneRootMat); - mLastTransform.mulL(sceneRootMat); - } - if (!isBounds()) { MatrixF axisFix = ColladaUtils::getOptions().axisCorrectionMat; @@ -279,37 +271,6 @@ 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 1d61c6b02..c6bacb79b 100644 --- a/Engine/source/ts/assimp/assimpAppNode.h +++ b/Engine/source/ts/assimp/assimpAppNode.h @@ -122,10 +122,22 @@ 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); } + bool isParentRoot() override + { + if (!appParent) + return false; // the scene root itself has no parent — not a content root + + // True when this node's immediate parent is the scene root node. + // mParentName is stored at construction from the AppNode's normalised name + // (empty names become "null"), so apply the same normalisation to the raw + // aiScene root name before comparing. + const char* rootName = mScene->mRootNode->mName.C_Str(); + if (dStrlen(rootName) == 0) + rootName = "null"; + + return dStrcmp(mParentName, rootName) == 0; + } static void assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat); static aiNode* findChildNodeByName(const char* nodeName, aiNode* rootNode); diff --git a/Engine/source/ts/assimp/assimpShapeLoader.cpp b/Engine/source/ts/assimp/assimpShapeLoader.cpp index a48b55631..50f5d3a12 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.cpp +++ b/Engine/source/ts/assimp/assimpShapeLoader.cpp @@ -299,24 +299,40 @@ void AssimpShapeLoader::enumerateScene() // Setup LOD checks detectDetails(); - aiNode* root = mScene->mRootNode; - for (S32 iNode = 0; iNode < root->mNumChildren; iNode++) + // Process mRootNode as an AppNode directly. + // + // Making it the single parentless node means the !appParent branch in + // AssimpAppNode::getTransform() fires exactly once — for this node only. + // Scale + axisCorrectionMat are therefore applied in exactly one place. + // Every child (bones, mesh nodes, bounds) inherits the correction naturally + // through the parent chain; no per-node special-casing is needed. + AssimpAppNode* sceneRootAppNode = new AssimpAppNode(mScene, mScene->mRootNode, nullptr); + if (!processNode(sceneRootAppNode)) { - aiNode* child = root->mChildren[iNode]; - AssimpAppNode* node = new AssimpAppNode(mScene, child); - if (!processNode(node)) { - delete node; - } + Con::errorf("[ASSIMP] Failed to process scene root node '%s'.", + mScene->mRootNode->mName.C_Str()); + delete sceneRootAppNode; + sceneRootAppNode = nullptr; } - if (!boundsNode) { - aiNode* reqNode = new aiNode("bounds"); - reqNode->mTransformation = aiMatrix4x4(); - AssimpAppNode* appBoundsNode = new AssimpAppNode(mScene, reqNode); - if (!processNode(appBoundsNode)) { + // Bounds check — every Torque shape needs a bounds node. + // If the source file didn't include one, synthesise it + if (!boundsNode) + { + Con::printf("[ASSIMP] No 'bounds' node found - adding synthetic bounds node."); + aiNode* boundsAiNode = new aiNode("bounds"); + boundsAiNode->mTransformation = aiMatrix4x4(); // identity + AssimpAppNode* appBoundsNode = new AssimpAppNode(mScene, boundsAiNode, nullptr); + if (!processNode(appBoundsNode)) + { + Con::errorf("[ASSIMP] Failed to add synthetic bounds node."); delete appBoundsNode; } } + else + { + Con::printf("[ASSIMP] Bounds node found in scene."); + } // Process animations if available processAnimations(); diff --git a/Engine/source/ts/loader/appNode.h b/Engine/source/ts/loader/appNode.h index 2b6f14cab..65ef92e40 100644 --- a/Engine/source/ts/loader/appNode.h +++ b/Engine/source/ts/loader/appNode.h @@ -65,14 +65,6 @@ 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;