Skip to content

Fix BSGeometry virtual overrides and SkinAttach bone fallback#60

Merged
ousnius merged 1 commit into
ousnius:mainfrom
DJLegends1011:fix/starfield-bsgeometry-overrides
May 14, 2026
Merged

Fix BSGeometry virtual overrides and SkinAttach bone fallback#60
ousnius merged 1 commit into
ousnius:mainfrom
DJLegends1011:fix/starfield-bsgeometry-overrides

Conversation

@DJLegends1011
Copy link
Copy Markdown
Contributor

Summary

  • BSGeometry missing virtual overrides: BSGeometry had skinInstanceRef, shaderPropertyRef, and alphaPropertyRef members and read them in Sync(), but never overrode the virtual accessors from NiShape. This caused SkinInstanceRef(), IsSkinned(), HasShaderProperty(), etc. to return null/false for all Starfield BSGeometry shapes — breaking skinning, bone loading, and shader/alpha property access.
  • SkinAttach bone name fallback: GetShapeBoneList now falls back to SkinAttach extra data when boneRefs yield no bone NiNodes. Starfield NIFs store bone names as strings in SkinAttach instead of NiNode block references (all boneRefs are 0xFFFFFFFF).

Context

These two changes are required for Starfield mesh loading in Outfit Studio. Without the virtual overrides, no code path using the NiShape interface (skinning, shaders, alpha) works on BSGeometry shapes. Without the SkinAttach fallback, bone lists are empty for SF meshes.

Test plan

  • Load SF body NIF (naked_f.nif) — 38 bones loaded via SkinAttach
  • Load SF outfit NIFs (swimsuit, Ajun torso, redeemed armor) — all shapes load bones correctly
  • IsSkinned() returns true for skinned BSGeometry shapes
  • SkinInstanceRef() returns valid ref for BSGeometry with BSSkinInstance
  • FO4/SSE NIFs continue to work unchanged (NiGeometry path unaffected)

🤖 Generated with Claude Code

… fallback

BSGeometry had skinInstanceRef, shaderPropertyRef, and alphaPropertyRef members
and read them in Sync(), but never overrode the virtual accessors inherited from
NiShape. This caused SkinInstanceRef(), IsSkinned(), HasShaderProperty(), etc.
to return null/false for all Starfield BSGeometry shapes, breaking skinning,
bone loading, and shader/alpha property access.

GetShapeBoneList now falls back to SkinAttach extra data when boneRefs yield no
bone NiNodes. Starfield NIFs store bone names as strings in SkinAttach instead
of NiNode block references (all boneRefs are 0xFFFFFFFF).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DJLegends1011 added a commit to DJLegends1011/BodySlide-and-Outfit-Studio that referenced this pull request May 11, 2026
Starfield meshes appeared rotated and mispositioned because:

1. BSGeometry was missing virtual overrides for SkinInstanceRef(),
   IsSkinned(), etc. — fixed in nifly (ousnius/nifly#60). Without these,
   the skinned render path was skipped entirely.

2. SF NIFs store bone names in SkinAttach extra data instead of NiNode
   block references. AnimSkin::LoadFromNif now falls back to name-based
   bone lookup via GetShapeBoneList when block IDs yield no NiNodes.

3. SF body NIFs contain no bone NiNodes, so LoadCustomBoneFromNif fails.
   Added fallback to look up bones in the reference skeleton NIF.

4. SF skeleton/skin transforms are in meters, but mesh vertices are
   scaled by havokScale (69.969) during BSGeometryMeshData loading.
   The computed globalToSkin translation is now scaled to match.

Tested on: naked_f.nif, naked_f_swimsuit.nif, Outfit_Ajun_Torso_f.nif,
redeemed_armor.nif (multi-shape). All display upright and centered.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ousnius ousnius requested a review from Copilot May 14, 2026 08:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes two Starfield-specific issues in BSGeometry handling. First, BSGeometry was missing virtual overrides for skin instance, shader, and alpha property accessors (although it stored those refs and serialized them), causing all NiShape-based skinning and shader logic to silently fail. Second, Starfield NIFs store bone names in a SkinAttach extra data block rather than as NiNode references, so GetShapeBoneList needs a fallback to read from there.

Changes:

  • Add IsSkinned/HasSkinInstance/SkinInstanceRef/HasShaderProperty/ShaderPropertyRef/HasAlphaProperty/AlphaPropertyRef overrides on BSGeometry, mirroring the BSTriShape pattern.
  • In NifFile::GetShapeBoneList, fall back to SkinAttach extra data when boneRefs yields no bone NiNodes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
include/Geometry.hpp Adds the missing virtual accessor overrides on BSGeometry for skin instance, shader, and alpha property refs.
src/NifFile.cpp Adds a Starfield SkinAttach extra-data fallback to populate bone name lists when boneRefs contains no resolvable NiNodes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ousnius ousnius merged commit cd405a5 into ousnius:main May 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants