GpuEcsAnimatorSystem.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. using GpuEcsAnimationBaker.Engine.Data;
  2. using Unity.Burst;
  3. using Unity.Collections;
  4. using Unity.Entities;
  5. using Unity.Mathematics;
  6. using UnityEngine;
  7. namespace GPUECSAnimationBaker.Engine.AnimatorSystem
  8. {
  9. [BurstCompile]
  10. public partial struct GpuEcsAnimatorSystem : ISystem
  11. {
  12. [BurstCompile]
  13. public void OnUpdate(ref SystemState state)
  14. {
  15. EndSimulationEntityCommandBufferSystem.Singleton ecbSystem =
  16. SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();
  17. EntityCommandBuffer.ParallelWriter ecb = ecbSystem.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter();
  18. float deltaTime = SystemAPI.Time.DeltaTime;
  19. state.Dependency = new GpuEcsAnimatorJob()
  20. {
  21. ecb = ecb,
  22. deltaTime = deltaTime
  23. }.ScheduleParallel(state.Dependency);
  24. }
  25. [BurstCompile]
  26. private partial struct GpuEcsAnimatorJob : IJobEntity
  27. {
  28. public EntityCommandBuffer.ParallelWriter ecb;
  29. [ReadOnly] public float deltaTime;
  30. public void Execute(
  31. ref GpuEcsAnimatorShaderDataComponent gpuEcsAnimatorShaderData,
  32. ref GpuEcsAnimatorTransitionInfoComponent gpuEcsAnimatorTransitionInfo,
  33. ref GpuEcsAnimatorStateComponent gpuEcsAnimatorState,
  34. ref GpuEcsAnimatorInitializedComponent gpuEcsAnimatorInitialized,
  35. ref DynamicBuffer<GpuEcsCurrentAttachmentAnchorBufferElement> gpuEcsCurrentAttachmentAnchors,
  36. ref GpuEcsAnimatorControlStateComponent gpuEcsAnimatorControlState,
  37. ref DynamicBuffer<GpuEcsAnimatorEventBufferElement> gpuEcsAnimatorEventBuffer,
  38. in GpuEcsAnimatorControlComponent gpuEcsAnimatorControl,
  39. in GpuEcsAnimationDataComponent gpuEcsAnimationData,
  40. in DynamicBuffer<GpuEcsAnimationDataBufferElement> gpuEcsAnimationDataBuffer,
  41. in DynamicBuffer<GpuEcsAnimationEventOccurenceBufferElement> gpuEcsAnimationEventOccurenceBuffer,
  42. in DynamicBuffer<GpuEcsAttachmentAnchorDataBufferElement> gpuEcsAttachmentAnchorData,
  43. [ChunkIndexInQuery] int sortKey, Entity gpuEcsAnimatorEntity)
  44. {
  45. gpuEcsAnimatorEventBuffer.Clear();
  46. if (!gpuEcsAnimatorInitialized.initialized )
  47. {
  48. // We switch immediately to the first animation, no transition
  49. gpuEcsAnimatorTransitionInfo = new GpuEcsAnimatorTransitionInfoComponent()
  50. {
  51. current = gpuEcsAnimatorControl.animatorInfo,
  52. blendPreviousToCurrent = 1f
  53. };
  54. gpuEcsAnimatorState = new GpuEcsAnimatorStateComponent()
  55. {
  56. currentNormalizedTime = gpuEcsAnimatorControl.startNormalizedTime,
  57. stoppedPrevious = false,
  58. stoppedCurrent = false
  59. };
  60. gpuEcsAnimatorInitialized.initialized = true;
  61. }
  62. else if(gpuEcsAnimatorControl.animatorInfo.animationID != gpuEcsAnimatorTransitionInfo.current.animationID)
  63. {
  64. // A new animation (or animation combination) has been started, so we need to do a transition
  65. // from the old one to the new
  66. gpuEcsAnimatorTransitionInfo = new GpuEcsAnimatorTransitionInfoComponent()
  67. {
  68. current = gpuEcsAnimatorControl.animatorInfo,
  69. previous = gpuEcsAnimatorTransitionInfo.current,
  70. blendPreviousToCurrent = 0f
  71. };
  72. gpuEcsAnimatorState = new GpuEcsAnimatorStateComponent()
  73. {
  74. previousNormalizedTime = gpuEcsAnimatorState.currentNormalizedTime,
  75. stoppedPrevious = gpuEcsAnimatorState.stoppedCurrent,
  76. currentNormalizedTime = gpuEcsAnimatorControl.startNormalizedTime,
  77. stoppedCurrent = false,
  78. };
  79. }
  80. else
  81. {
  82. // The same animation (or animation combination) is still running, but the parameters might have changed
  83. // (blendPrimaryToSecondary or speedFactor)
  84. gpuEcsAnimatorTransitionInfo.current = gpuEcsAnimatorControl.animatorInfo;
  85. }
  86. GpuEcsAnimatorControlStates controlState = gpuEcsAnimatorControlState.state;
  87. if (gpuEcsAnimatorControlState.state == GpuEcsAnimatorControlStates.Start)
  88. gpuEcsAnimatorState.stoppedCurrent = false;
  89. else if (gpuEcsAnimatorControlState.state == GpuEcsAnimatorControlStates.Stop)
  90. gpuEcsAnimatorState.stoppedCurrent = true;
  91. gpuEcsAnimatorControlState.state = GpuEcsAnimatorControlStates.KeepCurrentState;
  92. if (!gpuEcsAnimatorState.stoppedCurrent)
  93. {
  94. UpdateAnimatorState(ref gpuEcsAnimatorState.currentNormalizedTime, ref gpuEcsAnimatorState.stoppedCurrent,
  95. ref gpuEcsAnimatorEventBuffer,
  96. gpuEcsAnimatorTransitionInfo.current, controlState, gpuEcsAnimationDataBuffer, gpuEcsAnimationEventOccurenceBuffer,
  97. out float primaryBlendFactor, out float primaryTransitionToNextFrame, out int primaryFrameIndex,
  98. out float secondaryBlendFactor, out float secondaryTransitionToNextFrame, out int secondaryFrameIndex,
  99. sortKey, gpuEcsAnimatorEntity, forPrevious: false);
  100. if (gpuEcsAnimatorTransitionInfo.blendPreviousToCurrent >= 1f)
  101. {
  102. gpuEcsAnimatorShaderData.shaderData = new float4x4(
  103. primaryBlendFactor, primaryTransitionToNextFrame, primaryFrameIndex, 0,
  104. secondaryBlendFactor, secondaryTransitionToNextFrame, secondaryFrameIndex, 0,
  105. 0, 0, 0, 0,
  106. 0, 0, 0, 0);
  107. //Apply attachment anchor transforms
  108. for (int attachmentAnchorIndex = 0; attachmentAnchorIndex < gpuEcsAnimationData.nbrOfAttachmentAnchors; attachmentAnchorIndex++)
  109. {
  110. int baseIndex = gpuEcsAnimationData.totalNbrOfFrames * attachmentAnchorIndex;
  111. gpuEcsCurrentAttachmentAnchors[attachmentAnchorIndex] = new GpuEcsCurrentAttachmentAnchorBufferElement()
  112. {
  113. currentTransform = LerpBlend(gpuEcsAttachmentAnchorData, baseIndex,
  114. primaryFrameIndex, secondaryFrameIndex,
  115. primaryTransitionToNextFrame, secondaryTransitionToNextFrame,
  116. secondaryBlendFactor)
  117. };
  118. }
  119. }
  120. else
  121. {
  122. if (gpuEcsAnimatorControl.transitionSpeed == 0) gpuEcsAnimatorTransitionInfo.blendPreviousToCurrent = 1f;
  123. else
  124. {
  125. gpuEcsAnimatorTransitionInfo.blendPreviousToCurrent += deltaTime / gpuEcsAnimatorControl.transitionSpeed;
  126. if (gpuEcsAnimatorTransitionInfo.blendPreviousToCurrent > 1f) gpuEcsAnimatorTransitionInfo.blendPreviousToCurrent = 1f;
  127. }
  128. float previousToCurrent = gpuEcsAnimatorTransitionInfo.blendPreviousToCurrent;
  129. float currentToPrevious = 1f - previousToCurrent;
  130. UpdateAnimatorState(ref gpuEcsAnimatorState.previousNormalizedTime, ref gpuEcsAnimatorState.stoppedPrevious,
  131. ref gpuEcsAnimatorEventBuffer,
  132. gpuEcsAnimatorTransitionInfo.previous, controlState, gpuEcsAnimationDataBuffer, gpuEcsAnimationEventOccurenceBuffer,
  133. out float previousPrimaryBlendFactor, out float previousPrimaryTransitionToNextFrame, out int previousPrimaryFrameIndex,
  134. out float previousSecondaryBlendFactor, out float previousSecondaryTransitionToNextFrame, out int previousSecondaryFrameIndex,
  135. sortKey, gpuEcsAnimatorEntity, forPrevious: true);
  136. gpuEcsAnimatorShaderData.shaderData = new float4x4(
  137. previousToCurrent * primaryBlendFactor, primaryTransitionToNextFrame, primaryFrameIndex, 0,
  138. previousToCurrent * secondaryBlendFactor, secondaryTransitionToNextFrame, secondaryFrameIndex, 0,
  139. currentToPrevious * previousPrimaryBlendFactor, previousPrimaryTransitionToNextFrame, previousPrimaryFrameIndex, 0,
  140. currentToPrevious * previousSecondaryBlendFactor, previousSecondaryTransitionToNextFrame, previousSecondaryFrameIndex, 0);
  141. for (int attachmentAnchorIndex = 0; attachmentAnchorIndex < gpuEcsAnimationData.nbrOfAttachmentAnchors; attachmentAnchorIndex++)
  142. {
  143. int baseIndex = gpuEcsAnimationData.totalNbrOfFrames * attachmentAnchorIndex;
  144. float4x4 current = LerpBlend(gpuEcsAttachmentAnchorData, baseIndex,
  145. primaryFrameIndex, secondaryFrameIndex,
  146. primaryTransitionToNextFrame, secondaryTransitionToNextFrame,
  147. secondaryBlendFactor);
  148. float4x4 previous = LerpBlend(gpuEcsAttachmentAnchorData, baseIndex,
  149. previousPrimaryFrameIndex, previousSecondaryFrameIndex,
  150. previousPrimaryTransitionToNextFrame, previousSecondaryTransitionToNextFrame,
  151. previousSecondaryBlendFactor);
  152. gpuEcsCurrentAttachmentAnchors[attachmentAnchorIndex] = new GpuEcsCurrentAttachmentAnchorBufferElement()
  153. {
  154. currentTransform = LerpTransform(previous, current, previousToCurrent)
  155. };
  156. }
  157. }
  158. }
  159. }
  160. private float4x4 LerpBlend(in DynamicBuffer<GpuEcsAttachmentAnchorDataBufferElement> gpuEcsAttachmentAnchorData,
  161. int baseIndex, int frameIndexA, int frameIndexB,
  162. float frameIndexATransitionToNextFrame, float frameIndexBTransitionToNextFrame,
  163. float t)
  164. {
  165. float4x4 result;
  166. if (t == 0)
  167. result = LerpNextFrame(gpuEcsAttachmentAnchorData, baseIndex, frameIndexA, frameIndexATransitionToNextFrame);
  168. else if(t == 1f)
  169. result = LerpNextFrame(gpuEcsAttachmentAnchorData, baseIndex, frameIndexB, frameIndexBTransitionToNextFrame);
  170. else
  171. {
  172. float4x4 primary = LerpNextFrame(gpuEcsAttachmentAnchorData, baseIndex, frameIndexA, frameIndexATransitionToNextFrame);
  173. float4x4 secondary = LerpNextFrame(gpuEcsAttachmentAnchorData, baseIndex, frameIndexB, frameIndexBTransitionToNextFrame);
  174. result = LerpTransform(primary, secondary, t);
  175. }
  176. return result;
  177. }
  178. private float4x4 LerpNextFrame(in DynamicBuffer<GpuEcsAttachmentAnchorDataBufferElement> gpuEcsAttachmentAnchorData,
  179. int baseIndex, int frameIndex, float transitionToNextFrame)
  180. {
  181. return LerpTransform(
  182. gpuEcsAttachmentAnchorData[baseIndex + frameIndex].anchorTransform,
  183. gpuEcsAttachmentAnchorData[baseIndex + frameIndex + 1].anchorTransform,
  184. transitionToNextFrame
  185. );
  186. }
  187. private float4x4 LerpTransform(float4x4 valueA, float4x4 valueB, float t)
  188. {
  189. float3 posA = new float3(valueA.c3.x, valueA.c3.y, valueA.c3.z);
  190. quaternion rotA = new quaternion(valueA);
  191. float3 posB = new float3(valueB.c3.x, valueB.c3.y, valueB.c3.z);
  192. quaternion rotB = new quaternion(valueB);
  193. float3 pos = math.lerp(posA, posB, t);
  194. Quaternion rot = math.slerp(rotA, rotB, t);
  195. return float4x4.TRS(pos, rot, new float3(1f, 1f, 1f));
  196. }
  197. private void UpdateAnimatorState(ref float normalizedTime, ref bool stopped,
  198. ref DynamicBuffer<GpuEcsAnimatorEventBufferElement> gpuEcsAnimatorEventBuffer,
  199. AnimatorInfo animatorInfo,
  200. in GpuEcsAnimatorControlStates controlState,
  201. in DynamicBuffer<GpuEcsAnimationDataBufferElement> gpuEcsAnimationDataBuffer,
  202. in DynamicBuffer<GpuEcsAnimationEventOccurenceBufferElement> gpuEcsAnimationEventOccurenceBuffer,
  203. out float primaryBlendFactor, out float primaryTransitionToNextFrame, out int primaryFrameIndex,
  204. out float secondaryBlendFactor, out float secondaryTransitionToNextFrame, out int secondaryFrameIndex,
  205. in int sortKey, Entity gpuEcsAnimatorEntity, bool forPrevious)
  206. {
  207. GpuEcsAnimationDataBufferElement animationData = gpuEcsAnimationDataBuffer[animatorInfo.animationID];
  208. if (animationData.nbrOfInBetweenSamples == 1)
  209. {
  210. float blendSpeedAdjustment = 1f;
  211. UpdateAnimationNormalizedTime(ref normalizedTime, ref stopped, ref gpuEcsAnimatorEventBuffer, animatorInfo, controlState,
  212. gpuEcsAnimationEventOccurenceBuffer, animationData, blendSpeedAdjustment,
  213. out float transitionToNextFrame, out int relativeFrameIndex, sortKey, gpuEcsAnimatorEntity, forPrevious);
  214. primaryBlendFactor = 1;
  215. primaryTransitionToNextFrame = transitionToNextFrame;
  216. primaryFrameIndex = animationData.startFrameIndex + relativeFrameIndex;
  217. secondaryBlendFactor = 0;
  218. secondaryTransitionToNextFrame = 0;
  219. secondaryFrameIndex = 0;
  220. }
  221. else
  222. {
  223. float endBlend = (float)(animationData.nbrOfInBetweenSamples - 1);
  224. float currentBlendSetFloat = animatorInfo.blendFactor * endBlend;
  225. int currentBlendSet = (int)math.floor(currentBlendSetFloat);
  226. float transitionToNextSet = currentBlendSetFloat - (float)currentBlendSet;
  227. float blendSpeedAdjustment = animatorInfo.blendFactor * animationData.blendTimeCorrection + (1f - animatorInfo.blendFactor);
  228. UpdateAnimationNormalizedTime(ref normalizedTime, ref stopped, ref gpuEcsAnimatorEventBuffer, animatorInfo, controlState,
  229. gpuEcsAnimationEventOccurenceBuffer, animationData, blendSpeedAdjustment,
  230. out float transitionToNextFrame, out int relativeFrameIndex, sortKey, gpuEcsAnimatorEntity, forPrevious);
  231. primaryBlendFactor = 1f - transitionToNextSet;
  232. primaryTransitionToNextFrame = transitionToNextFrame;
  233. primaryFrameIndex = animationData.startFrameIndex + currentBlendSet * animationData.nbrOfFramesPerSample + relativeFrameIndex;
  234. secondaryBlendFactor = transitionToNextSet;
  235. secondaryTransitionToNextFrame = transitionToNextFrame;
  236. secondaryFrameIndex = animationData.startFrameIndex + (currentBlendSet + 1) * animationData.nbrOfFramesPerSample + relativeFrameIndex;
  237. }
  238. }
  239. private void UpdateAnimationNormalizedTime(ref float normalizedTime, ref bool stopped,
  240. ref DynamicBuffer<GpuEcsAnimatorEventBufferElement> gpuEcsAnimatorEventBuffer,
  241. AnimatorInfo animatorInfo, in GpuEcsAnimatorControlStates controlState,
  242. in DynamicBuffer<GpuEcsAnimationEventOccurenceBufferElement> gpuEcsAnimationEventOccurenceBuffer,
  243. GpuEcsAnimationDataBufferElement animationData, float blendSpeedAdjustment,
  244. out float transitionToNextFrame, out int relativeFrameIndex, int sortKey, Entity gpuEcsAnimatorEntity, bool forPrevious)
  245. {
  246. int endFrame = animationData.nbrOfFramesPerSample - 1;
  247. float animationLength = (float)endFrame / GlobalConstants.SampleFrameRate;
  248. float currentTime = normalizedTime * animationLength;
  249. if(!stopped) currentTime += deltaTime * animatorInfo.speedFactor * blendSpeedAdjustment;
  250. float normalizedTimeLastUpdate = normalizedTime;
  251. normalizedTime = currentTime / animationLength;
  252. for (int eventOccurencId = animationData.startEventOccurenceId; eventOccurencId < animationData.startEventOccurenceId + animationData.nbrOfEventOccurenceIds; eventOccurencId++)
  253. {
  254. GpuEcsAnimationEventOccurenceBufferElement occurence = gpuEcsAnimationEventOccurenceBuffer[eventOccurencId];
  255. if (normalizedTimeLastUpdate < occurence.eventNormalizedTime && normalizedTime > occurence.eventNormalizedTime)
  256. {
  257. //Trigger event
  258. gpuEcsAnimatorEventBuffer.Add(new GpuEcsAnimatorEventBufferElement()
  259. {
  260. animationId = animatorInfo.animationID,
  261. eventId = occurence.eventId
  262. });
  263. }
  264. }
  265. if (!forPrevious && (animationData.loop || controlState == GpuEcsAnimatorControlStates.Start))
  266. {
  267. while (normalizedTime >= 1f) normalizedTime -= 1f;
  268. }
  269. else
  270. {
  271. if (normalizedTime >= 1f)
  272. {
  273. normalizedTime = 1f;
  274. stopped = true;
  275. }
  276. }
  277. if (normalizedTime == 1f)
  278. {
  279. relativeFrameIndex = endFrame - 1;
  280. transitionToNextFrame = 1f;
  281. }
  282. else
  283. {
  284. float relativeFrameIndexFloat = normalizedTime * (float)endFrame;
  285. relativeFrameIndex = (int)math.floor(relativeFrameIndexFloat);
  286. transitionToNextFrame = relativeFrameIndexFloat - (float)relativeFrameIndex;
  287. }
  288. }
  289. }
  290. }
  291. }