@@ -430,7 +430,9 @@ float3x4 GetPrevBoneMatrix(int index)
|
|||||||
float3 SkinPrevPosition(ModelInput_Skinned input)
|
float3 SkinPrevPosition(ModelInput_Skinned input)
|
||||||
{
|
{
|
||||||
float4 position = float4(input.Position.xyz, 1);
|
float4 position = float4(input.Position.xyz, 1);
|
||||||
float3x4 boneMatrix = input.BlendWeights.x * GetPrevBoneMatrix(input.BlendIndices.x);
|
float weightsSum = input.BlendWeights.x + input.BlendWeights.y + input.BlendWeights.z + input.BlendWeights.w;
|
||||||
|
float mainWeight = input.BlendWeights.x + (1.0f - weightsSum); // Re-normalize to account for 16-bit weights encoding erros
|
||||||
|
float3x4 boneMatrix = mainWeight * GetPrevBoneMatrix(input.BlendIndices.x);
|
||||||
boneMatrix += input.BlendWeights.y * GetPrevBoneMatrix(input.BlendIndices.y);
|
boneMatrix += input.BlendWeights.y * GetPrevBoneMatrix(input.BlendIndices.y);
|
||||||
boneMatrix += input.BlendWeights.z * GetPrevBoneMatrix(input.BlendIndices.z);
|
boneMatrix += input.BlendWeights.z * GetPrevBoneMatrix(input.BlendIndices.z);
|
||||||
boneMatrix += input.BlendWeights.w * GetPrevBoneMatrix(input.BlendIndices.w);
|
boneMatrix += input.BlendWeights.w * GetPrevBoneMatrix(input.BlendIndices.w);
|
||||||
@@ -439,12 +441,6 @@ float3 SkinPrevPosition(ModelInput_Skinned input)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Cached skinning data to avoid multiple calculation
|
|
||||||
struct SkinningData
|
|
||||||
{
|
|
||||||
float3x4 BlendMatrix;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculates the transposed transform matrix for the given bone index
|
// Calculates the transposed transform matrix for the given bone index
|
||||||
float3x4 GetBoneMatrix(int index)
|
float3x4 GetBoneMatrix(int index)
|
||||||
{
|
{
|
||||||
@@ -457,7 +453,9 @@ float3x4 GetBoneMatrix(int index)
|
|||||||
// Calculates the transposed transform matrix for the given vertex (uses blending)
|
// Calculates the transposed transform matrix for the given vertex (uses blending)
|
||||||
float3x4 GetBoneMatrix(ModelInput_Skinned input)
|
float3x4 GetBoneMatrix(ModelInput_Skinned input)
|
||||||
{
|
{
|
||||||
float3x4 boneMatrix = input.BlendWeights.x * GetBoneMatrix(input.BlendIndices.x);
|
float weightsSum = input.BlendWeights.x + input.BlendWeights.y + input.BlendWeights.z + input.BlendWeights.w;
|
||||||
|
float mainWeight = input.BlendWeights.x + (1.0f - weightsSum); // Re-normalize to account for 16-bit weights encoding erros
|
||||||
|
float3x4 boneMatrix = mainWeight * GetBoneMatrix(input.BlendIndices.x);
|
||||||
boneMatrix += input.BlendWeights.y * GetBoneMatrix(input.BlendIndices.y);
|
boneMatrix += input.BlendWeights.y * GetBoneMatrix(input.BlendIndices.y);
|
||||||
boneMatrix += input.BlendWeights.z * GetBoneMatrix(input.BlendIndices.z);
|
boneMatrix += input.BlendWeights.z * GetBoneMatrix(input.BlendIndices.z);
|
||||||
boneMatrix += input.BlendWeights.w * GetBoneMatrix(input.BlendIndices.w);
|
boneMatrix += input.BlendWeights.w * GetBoneMatrix(input.BlendIndices.w);
|
||||||
@@ -465,13 +463,13 @@ float3x4 GetBoneMatrix(ModelInput_Skinned input)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transforms the vertex position by weighted sum of the skinning matrices
|
// Transforms the vertex position by weighted sum of the skinning matrices
|
||||||
float3 SkinPosition(ModelInput_Skinned input, SkinningData data)
|
float3 SkinPosition(ModelInput_Skinned input, float3x4 boneMatrix)
|
||||||
{
|
{
|
||||||
return mul(data.BlendMatrix, float4(input.Position.xyz, 1));
|
return mul(boneMatrix, float4(input.Position.xyz, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transforms the vertex position by weighted sum of the skinning matrices
|
// Transforms the vertex position by weighted sum of the skinning matrices
|
||||||
float3x3 SkinTangents(ModelInput_Skinned input, SkinningData data)
|
float3x3 SkinTangents(ModelInput_Skinned input, float3x4 boneMatrix)
|
||||||
{
|
{
|
||||||
// Unpack vertex tangent frame
|
// Unpack vertex tangent frame
|
||||||
float bitangentSign = input.Tangent.w ? -1.0f : +1.0f;
|
float bitangentSign = input.Tangent.w ? -1.0f : +1.0f;
|
||||||
@@ -479,10 +477,10 @@ float3x3 SkinTangents(ModelInput_Skinned input, SkinningData data)
|
|||||||
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
float3 tangent = input.Tangent.xyz * 2.0 - 1.0;
|
||||||
|
|
||||||
// Apply skinning
|
// Apply skinning
|
||||||
tangent = mul(data.BlendMatrix, float4(tangent, 0));
|
tangent = normalize(mul(boneMatrix, float4(tangent, 0)));
|
||||||
normal = mul(data.BlendMatrix, float4(normal, 0));
|
normal = normalize(mul(boneMatrix, float4(normal, 0)));
|
||||||
|
|
||||||
float3 bitangent = cross(normal, tangent) * bitangentSign;
|
float3 bitangent = normalize(cross(normal, tangent) * bitangentSign);
|
||||||
return float3x3(tangent, bitangent, normal);
|
return float3x3(tangent, bitangent, normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,10 +499,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
|
|||||||
VertexOutput output;
|
VertexOutput output;
|
||||||
|
|
||||||
// Perform skinning
|
// Perform skinning
|
||||||
SkinningData data;
|
float3x4 boneMatrix = GetBoneMatrix(input);
|
||||||
data.BlendMatrix = GetBoneMatrix(input);
|
float3 position = SkinPosition(input, boneMatrix);
|
||||||
float3 position = SkinPosition(input, data);
|
float3x3 tangentToLocal = SkinTangents(input, boneMatrix);
|
||||||
float3x3 tangentToLocal = SkinTangents(input, data);
|
|
||||||
|
|
||||||
// Compute world space vertex position
|
// Compute world space vertex position
|
||||||
CalculateInstanceTransform(input);
|
CalculateInstanceTransform(input);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Current materials shader version.
|
/// Current materials shader version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#define MATERIAL_GRAPH_VERSION 161
|
#define MATERIAL_GRAPH_VERSION 162
|
||||||
|
|
||||||
class Material;
|
class Material;
|
||||||
class GPUShader;
|
class GPUShader;
|
||||||
|
|||||||
@@ -563,9 +563,10 @@ void MeshData::NormalizeBlendWeights()
|
|||||||
ASSERT(Positions.Count() == BlendWeights.Count());
|
ASSERT(Positions.Count() == BlendWeights.Count());
|
||||||
for (int32 i = 0; i < Positions.Count(); i++)
|
for (int32 i = 0; i < Positions.Count(); i++)
|
||||||
{
|
{
|
||||||
const float sum = BlendWeights[i].SumValues();
|
Float4& weights = BlendWeights.Get()[i];
|
||||||
|
const float sum = weights.SumValues();
|
||||||
const float invSum = sum > ZeroTolerance ? 1.0f / sum : 0.0f;
|
const float invSum = sum > ZeroTolerance ? 1.0f / sum : 0.0f;
|
||||||
BlendWeights[i] *= invSum;
|
weights *= invSum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ void AnimatedModel::PreInitSkinningData()
|
|||||||
for (int32 boneIndex = 0; boneIndex < bonesCount; boneIndex++)
|
for (int32 boneIndex = 0; boneIndex < bonesCount; boneIndex++)
|
||||||
{
|
{
|
||||||
auto& bone = skeleton.Bones[boneIndex];
|
auto& bone = skeleton.Bones[boneIndex];
|
||||||
identityMatrices[boneIndex] = bone.OffsetMatrix * GraphInstance.NodesPose[bone.NodeIndex];
|
identityMatrices.Get()[boneIndex] = bone.OffsetMatrix * GraphInstance.NodesPose[bone.NodeIndex];
|
||||||
}
|
}
|
||||||
_skinningData.SetData(identityMatrices.Get(), true);
|
_skinningData.SetData(identityMatrices.Get(), true);
|
||||||
|
|
||||||
|
|||||||
@@ -720,23 +720,23 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
|
|||||||
{
|
{
|
||||||
int vtxIndex = clusterIndices[j] - firstVertexOffset;
|
int vtxIndex = clusterIndices[j] - firstVertexOffset;
|
||||||
float vtxWeight = (float)clusterWeights[j];
|
float vtxWeight = (float)clusterWeights[j];
|
||||||
|
|
||||||
if (vtxWeight <= 0 || vtxIndex < 0 || vtxIndex >= vertexCount)
|
if (vtxWeight <= 0 || vtxIndex < 0 || vtxIndex >= vertexCount)
|
||||||
continue;
|
continue;
|
||||||
|
Int4& indices = mesh.BlendIndices.Get()[vtxIndex];
|
||||||
auto& indices = mesh.BlendIndices[vtxIndex];
|
Float4& weights = mesh.BlendWeights.Get()[vtxIndex];
|
||||||
auto& weights = mesh.BlendWeights[vtxIndex];
|
|
||||||
|
|
||||||
for (int32 k = 0; k < 4; k++)
|
for (int32 k = 0; k < 4; k++)
|
||||||
{
|
{
|
||||||
if (vtxWeight >= weights.Raw[k])
|
if (vtxWeight >= weights.Raw[k])
|
||||||
{
|
{
|
||||||
|
// Move lower weights by one down
|
||||||
for (int32 l = 2; l >= k; l--)
|
for (int32 l = 2; l >= k; l--)
|
||||||
{
|
{
|
||||||
indices.Raw[l + 1] = indices.Raw[l];
|
indices.Raw[l + 1] = indices.Raw[l];
|
||||||
weights.Raw[l + 1] = weights.Raw[l];
|
weights.Raw[l + 1] = weights.Raw[l];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set bone influence
|
||||||
indices.Raw[k] = boneIndex;
|
indices.Raw[k] = boneIndex;
|
||||||
weights.Raw[k] = vtxWeight;
|
weights.Raw[k] = vtxWeight;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user