protected override void OnUpdate() { // Initialize Entities.WithNone <Initialized>().WithAll <Base>().ForEach((Entity entity, ref RigDefinitionSetup rigDefSetup) => { // TODO (mogensh) make this an option. If we remap content to another rigentity we dont want to update rig here RigEntityBuilder.SetupRigEntity(entity, EntityManager, rigDefSetup.Value); if (EntityManager.HasComponent <SkinnedMeshRenderer>(entity)) { var animatedSkinMatricesArray = EntityManager.AddBuffer <AnimatedLocalToRig>(entity); animatedSkinMatricesArray.ResizeUninitialized(rigDefSetup.Value.Value.Skeleton.BoneCount); } EntityManager.SetSharedComponentData(entity, new SharedRigDefinition { Value = rigDefSetup.Value }); PostUpdateCommands.AddComponent(entity, new Initialized()); }); // Deinitialize Entities.WithNone <Base>().WithAll <Initialized>().ForEach((Entity entity) => { PostUpdateCommands.RemoveComponent <Initialized>(entity); }); }
public void CanInstantiatePrefabEntity() { var instanceCount = 100; var skeletonNodes = new SkeletonNode[] { new SkeletonNode { ParentIndex = -1, Id = "Root", AxisIndex = -1 }, new SkeletonNode { ParentIndex = 0, Id = "Hips", AxisIndex = -1 }, new SkeletonNode { ParentIndex = 1, Id = "LeftUpLeg", AxisIndex = -1 }, new SkeletonNode { ParentIndex = 1, Id = "RightUpLeg", AxisIndex = -1 } }; var rigDefinition = RigBuilder.CreateRigDefinition(skeletonNodes); var prefab = RigEntityBuilder.CreatePrefabEntity(m_Manager, rigDefinition); var entities = new NativeArray <Entity>(instanceCount, Allocator.Temp); m_Manager.Instantiate(prefab, entities); foreach (var entity in entities) { CheckEntityHasRigComponentTypeAndBufferResized(entity, rigDefinition, RigEntityBuilder.RigComponentTypes, skeletonNodes.Length); } }
protected override void OnUpdate() { Entities.ForEach((Entity e, ref RigSpawner spawner) => { if (EntityManager.HasComponent <RigDefinitionSetup>(spawner.RigPrefab)) { var rigDefinition = EntityManager.GetComponentData <RigDefinitionSetup>(spawner.RigPrefab); if (!rigDefinition.Value.IsCreated) { throw new System.ObjectDisposedException("RigDefinition is not Created"); } RigEntityBuilder.SetupRigEntity(spawner.RigPrefab, EntityManager, rigDefinition.Value); } for (var x = 0; x < spawner.CountX; x++) { for (var y = 0; y < spawner.CountY; ++y) { var rigInstance = EntityManager.Instantiate(spawner.RigPrefab); var position = new float3(x * 1.3F, 0, y * 1.3F); EntityManager.SetComponentData(rigInstance, new Translation { Value = position }); if (m_Input != null) { m_Input.RegisterEntity(rigInstance); } } } EntityManager.DestroyEntity(e); }); }
protected override JobHandle OnUpdate(JobHandle inputDependencies) { inputDependencies.Complete(); var animGraphSys = World.GetExistingSystem <AnimationGraphSystem>(); // Initialize Entities .WithStructuralChanges() .WithNone <LOD>() .WithAll <Settings>() .ForEach((Entity entity) => { GameDebug.Log(World, ShowLifetime, "InitSys: Initialize DotsAnimStateCtrl:{0}", entity); // Setup lowest LOD rig var rigDataBuffer = EntityManager.GetBuffer <RigData>(entity); // var lowestLod = rigDataBuffer.Length - 1; // TODO (mogensh) for now we only use Rig LOD for selecting low lod on server var isServer = World.GetExistingSystem <ServerSimulationSystemGroup>() != null;// TODO (mogensh) cant we find better way to test for server? var lod = isServer ? 1 : 0; var rigData = rigDataBuffer[lod]; RigEntityBuilder.SetupRigEntity(entity, EntityManager, rigData.Rig); var animLocalToRigBuffer = EntityManager.AddBuffer <AnimatedLocalToRig>(entity); animLocalToRigBuffer.ResizeUninitialized(rigData.Rig.Value.Skeleton.Ids.Length); // Create root animsource var settings = EntityManager.GetComponentData <Settings>(entity); var rootAnimSourceEntity = PrefabAssetManager.CreateEntity(EntityManager, settings.RootAnimSource); #if UNITY_EDITOR var name = EntityManager.GetName(rootAnimSourceEntity) + " -> Entity " + entity.Index + ".DotsAnimStateController.RootAnimSource"; EntityManager.SetName(rootAnimSourceEntity, name); #endif AnimSource.SetAnimStateEntityOnPrefab(EntityManager, rootAnimSourceEntity, entity); var rootAnimSource = RootAnimSource.Default; rootAnimSource.Value = rootAnimSourceEntity; EntityManager.AddComponentData(entity, rootAnimSource); EntityManager.AddComponentData(entity, new LOD { Value = lod, }); }).Run(); // Deinitialize Entities .WithStructuralChanges() .WithNone <Settings>() .WithAll <LOD>() .ForEach((Entity entity, ref RootAnimSource rootAnimSource, ref OutputNode outputNode, ref GraphOutput graphOutput) => { Deinitialize(EntityManager, entity, animGraphSys); }).Run(); return(default);
protected override void OnUpdate() { Entities.ForEach((RigComponent rigComponent) => { var rigEntity = GetPrimaryEntity(rigComponent); var skeletonNodes = RigGenerator.ExtractSkeletonNodesFromRigComponent(rigComponent); var channels = RigGenerator.ExtractAnimationChannelFromRigComponent(rigComponent); var rigDefinition = RigBuilder.CreateRigDefinition(skeletonNodes, null, channels); RigEntityBuilder.SetupRigEntity(rigEntity, DstEntityManager, rigDefinition); }); }
public void CanApplyInPlaceNode() { var entity = m_Manager.CreateEntity(); RigEntityBuilder.SetupRigEntity(entity, m_Manager, m_Rig); var clipNode = CreateNode <ClipNode>(); Set.SendMessage(clipNode, ClipNode.SimulationPorts.Rig, m_Rig); Set.SendMessage(clipNode, ClipNode.SimulationPorts.Clip, m_Clip); Set.SetData(clipNode, ClipNode.KernelPorts.Time, 1.0f); var inPlaceNode = CreateNode <InPlaceMotionNode>(); Set.SendMessage(inPlaceNode, InPlaceMotionNode.SimulationPorts.Rig, m_Rig); Set.SendMessage(inPlaceNode, InPlaceMotionNode.SimulationPorts.Configuration, new ClipConfiguration { MotionID = new StringHash("Motion") }); Set.Connect(clipNode, ClipNode.KernelPorts.Output, inPlaceNode, InPlaceMotionNode.KernelPorts.Input); var entityNode = CreateComponentNode(entity); Set.Connect(inPlaceNode, InPlaceMotionNode.KernelPorts.Output, entityNode); m_Manager.AddComponent <PreAnimationGraphTag>(entity); m_AnimationGraphSystem.Update(); var translation = m_StopTranslation; var rotation = m_StopRotation; var projRotation = math.normalize(new quaternion(0, rotation.value.y / rotation.value.w, 0, 1)); var streamECS = AnimationStream.CreateReadOnly( m_Rig, m_Manager.GetBuffer <AnimatedData>(entity).AsNativeArray() ); // validate projection of motion on root var rootTranslation = streamECS.GetLocalToParentTranslation(0); Assert.That(rootTranslation, Is.EqualTo(new float3(translation.x, 0, translation.z)).Using(TranslationComparer)); var rootRotation = streamECS.GetLocalToParentRotation(0); Assert.That(rootRotation, Is.EqualTo(projRotation).Using(RotationComparer)); // validate that motion is now in place var motionTranslation = streamECS.GetLocalToParentTranslation(2); Assert.That(motionTranslation, Is.EqualTo(new float3(0, translation.y, 0)).Using(TranslationComparer)); var motionRotation = streamECS.GetLocalToParentRotation(2); Assert.That(motionRotation, Is.EqualTo(mathex.mul(math.conjugate(projRotation), rotation)).Using(RotationComparer)); }
public void CanCreatePrefabEntity() { var skeletonNodes = new SkeletonNode[] { new SkeletonNode { ParentIndex = -1, Id = "Root", AxisIndex = -1 } }; var rigDefinition = RigBuilder.CreateRigDefinition(skeletonNodes); var prefab = RigEntityBuilder.CreatePrefabEntity(m_Manager, rigDefinition); CheckEntityHasRigComponentTypeAndBufferResized(prefab, rigDefinition, RigEntityBuilder.RigPrefabComponentTypes, skeletonNodes.Length); }
protected override void SetUp() { base.SetUp(); m_RigComputeMatricesSystem = World.GetOrCreateSystem <RigComputeMatricesSystem>(); // Force and update to kick burst compilation m_RigComputeMatricesSystem.Update(); Set.RendererModel = DataFlowGraph.NodeSet.RenderExecutionModel.Islands; // Force and update to kick burst compilation m_AnimationGraphSystem.Update(); m_RigPrefab = RigEntityBuilder.CreatePrefabEntity(m_Manager, m_RigDefinition); m_Manager.AddComponentData(m_RigPrefab, new Translation { Value = float3.zero }); m_Manager.AddComponentData(m_RigPrefab, new Rotation { Value = quaternion.identity }); }
public void CanEvaluateCycleRootClipNode(float time) { var entity = m_Manager.CreateEntity(); RigEntityBuilder.SetupRigEntity(entity, m_Manager, m_Rig); var clipNode = CreateNode <ConfigurableClipNode>(); Set.SendMessage(clipNode, ConfigurableClipNode.SimulationPorts.Configuration, new ClipConfiguration { Mask = ClipConfigurationMask.CycleRootMotion, MotionID = new StringHash("Motion") }); Set.SendMessage(clipNode, ConfigurableClipNode.SimulationPorts.Rig, m_Rig); Set.SendMessage(clipNode, ConfigurableClipNode.SimulationPorts.Clip, m_Clip); Set.SetData(clipNode, ConfigurableClipNode.KernelPorts.Time, time); var entityNode = CreateComponentNode(entity); Set.Connect(clipNode, ConfigurableClipNode.KernelPorts.Output, entityNode); m_Manager.AddComponent <PreAnimationGraphTag>(entity); m_AnimationGraphSystem.Update(); var normalizedTime = time; var normalizedTimeInt = (int)normalizedTime; var cycle = math.select(normalizedTimeInt, normalizedTimeInt - 1, normalizedTime < 0); normalizedTime = math.select(normalizedTime - normalizedTimeInt, normalizedTime - normalizedTimeInt + 1, normalizedTime < 0); // start and stop root transform var startTProj = new float3(m_StartTranslation.x, 0, m_StartTranslation.z); var startRProj = math.normalize(new quaternion(0, m_StartRotation.value.y / m_StartRotation.value.w, 0, 1)); var stopTProj = new float3(m_StopTranslation.x, 0, m_StopTranslation.z); var stopRProj = math.normalize(new quaternion(0, m_StopRotation.value.y / m_StopRotation.value.w, 0, 1)); // current root transform var translation = m_StopTranslation * normalizedTime + m_StartTranslation * (1f - normalizedTime); var rotation = math.normalize(new quaternion(math.normalize(m_StopRotation).value *normalizedTime + math.normalize(m_StartRotation).value *(1f - normalizedTime))); var tProj = new float3(translation.x, 0, translation.z); var rProj = math.normalize(new quaternion(0, rotation.value.y / rotation.value.w, 0, 1)); // cycled root transform var startX = cycle >= 0 ? new RigidTransform(startRProj, startTProj) : new RigidTransform(stopRProj, stopTProj); var stopX = cycle >= 0 ? new RigidTransform(stopRProj, stopTProj) : new RigidTransform(startRProj, startTProj); var x = new RigidTransform(rProj, tProj); RigidTransform cycleX = mathex.rigidPow(math.mul(stopX, math.inverse(startX)), math.asuint(math.abs(cycle))); x = math.mul(cycleX, x); var streamECS = AnimationStream.CreateReadOnly( m_Rig, m_Manager.GetBuffer <AnimatedData>(entity).AsNativeArray() ); // validate var rootTranslation = streamECS.GetLocalToParentTranslation(0); Assert.That(rootTranslation, Is.EqualTo(x.pos)); var rootRotation = streamECS.GetLocalToParentRotation(0); Assert.That(rootRotation, Is.EqualTo(x.rot).Using(RotationComparer)); }
public void CanRemapAllIntChannel() { var sourceChannels = new IAnimationChannel[] { new IntChannel { Id = "Root", DefaultValue = m_ExpectedSourceInt }, new IntChannel { Id = "Child1", DefaultValue = m_ExpectedSourceInt }, new IntChannel { Id = "Child2", DefaultValue = m_ExpectedSourceInt }, }; var sourceRig = new Rig { Value = RigBuilder.CreateRigDefinition(sourceChannels) }; var destinationChannels = new IAnimationChannel[] { new IntChannel { Id = "AnotherRoot", DefaultValue = 0 }, new IntChannel { Id = "AnotherChild1", DefaultValue = 0 }, new IntChannel { Id = "AnotherChild2", DefaultValue = 0 }, }; var destinationRig = new Rig { Value = RigBuilder.CreateRigDefinition(destinationChannels) }; var rigEntity = m_Manager.CreateEntity(); RigEntityBuilder.SetupRigEntity(rigEntity, m_Manager, destinationRig); var rigRemapQuery = new RigRemapQuery { AllChannels = new [] { new ChannelMap { SourceId = "Root", DestinationId = "AnotherRoot" }, new ChannelMap { SourceId = "Child1", DestinationId = "AnotherChild1" }, new ChannelMap { SourceId = "Child2", DestinationId = "AnotherChild2" } } }; var remapTable = rigRemapQuery.ToRigRemapTable(sourceRig, destinationRig); // Here I'm using a layerMixer with no inputs connected // the expected result is to inject the default pose into Graph samples buffer var layerMixer = CreateNode <LayerMixerNode>(); Set.SendMessage(layerMixer, LayerMixerNode.SimulationPorts.Rig, sourceRig); var rigRemapper = CreateNode <RigRemapperNode>(); Set.Connect(layerMixer, LayerMixerNode.KernelPorts.Output, rigRemapper, RigRemapperNode.KernelPorts.Input); Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.SourceRig, sourceRig); Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.DestinationRig, destinationRig); Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.RemapTable, remapTable); var entityNode = CreateComponentNode(rigEntity); Set.Connect(rigRemapper, RigRemapperNode.KernelPorts.Output, entityNode); m_Manager.AddComponent <PreAnimationGraphTag>(rigEntity); m_AnimationGraphSystem.Update(); var streamECS = AnimationStream.CreateReadOnly( destinationRig, m_Manager.GetBuffer <AnimatedData>(rigEntity).AsNativeArray() ); Assert.That(streamECS.GetInt(0), Is.EqualTo(m_ExpectedSourceInt), "Channel int 0 doesn't match source rig default value"); Assert.That(streamECS.GetInt(1), Is.EqualTo(m_ExpectedSourceInt), "Channel int 1 doesn't match source rig default value"); Assert.That(streamECS.GetInt(2), Is.EqualTo(m_ExpectedSourceInt), "Channel int 2 doesn't match source rig default value"); }
public void CanRemapRigRotationOffset() { var sourceChannels = new IAnimationChannel[] { new LocalRotationChannel { Id = "Root", DefaultValue = m_ExpectedSourceRotation }, new LocalRotationChannel { Id = "Child", DefaultValue = m_ExpectedSourceRotation }, }; var sourceRig = new Rig { Value = RigBuilder.CreateRigDefinition(sourceChannels) }; var destinationChannels = new IAnimationChannel[] { new LocalRotationChannel { Id = "AnotherRoot", DefaultValue = quaternion.identity }, new LocalRotationChannel { Id = "AnotherChild", DefaultValue = quaternion.identity }, }; var destinationRig = new Rig { Value = RigBuilder.CreateRigDefinition(destinationChannels) }; var rigEntity = m_Manager.CreateEntity(); RigEntityBuilder.SetupRigEntity(rigEntity, m_Manager, destinationRig); var rigRemapQuery = new RigRemapQuery { RotationChannels = new [] { new ChannelMap { SourceId = "Root", DestinationId = "AnotherRoot" }, new ChannelMap { SourceId = "Child", DestinationId = "AnotherChild", OffsetIndex = 1 } }, RotationOffsets = new [] { new RigRotationOffset(), new RigRotationOffset { PreRotation = math.normalize(math.quaternion(1, 2, 3, 4)), PostRotation = math.normalize(math.quaternion(5, 6, 7, 8)) } } }; var remapTable = rigRemapQuery.ToRigRemapTable(sourceRig, destinationRig); // Here I'm using a layerMixer with no inputs connected // the expected result is to inject the default pose into Graph samples buffer var layerMixer = CreateNode <LayerMixerNode>(); Set.SendMessage(layerMixer, LayerMixerNode.SimulationPorts.Rig, sourceRig); var rigRemapper = CreateNode <RigRemapperNode>(); Set.Connect(layerMixer, LayerMixerNode.KernelPorts.Output, rigRemapper, RigRemapperNode.KernelPorts.Input); Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.SourceRig, sourceRig); Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.DestinationRig, destinationRig); Set.SendMessage(rigRemapper, RigRemapperNode.SimulationPorts.RemapTable, remapTable); var entityNode = CreateComponentNode(rigEntity); Set.Connect(rigRemapper, RigRemapperNode.KernelPorts.Output, entityNode); m_Manager.AddComponent <PreAnimationGraphTag>(rigEntity); m_AnimationGraphSystem.Update(); var streamECS = AnimationStream.CreateReadOnly( destinationRig, m_Manager.GetBuffer <AnimatedData>(rigEntity).AsNativeArray() ); Assert.That(streamECS.GetLocalToParentRotation(1), Is.EqualTo(math.mul(rigRemapQuery.RotationOffsets[1].PreRotation, math.mul(m_ExpectedSourceRotation, rigRemapQuery.RotationOffsets[1].PostRotation))).Using(RotationComparer), "Channel localRotation doesn't match destination rig default value with rig rotation offset"); }