public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == BlobAssetReference <RigDefinition> .Null)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                var inputStream  = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                AnimationStreamUtils.MemCpy(ref outputStream, ref inputStream);

                var deltaRootX = new RigidTransform(inputStream.GetLocalToParentRotation(0), inputStream.GetLocalToParentTranslation(0));

                context.Resolve(ref ports.DeltaRootX) = math.float4x4(deltaRootX);

                RigidTransform prevRootX = new RigidTransform(context.Resolve(ports.PrevRootX));

                prevRootX.rot = math.normalizesafe(prevRootX.rot);
                context.Resolve(ref ports.RootX) = math.float4x4(math.mul(prevRootX, deltaRootX));

                var defaultStream = AnimationStream.FromDefaultValues(outputStream.Rig);

                outputStream.SetLocalToParentTranslation(0, defaultStream.GetLocalToParentTranslation(0));
                outputStream.SetLocalToParentRotation(0, defaultStream.GetLocalToParentRotation(0));

                data.ProfileMarker.End();
            }
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == default)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                // Fill the destination stream with default values.
                var startStream  = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Start));
                var stopStream   = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Stop));
                var inputStream  = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                AnimationStreamUtils.MemCpy(ref outputStream, ref inputStream);

                var startX = new RigidTransform(startStream.GetLocalToParentRotation(0), startStream.GetLocalToParentTranslation(0));
                var stopX  = new RigidTransform(stopStream.GetLocalToParentRotation(0), stopStream.GetLocalToParentTranslation(0));
                var x      = new RigidTransform(outputStream.GetLocalToParentRotation(0), outputStream.GetLocalToParentTranslation(0));
                var cycleX = GetCycleX(x, startX, stopX, context.Resolve(ports.Cycle));

                outputStream.SetLocalToParentRotation(0, cycleX.rot);
                outputStream.SetLocalToParentTranslation(0, cycleX.pos);

                data.ProfileMarker.End();
            }
예제 #3
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.SourceRigDefinition == default)
                {
                    return;
                }

                if (data.DestinationRigDefinition == default)
                {
                    return;
                }

                if (data.RemapTable == default)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                // Fill the destination stream with default values.
                var destinationStream = AnimationStream.Create(data.DestinationRigDefinition, context.Resolve(ref ports.Output));

                AnimationStreamUtils.SetDefaultValues(ref destinationStream);

                var sourceStream = AnimationStream.CreateReadOnly(data.SourceRigDefinition, context.Resolve(ports.Input));

                Core.RigRemapper(data.RemapTable, ref destinationStream, ref sourceStream);

                data.ProfileMarker.End();
            }
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == default)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                // Fill the destination stream with default values.
                var inputStream  = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                AnimationStreamUtils.MemCpy(ref outputStream, ref inputStream);

                var defaultStream     = AnimationStream.FromDefaultValues(data.RigDefinition);
                var motionTranslation = outputStream.GetLocalToRootTranslation(data.TranslationIndex);
                var motionRotation    = outputStream.GetLocalToRootRotation(data.RotationIndex);

                var defaultRotation = defaultStream.GetLocalToRootRotation(data.RotationIndex);

                defaultRotation = mathex.mul(motionRotation, math.conjugate(defaultRotation));
                defaultRotation = mathex.select(quaternion.identity, defaultRotation, math.dot(defaultRotation, defaultRotation) > math.FLT_MIN_NORMAL);

                ProjectMotionNode(motionTranslation, defaultRotation, out float3 motionProjTranslation, out quaternion motionProjRotation, (data.Configuration.Mask & ClipConfigurationMask.BankPivot) != 0);

                outputStream.SetLocalToRootTranslation(0, motionProjTranslation);
                outputStream.SetLocalToRootRotation(0, motionProjRotation);

                outputStream.SetLocalToRootTranslation(data.TranslationIndex, motionTranslation);
                outputStream.SetLocalToRootRotation(data.RotationIndex, motionRotation);

                data.ProfileMarker.End();
            }
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == BlobAssetReference <RigDefinition> .Null)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                // Fill the destination stream with default values.
                var prevStream    = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Previous));
                var currentStream = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Current));
                var outputStream  = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                AnimationStreamUtils.MemCpy(ref outputStream, ref currentStream);

                // current = prev * delta
                // delta = Inv(prev) * current
                var prevX  = new RigidTransform(prevStream.GetLocalToParentRotation(0), prevStream.GetLocalToParentTranslation(0));
                var x      = new RigidTransform(currentStream.GetLocalToParentRotation(0), currentStream.GetLocalToParentTranslation(0));
                var deltaX = math.mul(math.inverse(prevX), x);

                outputStream.SetLocalToParentTranslation(0, deltaX.pos);
                outputStream.SetLocalToParentRotation(0, deltaX.rot);

                data.ProfileMarker.End();
            }
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == BlobAssetReference <RigDefinition> .Null)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                // Fill the destination stream with default values.
                var inputStream  = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                AnimationStreamUtils.MemCpy(ref outputStream, ref inputStream);

                float deltaTime = context.Resolve(ports.DeltaTime) * data.SampleRate;

                var rootVelocity = new RigidTransform(outputStream.GetLocalToParentRotation(0), outputStream.GetLocalToParentTranslation(0));

                rootVelocity.pos           *= deltaTime;
                rootVelocity.rot.value.xyz *= (deltaTime / rootVelocity.rot.value.w);
                rootVelocity.rot.value.w    = 1;
                rootVelocity.rot            = math.normalize(rootVelocity.rot);

                outputStream.SetLocalToParentTranslation(0, rootVelocity.pos);
                outputStream.SetLocalToParentRotation(0, rootVelocity.rot);

                data.ProfileMarker.End();
            }
예제 #7
0
        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 Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var stream = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));

                if (stream.IsNull)
                {
                    throw new System.InvalidOperationException("GetAnimationStreamFloatNode input is invalid.");
                }

                data.ProfilerMarker.Begin();
                context.Resolve(ref ports.Output) = stream.GetFloat(context.Resolve(ports.Index));
                data.ProfilerMarker.End();
            }
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == BlobAssetReference <RigDefinition> .Null)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                var inputStream  = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                Core.WeightPose(ref outputStream, ref inputStream, context.Resolve(ports.WeightMasks));

                data.ProfileMarker.End();
            }
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var rigs         = chunk.GetNativeArray(Rigs);
                var lFloats      = chunk.GetBufferAccessor(Floats);
                var localToRoots = chunk.GetBufferAccessor(LocalToRoot);

                for (int i = 0; i != chunk.Count; ++i)
                {
                    var stream = AnimationStream.CreateReadOnly(
                        rigs[i].Value,
                        lFloats[i].AsNativeArray()
                        );

                    Core.ComputeLocalToRoot(ref stream, localToRoots[i].Reinterpret <float4x4>().AsNativeArray());
                }
            }
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == BlobAssetReference <RigDefinition> .Null)
                {
                    return;
                }

                data.ProfileMarker.Begin();

                // Fill the destination stream with default values.
                var inputStream  = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                Core.InversePose(ref outputStream, ref inputStream);

                data.ProfileMarker.End();
            }
예제 #12
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var rigs             = chunk.GetNativeArray(Rigs);
                var graphOutputArray = chunk.GetNativeArray(GraphOutputs);
                var floatsBuffer     = chunk.GetBufferAccessor(Floats);

                for (int i = 0; i != graphOutputArray.Length; ++i)
                {
                    var ecsStream = AnimationStream.Create(
                        rigs[i].Value,
                        floatsBuffer[i].AsNativeArray()
                        );
                    var graphStream = AnimationStream.CreateReadOnly(rigs[i].Value, GraphValueResolver.Resolve(graphOutputArray[i].Buffer));

                    AnimationStreamUtils.MemCpy(ref ecsStream, ref graphStream);
                }
            }
예제 #13
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var stream = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));

                if (stream.IsNull)
                {
                    throw new System.InvalidOperationException($"GetAnimationStreamLocalToRootNode input is invalid.");
                }

                data.ProfilerMarker.Begin();

                stream.GetLocalToRootTR(context.Resolve(ports.Index), out float3 translation, out quaternion rotation);
                context.Resolve(ref ports.Translation) = translation;
                context.Resolve(ref ports.Rotation)    = rotation;
                context.Resolve(ref ports.Transform)   = new float4x4(rotation, translation);

                data.ProfilerMarker.End();
            }
예제 #14
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                if (outputStream.IsNull)
                {
                    throw new System.InvalidOperationException($"MixerEndNode Output is invalid.");
                }

                var defaultPoseInputStream = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.DefaultPoseInput));
                var inputStream            = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));

                data.ProfileMixerEnd.Begin();

                Core.MixerEnd(ref outputStream, ref inputStream, ref defaultPoseInputStream, context.Resolve(ports.SumWeight));

                data.ProfileMixerEnd.End();
            }
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                if (outputStream.IsNull)
                {
                    throw new System.InvalidOperationException($"ChannelWeightMixerNode output is invalid.");
                }

                var inputStream0 = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input0));
                var inputStream1 = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input1));

                data.ProfileMarker.Begin();

                var weight      = context.Resolve(ports.Weight);
                var weightMasks = context.Resolve(ports.WeightMasks);

                if (Core.WeightDataSize(outputStream.Rig) != weightMasks.Length)
                {
                    throw new System.InvalidOperationException($"ChannelWeightMixerNode: WeightMasks size does not match RigDefinition. WeightMasks size is '{weightMasks.Length}' but RigDefinition expects a size of '{Core.WeightDataSize(inputStream0.Rig)}'.");
                }

                if (inputStream0.IsNull && inputStream1.IsNull)
                {
                    AnimationStreamUtils.SetDefaultValues(ref outputStream);
                }
                else if (inputStream0.IsNull && !inputStream1.IsNull)
                {
                    AnimationStreamUtils.SetDefaultValues(ref outputStream);
                    Core.Blend(ref outputStream, ref outputStream, ref inputStream1, weight, weightMasks);
                }
                else if (!inputStream0.IsNull && inputStream1.IsNull)
                {
                    AnimationStreamUtils.SetDefaultValues(ref outputStream);
                    Core.Blend(ref outputStream, ref inputStream0, ref outputStream, weight, weightMasks);
                }
                else
                {
                    Core.Blend(ref outputStream, ref inputStream0, ref inputStream1, weight, weightMasks);
                }

                data.ProfileMarker.End();
            }
예제 #16
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                if (outputStream.IsNull)
                {
                    throw new System.InvalidOperationException($"MixerAddNode Output is invalid.");
                }

                var addStream   = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Add));
                var inputStream = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input));
                var weight      = context.Resolve(ports.Weight);
                var sumWeight   = context.Resolve(ports.SumWeightInput);

                data.ProfileMixerAdd.Begin();

                sumWeight = Core.MixerAdd(ref outputStream, ref inputStream, ref addStream, weight, sumWeight);

                context.Resolve(ref ports.SumWeightOutput) = sumWeight;

                data.ProfileMixerAdd.End();
            }
예제 #17
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                if (outputStream.IsNull)
                {
                    throw new System.InvalidOperationException($"NMixerNode Output is invalid.");
                }

                var inputArray  = context.Resolve(ports.Inputs);
                var weightArray = context.Resolve(ports.Weights);

                if (inputArray.Length != weightArray.Length)
                {
                    throw new System.InvalidOperationException($"NMixerNode: Inputs And Weight Port array length mismatch. Expecting '{weightArray.Length}' but was '{inputArray.Length}'.");
                }

                var sumWeight = 0.0f;

                data.ProfileNMixer.Begin();

                Core.MixerBegin(ref outputStream);

                for (int i = 0; i < inputArray.Length; ++i)
                {
                    var inputStream = AnimationStream.CreateReadOnly(data.RigDefinition, inputArray[i].ToNative(context));

                    if (!inputStream.IsNull)
                    {
                        sumWeight = Core.MixerAdd(ref outputStream, ref outputStream, ref inputStream, weightArray[i], sumWeight);
                    }
                }

                var defaultPoseInputStream = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.DefaultPoseInput));

                Core.MixerEnd(ref outputStream, ref outputStream, ref defaultPoseInputStream, sumWeight);

                data.ProfileNMixer.End();
            }
예제 #18
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                if (outputStream.IsNull)
                {
                    throw new System.InvalidOperationException($"MixerNode Output is invalid.");
                }

                var inputStream1 = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input0));
                var inputStream2 = AnimationStream.CreateReadOnly(data.RigDefinition, context.Resolve(ports.Input1));

                var weight = context.Resolve(in ports.Weight);

                data.ProfileMixPose.Begin();

                if (inputStream1.IsNull && inputStream2.IsNull)
                {
                    AnimationStreamUtils.SetDefaultValues(ref outputStream);
                }
                else if (inputStream1.IsNull && !inputStream2.IsNull)
                {
                    AnimationStreamUtils.SetDefaultValues(ref outputStream);
                    Core.Blend(ref outputStream, ref outputStream, ref inputStream2, weight);
                }
                else if (!inputStream1.IsNull && inputStream2.IsNull)
                {
                    AnimationStreamUtils.SetDefaultValues(ref outputStream);
                    Core.Blend(ref outputStream, ref inputStream1, ref outputStream, weight);
                }
                else
                {
                    Core.Blend(ref outputStream, ref inputStream1, ref inputStream2, weight);
                }

                data.ProfileMixPose.End();
            }
예제 #19
0
            public unsafe void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var inputArray      = context.Resolve(ports.Inputs);
                var weightArray     = context.Resolve(ports.Weights);
                var weightMaskArray = context.Resolve(ports.WeightMasks);

                if (inputArray.Length != data.LayerCount)
                {
                    throw new System.InvalidOperationException($"LayerMixerNode: Inputs Port array length mismatch. Expecting '{data.LayerCount}' but was '{inputArray.Length}'.");
                }

                if (weightArray.Length != data.LayerCount)
                {
                    throw new System.InvalidOperationException($"LayerMixerNode: Weights Port array length mismatch. Expecting '{data.LayerCount}' but was '{weightArray.Length}'.");
                }

                if (weightMaskArray.Length != data.LayerCount)
                {
                    throw new System.InvalidOperationException($"LayerMixerNode: WeightMasks Port array length mismatch. Expecting '{data.LayerCount}' but was '{weightArray.Length}'.");
                }

                data.ProfilerMarker.Begin();

                var outputStream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

                AnimationStreamUtils.SetDefaultValues(ref outputStream);

                int expectedWeightDataSize = Core.WeightDataSize(data.RigDefinition);

                for (int i = 0; i < inputArray.Length; ++i)
                {
                    var inputStream = AnimationStream.CreateReadOnly(data.RigDefinition, inputArray[i].ToNative(context));
                    if (weightArray[i] > 0 && !inputStream.IsNull)
                    {
                        var weightMasks = weightMaskArray[i].ToNative(context);
                        if (weightMasks.Length == expectedWeightDataSize)
                        {
                            if (ItemAt <BlendingMode>(data.BlendingModes, i) == BlendingMode.Override)
                            {
                                Core.BlendOverrideLayer(ref outputStream, ref inputStream, weightArray[i], weightMasks);
                            }
                            else
                            {
                                Core.BlendAdditiveLayer(ref outputStream, ref inputStream, weightArray[i], weightMasks);
                            }
                        }
                        else
                        {
                            if (ItemAt <BlendingMode>(data.BlendingModes, i) == BlendingMode.Override)
                            {
                                Core.BlendOverrideLayer(ref outputStream, ref inputStream, weightArray[i]);
                            }
                            else
                            {
                                Core.BlendAdditiveLayer(ref outputStream, ref inputStream, weightArray[i]);
                            }
                        }
                    }
                }

                data.ProfilerMarker.End();
            }
예제 #20
0
        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));
        }
예제 #21
0
        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");
        }
예제 #22
0
        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");
        }