ConfettiFX / The-Forge

The Forge Cross-Platform Rendering Framework PC Windows, Steamdeck (native), Ray Tracing, macOS / iOS, Android, XBOX, PS4, PS5, Switch, Quest 2
Apache License 2.0
4.65k stars 491 forks source link

All Animation Examples (21 - 29) have a bone calculation / rendering bug #244

Closed swan-gh closed 2 years ago

swan-gh commented 2 years ago

Hello,

I've had no issues with the other examples but I noticed that all the tutorials using ozz seem to not render any skeleton, bones or joints. I've definitely ticked the boxes to enable this. I was curious what was going on so I had a poke around with RenderDoc + Visual Studio. It seems that Rig::mJointModelMats is allocated but not initialised to any values (which meant the uninitialised values were around e^38). Then in Rig::Pose(), these massive values are used to calculate new values for Rig::mJointWorldMats:

mJointWorldMats[jointIndex] = rootTransform * mJointModelMats[jointIndex];

leading to erratic values and NaNs. In RenderDoc I was able to see that the values for Get(toWorld)[InstanceID] were erratic,

Here's some more info about my setup: Windows 10 Windows SDK 10.0.19041.0 Visual Studio 2019 (v142) MSVC 19.29.30137 for x64

Occurs across all 3 rendering APIs: Vulkan, DX11, DX12. Compiling 22_Blending as both Debug x64 and Release x64.

swan-gh commented 2 years ago

image

wolfgangfengel commented 2 years ago

Good catch! We are going to look into this and fix it.

wolfgangfengel commented 2 years ago

Two ideas: you use Visual Studio 2019. We don't support Visual Studio 2019, only 2017. We can not keep track of all compiler bugs in various Visual Studio versions so we settle on supporting only one. Second idea: maybe an asset problem. It seems to work for us.

wolfgangfengel commented 2 years ago

Let me know if using Visual Studio 2017 is fixing it ...

swan-gh commented 2 years ago

Using the 2017 toolset (v141) works for me as well, just tested it. Looks like this is a bug when compiling with v142, I'll close this for now 👍

swan-gh commented 2 years ago

I've investigated this further out of my own curiosity - looks like MSVC with the v142 toolchain might have introduced a compiler bug. The defective code is in ozz so I'll see if I can open an issue with them and merge a fix.

Seems to be a side effect of defining constants in an enum and using them to set bitfield sizes:

//skeleton.h
enum Constants {
    ...
    kMaxJointsNumBits = 10,
    ...
    kMaxJoints = (1 << kMaxJointsNumBits) - 1,
    ...
    kMaxSoAJoints = (kMaxJoints + 3) / 4,
    ...
    kNoParentIndex = kMaxJoints,
};
...
// Per joint properties.
struct JointProperties {
    // Parent's index, kNoParentIndex for the root.
    uint16_t parent : Skeleton::kMaxJointsNumBits;

    // Set to 1 for a leaf, 0 for a branch.
    uint16_t is_leaf : 1;
};

In MSVC v142 when parent is assigned a value of kMaxJoints (1023) on line 70 of skeleton.cc, the code generated by the compiler goes a bit haywire and ends up assigning a value of 1. In MSVC v141 it works as expected and assigns the proper value.

A local fix is to just replace the enums with static or inline constants, and it compiles as expected on v142. Hope this helps for when you guys make the move to 2019!

wolfgangfengel commented 2 years ago

Thank you!