more fix attempts

This commit is contained in:
marauder2k7 2026-06-27 01:51:07 +01:00
parent 07d0eeed77
commit dc8aa598ed
6 changed files with 46 additions and 96 deletions

View file

@ -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)

View file

@ -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<S32> sMaterialRemap;
};

View file

@ -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 <unit>
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,

View file

@ -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);

View file

@ -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();

View file

@ -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;