Skip to content

Sync up to latest in original repo#16

Draft
SteveTownsend wants to merge 106 commits into
SteveTownsend:mainfrom
ousnius:main
Draft

Sync up to latest in original repo#16
SteveTownsend wants to merge 106 commits into
SteveTownsend:mainfrom
ousnius:main

Conversation

@SteveTownsend

Copy link
Copy Markdown
Owner

Get up to date before working on new Synthesis patcher requiring NIF introspection

ousnius and others added 30 commits April 11, 2022 10:19
Add tests for version 132 and 139, too.
This was to make it build with gcc 11.
And add a test for loading/saving NiSkinData w/o vertex weights (false).
…e symmetrical functions (#39)

Equality operations should be symmetrical hence 

x == y <=> y == x 

therefore both inputs need the same type and therefore need to be const
Credits to @hexabits for decoding work.
- New blocks: BSGeometry, SkinAttach, BoneTranslations, BSWeakReferenceNode
- All NIF changes are handled
- Support for *.mesh or  *.morph files not included
Basic skinned file with external mesh and material. Test is for the NIF part of the model only.
* Early IO of external mesh data from SF, writing untested (#41)
* Scale mesh data by a factor to bring them similar in scale to previous games (69.969)

---------

Co-authored-by: Cali Ente <ochocaliente@gmail.com>
ousnius and others added 29 commits April 3, 2026 14:51
macos-latest runs on arm64 which doesn't work with half.hpp.
- Fix SyncUDEC3 write: use |= instead of &= for packing, add W bit (1 << 30)
- Add count sync before write in BSGeometryMeshData::Sync
- Fix vertex pack to use int16_t + std::round for correct precision
- Fix SaveExternalShapeData: use Mode::Writing and meshData.Sync
- Add BSGeometry finalization in FinalizeData() to update triSize/numVerts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BSGeometry flag 512 (0x200) controls whether mesh data is embedded
inline in the NIF or stored as external .mesh files. This adds
read/write support for both modes and exposes HasInternalGeomData()
and SetInternalGeomData() API for toggling the flag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cast ~0x200 to uint32_t to avoid GCC -Werror=sign-conversion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FinalizeData was overwriting triSize and numVerts from meshData even
when external mesh data hadn't been loaded, zeroing the header values.
Only update counts when mesh data is actually populated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove upper bound on IsSF() stream version check. Starfield patches
(MeshesPatch.ba2) ship NIFs with stream version 175 which use the
same format as 172/173.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per ousnius's feedback — keep a bounded range (172–175) so unknown
future stream versions don't silently pass validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set numVertices differently depending on stream mode: when reading, cast nVertices to uint16_t as before; when writing, clamp nVertices to 0xFFFF using std::min before casting. This ensures we don't write a numVertices larger than a 16-bit limit while preserving the original value when reading.
Add support for the 2-bit W component of UDEC3 tangents: introduce SyncUDEC3 to pack/unpack tangent W bits and switch packing to std::round for consistent rounding.

Store per-tangent W values in Geometry (tangentWs) and update BSGeometryMeshData::Sync to read/write tangent W components.

Add tests that load/save external .mesh data and convert external meshes to internal geometry.
Change variable 'di' from int to size_t to match other size/index types (e.g. map.size() and vector indexing). This fixes signed/unsigned mismatches and avoids related compiler warnings when tracking deleted triangle indices.
Fix Starfield BSGeometry mesh data export
… 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>
…errides

Fix BSGeometry virtual overrides and SkinAttach bone fallback
GetShapeBoneWeights had no path for BSGeometry shapes. Starfield
meshes store per-vertex bone weights in BSGeometryMeshData::skinWeights
as packed uint16 values (65535 = 1.0). Add a BSGeometry case that reads
these weights, bridging the gap that caused all SF mesh vertices to
appear unweighted in Outfit Studio.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete a stray '#pragma once' from the NifUtil.cpp implementation file. Pragma once is intended for headers as an include guard; removing it avoids misuse and potential confusion since the corresponding header (NifUtil.hpp) provides the proper declaration.
Address Copilot review notes on the BSGeometry GetShapeBoneWeights path:
- The vertex loop counter was uint16_t while skinWeights.size() is 32-bit,
  causing an infinite loop on meshes with more than 65535 vertices. Iterate
  with a size_t index capped at the uint16_t-keyed output map's range.
- Add a Starfield regression test that loads the external mesh data and
  verifies GetShapeBoneWeights returns normalized weights in [0, 1].

https://claude.ai/code/session_01M73z1PscSn8M97dpyPYUW5
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
In tests/TestNifFile.cpp (BSGeometry bone weights test) replace structured bindings that returned full file tuples with std::get<0>() to only retrieve the input path (fileInput / meshFileInput). Add REQUIRE checks to ensure external mesh path lists and mesh path strings are not empty before attempting to open streams. These changes remove unused tuple elements and add safer assertions to avoid opening invalid paths during the test.
Replace hardcoded magic values (0x10000 and 65535) with constexpr derived from std::numeric_limits<uint16_t>::max(). Cap vertCount via std::min to avoid overflow on meshes with >65535 vertices and normalize bone weights by a named maxWeightValue. Improves clarity and avoids magic numbers.
…errides

Add BSGeometry bone weight loading from mesh data
Upgrade testing to Catch2 v3.15.0 and update CI/build scripts accordingly.
@SteveTownsend SteveTownsend marked this pull request as draft June 11, 2026 22:12
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.

9 participants