Files
2026-05-31 14:27:52 -07:00

150 lines
5.9 KiB
C#

using Rukhanka.Toolbox;
using Unity.Entities;
using Unity.Burst;
using Unity.Burst.CompilerServices;
using Unity.Burst.Intrinsics;
using Unity.Collections;
using Unity.Mathematics;
using Unity.Transforms;
using TransformHelpers = Unity.Transforms.TransformHelpers;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka
{
partial class GPUAttachmentsUpdateSystem
{
[BurstCompile]
struct UpdateGPUAttachmentBoneIndexJob: IJobChunk
{
struct ParentBoneInfo
{
public Entity boneEntity;
public Entity rigEntity;
public int boneIndexInRig;
public float4x4 attachmentToBoneTransform;
}
[ReadOnly]
public ComponentLookup<GPURigFrameOffsetsComponent> frameOffsetsLookup;
[ReadOnly]
public ComponentLookup<LocalTransform> localTransformLookup;
[ReadOnly]
public ComponentLookup<PostTransformMatrix> postTransformMatrixLookup;
[ReadOnly]
public ComponentLookup<AnimatorEntityRefComponent> rigBoneRefLookup;
[ReadOnly]
public ComponentLookup<Parent> parentLookup;
[ReadOnly]
public ComponentTypeHandle<GPUAttachmentComponent> gpuAttachmentTypeHandle;
[ReadOnly]
public ComponentTypeHandle<GPURigFrameOffsetsComponent> gpuRigFrameOffsetsTypeHandle;
[ReadOnly]
public ComponentLookup<GPUAnimationEngineTag> gpuEngineTagLookup;
[ReadOnly]
public EntityTypeHandle entityTypeHandle;
public ComponentTypeHandle<GPUAttachmentBoneIndexMPComponent> gpuAttachmentBoneIndexTypeHandle;
public ComponentTypeHandle<GPUAttachmentToBoneTransformMPComponent> gpuAttachmentToBoneTransformTypeHandle;
public ComponentTypeHandle<GPURigEntityLocalToWorldMPComponent> gpuRigEntityLocalToWorldTypeHandle;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
var gpuAttachments = chunk.GetNativeArray(ref gpuAttachmentTypeHandle);
var gpuAttachmentBoneIndices = chunk.GetNativeArray(ref gpuAttachmentBoneIndexTypeHandle);
var gpuAttachmentToBoneTransforms = chunk.GetNativeArray(ref gpuAttachmentToBoneTransformTypeHandle);
var gpuRigEntityLocalToWorlds = chunk.GetNativeArray(ref gpuRigEntityLocalToWorldTypeHandle);
var entities = chunk.GetNativeArray(entityTypeHandle);
var cee = new ChunkEntityEnumerator(useEnabledMask, chunkEnabledMask, chunk.Count);
while (cee.NextEntityIndex(out var i))
{
var gpuAttachment = gpuAttachments[i];
var gpuAttachmentBoneIndex = gpuAttachmentBoneIndices[i];
var gpuAttachmentToBoneTransform = gpuAttachmentToBoneTransforms[i];
var gpuRigEntityToL2W = gpuRigEntityLocalToWorlds[i];
var e = entities[i];
Execute(e, ref gpuAttachmentBoneIndex, ref gpuAttachmentToBoneTransform, ref gpuRigEntityToL2W, gpuAttachment, chunk);
gpuAttachmentBoneIndices[i] = gpuAttachmentBoneIndex;
gpuAttachmentToBoneTransforms[i] = gpuAttachmentToBoneTransform;
gpuRigEntityLocalToWorlds[i] = gpuRigEntityToL2W;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Execute
(
Entity e,
ref GPUAttachmentBoneIndexMPComponent abi,
ref GPUAttachmentToBoneTransformMPComponent atbt,
ref GPURigEntityLocalToWorldMPComponent rltw,
in GPUAttachmentComponent ac,
in ArchetypeChunk chunk
)
{
abi.boneIndex = -1;
var pbi = GetParentRigBoneEntity(e, ac);
if (pbi.boneEntity == Entity.Null)
return;
// Act as ordinary attachment in case of CPU animation engine
if (!AnimationUtils.IsGPUAnimator(pbi.rigEntity, gpuEngineTagLookup))
return;
atbt.value = pbi.attachmentToBoneTransform;
TransformHelpers.ComputeWorldTransformMatrix(pbi.rigEntity, out rltw.value, ref localTransformLookup, ref parentLookup, ref postTransformMatrixLookup);
if (frameOffsetsLookup.TryGetComponent(pbi.rigEntity, out var boneOffset) &&
EntityTools.TryGetChunkComponentData(chunk, pbi.rigEntity, ref gpuRigFrameOffsetsTypeHandle, out var chunkFrameOffsets))
{
boneOffset.AddOffsets(chunkFrameOffsets);
abi.boneIndex = boneOffset.boneIndex + pbi.boneIndexInRig;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ParentBoneInfo GetParentRigBoneEntity(Entity e, GPUAttachmentComponent ac)
{
AnimatorEntityRefComponent rbr = default;
float4x4 entityToBoneTransform = float4x4.identity;
var parent = new Parent() { Value = e};
do
{
if (!localTransformLookup.TryGetComponent(parent.Value, out var plt))
break;
if (rigBoneRefLookup.TryGetComponent(parent.Value, out rbr))
break;
var pltMat = plt.ToMatrix();
if (Hint.Unlikely(postTransformMatrixLookup.TryGetComponent(parent.Value, out var postTransformMatrixComponent)))
{
pltMat = math.mul(pltMat, postTransformMatrixComponent.Value);
}
entityToBoneTransform = math.mul(pltMat, entityToBoneTransform);
}
while (parentLookup.TryGetComponent(parent.Value, out parent));
var rv = new ParentBoneInfo();
if (rbr.animatorEntity != Entity.Null)
{
rv.boneEntity = parent.Value;
rv.rigEntity = rbr.animatorEntity;
rv.boneIndexInRig = math.select(rbr.boneIndexInAnimationRig, ac.attachedBoneIndex, ac.attachedBoneIndex >= 0);
rv.attachmentToBoneTransform = entityToBoneTransform;
}
return rv;
}
}
}
}