MeshUnit_CS_Lf
MeshUnit_CS_Lf
#include "/Engine/Public/Platform.ush"
#include "/Engine/Private/ComputeShaderUtils.ush"
uint NumMeshesPerThread;
uint NumFirstGPUBones;
uint NumCPUBones;
uint NumMeshesPerFrame;
uint AnimTextureSizeX;
uint AnimTextureSizeY;
uint OutputTextureSizeX;
uint OutputTextureSizeY;
uint NumLevelOfDetails;
uint NumDebugBuffer;
uint NumPixelBuffer;
uint NumCustomStates;
//uint NumCustomDataPixels;
StructuredBuffer<float4> ReferencePose_StructuredBuffer;
StructuredBuffer<float4> ReferencePoseIndices_StructuredBuffer;
StructuredBuffer<float4> BoneSpaceAnimationInput_StructuredBuffer;
StructuredBuffer<min16int> BoneSpaceAnimationDataInput_StructuredBuffer;
StructuredBuffer<int> BoneSpaceAnimationDataStartIndex_StructuredBuffer;
StructuredBuffer<min16int> BoneSpaceAnimationDataEndIndex_StructuredBuffer; //
Start Index + End Index = Real End Index
StructuredBuffer<int> PerMeshCustomDataIndices_StructuredBuffer;
StructuredBuffer<min16int> PerMeshCustomDataLod_StructuredBuffer;
StructuredBuffer<min16uint> PerMeshCustomDataCollectionIndex_StructuredBuffer;
StructuredBuffer<min16uint> ReferenceNumCPUBones_StructuredBuffer;
StructuredBuffer<int> AnimationStartIndex_StructuredBuffer;
StructuredBuffer<min16int> AnimationEndIndex_StructuredBuffer; // Start Index + End
Index = Real End Index
StructuredBuffer<min16int> AnimationWeight_StructuredBuffer;
StructuredBuffer<int> AnimationFramePose0_StructuredBuffer;
StructuredBuffer<min16uint> AnimationLayerIndex_StructuredBuffer;
StructuredBuffer<float4> AnimationLibrary_StructuredBuffer;
StructuredBuffer<min16uint> AnimationLayerLibrary_StructuredBuffer;
Texture2DArray<float4> R_AnimationLibrary_InputTexture;
Texture2DArray<float4> R_BoneTransform_OutputTexture;
RWTexture2DArray<float4> RW_BoneTransform_OutputTexture;
RWTexture2DArray<float4> RW_BoneTransformPrevious_OutputTexture;
RWStructuredBuffer<float> DebugValue;
// https://github.com/juj/MathGeoLib/blob/master/src/Math/float3x4.cpp
float3x4 MatrixMultiply_3x4(in float3x4 Lhs, in float3x4 Rhs)
{
float3x4 Result;
return Result;
}
Q.x *= scale;
Q.y *= scale;
Q.z *= scale;
Q.w *= scale;
}
else
{
Q = float4(0.0f, 0.0f, 0.0f, 1.0f); // Set to identity Q
}
return Q;
}
Q = Normalize_Quaternion(Q);
//return q;
}
struct FMatrix_Lf
{
float3 Translation;
float3 Scale;
float4 Rotation;
float3x4 M;
M[0][3] = T.x;
M[1][3] = T.y;
M[2][3] = T.z;
}
M[0][0] = S.x;
M[1][1] = S.y;
M[2][2] = S.z;
}
// See e.g.
http://www.geometrictools.com/Documentation/LinearAlgebraicQuaternions.pdf .
float x = Q.x;
float y = Q.y;
float z = Q.z;
float w = Q.w;
M[1][0] = Other[1][0];
M[1][1] = Other[1][1];
M[1][2] = Other[1][2];
M[2][0] = Other[2][0];
M[2][1] = Other[2][1];
M[2][2] = Other[2][2];
}
GetTranslation_3x4(Translation, FromMatrix);
SetTranslation(Translation);
GetRotation_3x4(Rotation, FromMatrix);
SetRotationMatrix(FromMatrix);
//SetRotation(Rotation);
}
};
float3x4 GetIdentity_Matrix_3x4()
{
return float3x4(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0);
}
FMatrix_Lf GetIdentity_Matrix()
{
FMatrix_Lf M;
M.Translation = float3(0, 0, 0);
M.Scale = float3(1, 1, 1);
M.Rotation = float4(0, 0, 0, 1);
M.M = GetIdentity_Matrix_3x4();
return M;
}
return Result;
}
// Blend rotation
return A + sign * B;
}
float4 result;
return result;
}
return Color;
}
DebugValue[ErrorIndex] = Index;
return 0;
}
if (NumKeys < 2)
{
PosIndex0Out = 0;
PosIndex1Out = 0;
return 0.0f;
}
float LayerWeight =
(float)AnimationLayerLibrary_StructuredBuffer[LayerLibraryIndex] / (float)0x7FFF;
if (!Scalar)
{
continue;
}
float4 C0 = R_AnimationLibrary_InputTexture[GetDimensionsFromIndex3D(
LibraryIndexCurrent, AnimTextureSizeX, AnimTextureSizeY)];
float4 C1 = R_AnimationLibrary_InputTexture[GetDimensionsFromIndex3D(
LibraryIndexCurrent + 1, AnimTextureSizeX, AnimTextureSizeY)];
float4 C2 = R_AnimationLibrary_InputTexture[GetDimensionsFromIndex3D(
LibraryIndexCurrent + 2, AnimTextureSizeX, AnimTextureSizeY)];
float3x4 RuntimeBoneMatrixCurrent = float3x4(C0, C1, C2);
if (!bFoundFirstAnimation)
{
bFoundFirstAnimation = true;
OutAtom.SetScale(Scale3_Float(Atom.Scale, Scalar));
OutAtom.SetTranslation(Scale3_Float(Atom.Translation, Scalar));
// float RotationW = Scalar;
// FullRotationWeight += RotationW;
// if (FullRotationWeight > 1)
// {
// RotationW -= abs(1.0f - FullRotationWeight);
// }
OutAtom.SetRotation(Atom.Rotation * clamp(Scalar, 0.0f, 1.0f));
}
else
{
OutAtom.SetScale(OutAtom.Scale + Scale3_Float(Atom.Scale,
Scalar));
OutAtom.SetTranslation(OutAtom.Translation +
Scale3_Float(Atom.Translation, Scalar));
// float RotationW = Scalar;
// FullRotationWeight += RotationW;
// if (FullRotationWeight > 1)
// {
// RotationW -= abs(1.0f - FullRotationWeight);
// }
OutAtom.SetRotation(
Normalize_Quaternion(
Scale_Quaternion(OutAtom.Rotation, Atom.Rotation,
clamp(Scalar, 0.0f, 1.0f))));
}
// FullLayerWeight += LayerWeight;
// if (FullLayerWeight >= 0.995f)
// {
// return OutAtom.M;
// }
}
OutAtom.SetRotation(Normalize_Quaternion(OutAtom.Rotation));
return OutAtom.M;
}
NumCustomStates,
NumPixelBuffer);
RW_BoneTransformPrevious_OutputTexture[uint3(1, 0, 0)] = float4(0,
0,
OutputTextureSizeX,
OutputTextureSizeY);
uint CPUMeshIndex =
PerMeshCustomDataIndices_StructuredBuffer[LocalMeshData];
int IKDataIndexStart =
BoneSpaceAnimationDataStartIndex_StructuredBuffer[LocalMeshData];
int IKDataIndexEnd = IKDataIndexStart +
BoneSpaceAnimationDataEndIndex_StructuredBuffer[LocalMeshData];
int AnimStartIndex =
AnimationStartIndex_StructuredBuffer[LocalMeshData];
int AnimEndIndex = AnimStartIndex +
AnimationEndIndex_StructuredBuffer[LocalMeshData];
uint ReferenceIndex =
PerMeshCustomDataCollectionIndex_StructuredBuffer[LocalMeshData];
// x -> CPU
// y -> GPU
// z -> Parent
// w -> Reserved
float4 ReferenceIndices =
ReferencePoseIndices_StructuredBuffer[B];
// Is not part of this Rig and the last bone pass already
if (ReferenceIndices.x < -0.5f)
{
break;
}
// Handle IK
if (RuntimeIndexGPU > -1)
{
bool bIsBoneSolvedByIK = false;
for (int IKIdx = IKDataIndexStart; IKIdx <
IKDataIndexEnd; ++IKIdx)
{
if
(BoneSpaceAnimationDataInput_StructuredBuffer[IKIdx] == RuntimeIndexGPU)
{
int IKBoneIndex = IKIdx * 3;
float3x4 IKBoneMatrix = float3x4(
BoneSpaceAnimationInput_StructuredBuffer[IKBoneIndex],
BoneSpaceAnimationInput_StructuredBuffer[IKBoneIndex + 1],
BoneSpaceAnimationInput_StructuredBuffer[IKBoneIndex + 2]
);
BoneMatrix =
MatrixMultiply_3x4(IKBoneMatrix, BoneMatrix);
bIsBoneSolvedByIK = true;
break;
}
}
if (bIsBoneSolvedByIK)
{
break;
}
}
BoneMatrix = MatrixMultiply_3x4(
BendBoneFromAnimations_Full(RuntimeIndexCPU,
AnimStartIndex, AnimEndIndex),
BoneMatrix);
RuntimeIndexCPU =
(int)ReferencePoseIndices_StructuredBuffer[BonePoseIndex].z;
// When ReferencePoseParentIndices_StructuredBuffer is
uninitialized we may never exit the loop.
// That's why we count down to the max amount of data as
fallback.
FallbackAnimationIndex--;
}
ReferencePose_StructuredBuffer[CPUBoneIndexBase + 1],
ReferencePose_StructuredBuffer[CPUBoneIndexBase + 2]);
RW_BoneTransformPrevious_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase,
OutputTextureSizeX,
OutputTextureSizeY)] =
R_BoneTransform_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase,
OutputTextureSizeX,
OutputTextureSizeY)];
RW_BoneTransformPrevious_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase +
1, OutputTextureSizeX,
OutputTextureSizeY)] =
R_BoneTransform_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase + 1,
OutputTextureSizeX,
OutputTextureSizeY)];
RW_BoneTransformPrevious_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase +
2, OutputTextureSizeX,
OutputTextureSizeY)] =
R_BoneTransform_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase + 2,
OutputTextureSizeX,
OutputTextureSizeY)];
RW_BoneTransform_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase,
OutputTextureSizeX,
OutputTextureSizeY)] = BoneMatrix[0];
RW_BoneTransform_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase + 1,
OutputTextureSizeX,
OutputTextureSizeY)] = BoneMatrix[1];
RW_BoneTransform_OutputTexture[GetDimensionsFromIndex3D(GPUBoneIndexBase + 2,
OutputTextureSizeX,
OutputTextureSizeY)] = BoneMatrix[2];
}
}
}