fix(nif): leave out a root node's rotation and translation

The client's render component sets the object's own position and
rotation on the root node it loads, over the stored ones, so a root's
turn never shows in game (its scale stays). NifFile now reads roots the
same way. LU Toolbox's .nif (root turned 90 degrees about X, the
NiLODNodes turned back) now stands up in icons and the dashboard's
views; every game .nif has an unturned root and reads as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 17:54:07 -05:00
parent 6208724e6a
commit 602acc0fe7
3 changed files with 92 additions and 11 deletions

View File

@@ -387,7 +387,14 @@ namespace {
reader.Skip(static_cast<uint64_t>(effectCount) * 4);
if (!reader.Ok()) return;
const auto world = parent.Then(av.transform);
// The client puts the object's own position and rotation in place of the root node's (the render component
// sets them on the loaded root), so a root's stored rotation and translation are never seen; its scale is kept
auto local = av.transform;
if (depth == 0) {
local.r = Transform{}.r;
local.t = {};
}
const auto world = parent.Then(local);
// Recorded even when hidden: attach points often are
if (!av.name.empty() && !m_Model.nodes.contains(av.name)) {
NifFile::NodeTransform node;

View File

@@ -13,7 +13,8 @@
* the NifTools project's format description (nif.xml). Pure (bytes in, meshes out) so it can be unit tested.
*
* The client's files are versions 20.2.0.8 and 20.3.0.9 with user version 0. What is drawn: the scene graph
* (NiNode, NiLODNode, NiBillboardNode and other nodes) with its transforms baked into the vertices, NiTriShape and
* (NiNode, NiLODNode, NiBillboardNode and other nodes) with its transforms baked into the vertices (except a root
* node's rotation and translation, which the client replaces with the object's own), NiTriShape and
* NiTriStrips geometry (positions, normals, the first UV set, vertex colors), and the properties Gamebryo passes down
* the tree: NiMaterialProperty, NiAlphaProperty, NiTexturingProperty's base texture (an external NiSourceTexture),
* NiVertexColorProperty and NiStencilProperty's draw mode (double sided), and how fast NiTextureTransformControllers move