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 TwoBoneIKInfluencedByHint()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var ikData = Core.TwoBoneIKData.Default();

            ikData.RootIndex   = k_RootIndex;
            ikData.MidIndex    = k_MidIndex;
            ikData.TipIndex    = k_TipIndex;
            ikData.LimbLengths = new float2(
                math.distance(stream.GetLocalToRootTranslation(k_RootIndex), stream.GetLocalToRootTranslation(k_MidIndex)),
                math.distance(stream.GetLocalToRootTranslation(k_MidIndex), stream.GetLocalToRootTranslation(k_TipIndex)));
            ikData.HintWeight = 1f;

            // Bend considering target is above x axis
            var midPos1 = stream.GetLocalToRootTranslation(k_MidIndex);

            ikData.Target.pos = new float3(2f, 0.5f, 0f);
            ikData.Hint       = midPos1 + new float3(0f, -2f, 0f);

            Core.SolveTwoBoneIK(ref stream, ikData, 1f);

            var midPos2 = stream.GetLocalToRootTranslation(k_MidIndex);

            Assert.Less(midPos2.y, 0f, "Expected midPos2.y to be less than zero");
            Assert.AreEqual(midPos1.z, midPos2.z, $"Expected midPos2.z to be '{midPos1.z}' but was '{midPos2.z}'");

            // Bend considering target is below x axis and hint is inverted
            ikData.Target.pos = new float3(2f, -0.5f, 0f);
            ikData.Hint       = midPos2 + new float3(0f, 2f, 0f);
            Core.SolveTwoBoneIK(ref stream, ikData, 1f);

            var midPos3 = stream.GetLocalToRootTranslation(k_MidIndex);

            Assert.Greater(midPos3.y, 0f, "Expected midPos3.y to be greater than zero");
            Assert.AreEqual(midPos1.z, midPos3.z, $"Expected midPos3.z to be '{midPos1.z}' but was '{midPos3.z}'");

            // Move hint in z axis
            ikData.Hint += new float3(0f, 0f, 1f);
            Core.SolveTwoBoneIK(ref stream, ikData, 1f);

            var midPos4 = stream.GetLocalToRootTranslation(k_MidIndex);

            Assert.Greater(midPos4.y, 0f, "Expected midPos4.y to be greater than zero");
            Assert.Greater(midPos4.z, 0f, "Expected midPos4.z to be greater than zero");

            // Move hint in -z axis
            ikData.Hint.z *= -1f;
            Core.SolveTwoBoneIK(ref stream, ikData, 1f);

            var midPos5 = stream.GetLocalToRootTranslation(k_MidIndex);

            Assert.Greater(midPos5.y, 0f, "Expected midPos5.y to be greater than zero");
            Assert.Less(midPos5.z, 0f, "Expected midPos5.z to be less than zero");

            buffer.Dispose();
        }
        public void TwoBoneIKFollowsTarget()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var ikData = Core.TwoBoneIKData.Default();

            ikData.RootIndex   = k_RootIndex;
            ikData.MidIndex    = k_MidIndex;
            ikData.TipIndex    = k_TipIndex;
            ikData.LimbLengths = new float2(
                math.distance(stream.GetLocalToRootTranslation(k_RootIndex), stream.GetLocalToRootTranslation(k_MidIndex)),
                math.distance(stream.GetLocalToRootTranslation(k_MidIndex), stream.GetLocalToRootTranslation(k_TipIndex)));

            ikData.Target.pos = new float3(0f, 1f, 0f);
            for (int i = 0; i < 5; ++i)
            {
                ikData.Target.pos.y += 0.3f;
                Core.SolveTwoBoneIK(ref stream, ikData, 1f);

                float3 rootToTip    = math.normalize(stream.GetLocalToRootTranslation(k_TipIndex) - stream.GetLocalToRootTranslation(k_RootIndex));
                float3 rootToTarget = math.normalize(ikData.Target.pos - stream.GetLocalToRootTranslation(k_RootIndex));

                Assert.That(rootToTarget, Is.EqualTo(rootToTip).Using(TranslationComparer));
            }

            buffer.Dispose();
        }
            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();
            }
            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();
            }
        public void PositionConstraintInfluencedByWeight()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var posConstraintData = Core.PositionConstraintData.Default();

            posConstraintData.Index           = 1;
            posConstraintData.SourcePositions = new NativeArray <float3>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            posConstraintData.SourceOffsets   = new NativeArray <float3>(1, Allocator.Temp, NativeArrayOptions.ClearMemory);
            posConstraintData.SourceWeights   = new NativeArray <float>(1, Allocator.Temp, NativeArrayOptions.ClearMemory);

            posConstraintData.SourcePositions[0] = new float3(0f, 0f, 2f);
            posConstraintData.SourceWeights[0]   = 1f;

            var defaultPos = stream.GetLocalToRootTranslation(posConstraintData.Index);

            for (int i = 0; i < 6; ++i)
            {
                float w = i / 5f;

                AnimationStreamUtils.SetDefaultValues(ref stream);
                Core.SolvePositionConstraint(ref stream, posConstraintData, w);

                float3 weightedPos = math.lerp(defaultPos, posConstraintData.SourcePositions[0], w);
                Assert.That(stream.GetLocalToRootTranslation(posConstraintData.Index), Is.EqualTo(weightedPos).Using(TranslationComparer));
            }

            buffer.Dispose();
            posConstraintData.SourcePositions.Dispose();
            posConstraintData.SourceOffsets.Dispose();
            posConstraintData.SourceWeights.Dispose();
        }
Esempio n. 8
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 == 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 RotationConstraintFollowsSources()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var rotConstraintData = Core.RotationConstraintData.Default();

            rotConstraintData.Index           = 1;
            rotConstraintData.SourceRotations = new NativeArray <quaternion>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            rotConstraintData.SourceOffsets   = new NativeArray <quaternion>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            rotConstraintData.SourceWeights   = new NativeArray <float>(2, Allocator.Temp, NativeArrayOptions.ClearMemory);

            for (int i = 0; i < 2; ++i)
            {
                rotConstraintData.SourceRotations[i] = quaternion.identity;
                rotConstraintData.SourceOffsets[i]   = quaternion.identity;
            }

            var defaultRot = stream.GetLocalToRootRotation(rotConstraintData.Index);

            // w0 = 0, w1 = 0
            Core.SolveRotationConstraint(ref stream, rotConstraintData, 1f);
            Assert.That(stream.GetLocalToRootRotation(rotConstraintData.Index), Is.EqualTo(defaultRot).Using(RotationComparer));

            // Set source rotations
            rotConstraintData.SourceRotations[0] = quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(70));
            rotConstraintData.SourceRotations[1] = quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(-20));

            // w0 = 1, w1 = 0
            AnimationStreamUtils.SetDefaultValues(ref stream);
            rotConstraintData.SourceWeights[0] = 1f;
            Core.SolveRotationConstraint(ref stream, rotConstraintData, 1f);
            Assert.That(stream.GetLocalToRootRotation(rotConstraintData.Index), Is.EqualTo(rotConstraintData.SourceRotations[0]).Using(RotationComparer));

            // w0 = 0, w1 = 1
            AnimationStreamUtils.SetDefaultValues(ref stream);
            rotConstraintData.SourceWeights[0] = 0f;
            rotConstraintData.SourceWeights[1] = 1f;
            Core.SolveRotationConstraint(ref stream, rotConstraintData, 1f);
            Assert.That(stream.GetLocalToRootRotation(rotConstraintData.Index), Is.EqualTo(rotConstraintData.SourceRotations[1]).Using(RotationComparer));

            // w0 = 1, w1 = 1
            AnimationStreamUtils.SetDefaultValues(ref stream);
            rotConstraintData.SourceWeights[0] = 1f;
            Core.SolveRotationConstraint(ref stream, rotConstraintData, 1f);

            var res = math.normalizesafe(mathex.add(rotConstraintData.SourceRotations[0].value * 0.5f, rotConstraintData.SourceRotations[1].value * 0.5f));

            Assert.That(stream.GetLocalToRootRotation(rotConstraintData.Index), Is.EqualTo(res).Using(RotationComparer));

            buffer.Dispose();
            rotConstraintData.SourceRotations.Dispose();
            rotConstraintData.SourceOffsets.Dispose();
            rotConstraintData.SourceWeights.Dispose();
        }
Esempio n. 11
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                var stream = AnimationStream.Create(data.RigDefinition, context.Resolve(ref ports.Output));

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

                data.ProfilerMarker.Begin();
                AnimationStreamUtils.SetDefaultValues(ref stream);
                data.ProfilerMarker.End();
            }
        public void PositionConstraintFollowsSources()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var posConstraintData = Core.PositionConstraintData.Default();

            posConstraintData.Index           = 1;
            posConstraintData.SourcePositions = new NativeArray <float3>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            posConstraintData.SourceOffsets   = new NativeArray <float3>(2, Allocator.Temp, NativeArrayOptions.ClearMemory);
            posConstraintData.SourceWeights   = new NativeArray <float>(2, Allocator.Temp, NativeArrayOptions.ClearMemory);

            posConstraintData.SourcePositions[0] = new float3(2f, 0f, 0f);
            posConstraintData.SourcePositions[1] = new float3(-2f, 0f, 0f);

            var defaultPos = stream.GetLocalToRootTranslation(posConstraintData.Index);

            // w0 = 0, w1 = 0
            Core.SolvePositionConstraint(ref stream, posConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(posConstraintData.Index), Is.EqualTo(defaultPos).Using(TranslationComparer));

            // w0 = 1, w1 = 0
            AnimationStreamUtils.SetDefaultValues(ref stream);
            posConstraintData.SourceWeights[0] = 1f;
            Core.SolvePositionConstraint(ref stream, posConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(posConstraintData.Index), Is.EqualTo(posConstraintData.SourcePositions[0]).Using(TranslationComparer));

            // w0 = 0, w1 = 1
            AnimationStreamUtils.SetDefaultValues(ref stream);
            posConstraintData.SourceWeights[0] = 0f;
            posConstraintData.SourceWeights[1] = 1f;
            Core.SolvePositionConstraint(ref stream, posConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(posConstraintData.Index), Is.EqualTo(posConstraintData.SourcePositions[1]).Using(TranslationComparer));

            // w0 = 1, w1 = 1
            // since source positions are mirrored, we should simply evaluate to origin.
            AnimationStreamUtils.SetDefaultValues(ref stream);
            posConstraintData.SourceWeights[0] = 1f;
            Core.SolvePositionConstraint(ref stream, posConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(posConstraintData.Index), Is.EqualTo(float3.zero).Using(TranslationComparer));

            buffer.Dispose();
            posConstraintData.SourcePositions.Dispose();
            posConstraintData.SourceOffsets.Dispose();
            posConstraintData.SourceWeights.Dispose();
        }
Esempio n. 13
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);
                }
            }
            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();
            }
        public void AimConstraintInfluencedByWeight()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var aimConstraintData = Core.AimConstraintData.Default();

            aimConstraintData.Index           = 1;
            aimConstraintData.LocalAimAxis    = new float3(1f, 0f, 0f);
            aimConstraintData.SourcePositions = new NativeArray <float3>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            aimConstraintData.SourceOffsets   = new NativeArray <quaternion>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            aimConstraintData.SourceWeights   = new NativeArray <float>(1, Allocator.Temp, NativeArrayOptions.ClearMemory);

            RigidTransform defaultTx;

            stream.GetLocalToRootTR(aimConstraintData.Index, out defaultTx.pos, out defaultTx.rot);

            aimConstraintData.SourcePositions[0] = defaultTx.pos + new float3(1f, 3f, 0f);
            aimConstraintData.SourceOffsets[0]   = quaternion.identity;
            aimConstraintData.SourceWeights[0]   = 1f;

            float          angle = 180f;
            RigidTransform constrainedTx;

            for (int i = 0; i < 6; ++i)
            {
                float w = i / 5f;

                AnimationStreamUtils.SetDefaultValues(ref stream);
                Core.SolveAimConstraint(ref stream, aimConstraintData, w);

                stream.GetLocalToRootTR(aimConstraintData.Index, out constrainedTx.pos, out constrainedTx.rot);
                float3 currAim = math.mul(constrainedTx.rot, aimConstraintData.LocalAimAxis);
                float3 src0Dir = math.normalize(aimConstraintData.SourcePositions[0] - constrainedTx.pos);

                float test = mathex.angle(currAim, src0Dir);
                Assert.Less(test, angle, "Angle between currAim and src0Dir should be smaller than last evaluation since constraint weight is greater");
                angle = test;
            }
        }
        public void ParentConstraintInfluencedByWeight()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var parentConstraintData = Core.ParentConstraintData.Default();

            parentConstraintData.Index         = 1;
            parentConstraintData.SourceTx      = new NativeArray <RigidTransform>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            parentConstraintData.SourceOffsets = new NativeArray <RigidTransform>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            parentConstraintData.SourceWeights = new NativeArray <float>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            RigidTransform defaultTx;

            stream.GetLocalToRootTR(parentConstraintData.Index, out defaultTx.pos, out defaultTx.rot);

            parentConstraintData.SourceTx[0]      = new RigidTransform(mathex.mul(defaultTx.rot, quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(60))), defaultTx.pos + new float3(0f, 0f, 1f));
            parentConstraintData.SourceOffsets[0] = RigidTransform.identity;
            parentConstraintData.SourceWeights[0] = 1f;

            for (int i = 0; i < 6; ++i)
            {
                float w = i / 5f;

                AnimationStreamUtils.SetDefaultValues(ref stream);
                Core.SolveParentConstraint(ref stream, parentConstraintData, w);

                float3     weightedPos = math.lerp(defaultTx.pos, parentConstraintData.SourceTx[0].pos, w);
                quaternion weightedRot = mathex.lerp(defaultTx.rot, parentConstraintData.SourceTx[0].rot, w);

                Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(weightedPos).Using(TranslationComparer));
                Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(weightedRot).Using(RotationComparer));
            }

            buffer.Dispose();
            parentConstraintData.SourceTx.Dispose();
            parentConstraintData.SourceOffsets.Dispose();
            parentConstraintData.SourceWeights.Dispose();
        }
        public void TwoBoneIKInfluencedByWeight()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var ikData = Core.TwoBoneIKData.Default();

            ikData.RootIndex   = k_RootIndex;
            ikData.MidIndex    = k_MidIndex;
            ikData.TipIndex    = k_TipIndex;
            ikData.LimbLengths = new float2(
                math.distance(stream.GetLocalToRootTranslation(k_RootIndex), stream.GetLocalToRootTranslation(k_MidIndex)),
                math.distance(stream.GetLocalToRootTranslation(k_MidIndex), stream.GetLocalToRootTranslation(k_TipIndex)));

            ikData.Target.pos = new float3(2f, 0.5f, 0f);
            var tipPos1 = stream.GetLocalToRootTranslation(k_TipIndex);

            Core.SolveTwoBoneIK(ref stream, ikData, 1f);
            var tipPos2 = stream.GetLocalToRootTranslation(k_TipIndex);

            for (int i = 0; i < 6; ++i)
            {
                float w = i / 5f;

                AnimationStreamUtils.SetDefaultValues(ref stream);
                Core.SolveTwoBoneIK(ref stream, ikData, w);

                float3 weightedTipPos = math.lerp(tipPos1, tipPos2, w);
                float3 tipPos         = stream.GetLocalToRootTranslation(k_TipIndex);

                Assert.That(weightedTipPos, Is.EqualTo(tipPos).Using(TranslationComparer));
            }

            buffer.Dispose();
        }
Esempio n. 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();
            }
        public void RotationConstraintInfluencedByWeight()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var rotConstraintData = Core.RotationConstraintData.Default();

            rotConstraintData.Index           = 1;
            rotConstraintData.SourceRotations = new NativeArray <quaternion>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            rotConstraintData.SourceOffsets   = new NativeArray <quaternion>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            rotConstraintData.SourceWeights   = new NativeArray <float>(1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            rotConstraintData.SourceRotations[0] = quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(80));
            rotConstraintData.SourceOffsets[0]   = quaternion.identity;
            rotConstraintData.SourceWeights[0]   = 1f;

            var defaultRot = stream.GetLocalToRootRotation(rotConstraintData.Index);

            for (int i = 0; i < 6; ++i)
            {
                float w = i / 5f;

                AnimationStreamUtils.SetDefaultValues(ref stream);
                Core.SolveRotationConstraint(ref stream, rotConstraintData, w);

                quaternion weightedRot = mathex.lerp(defaultRot, rotConstraintData.SourceRotations[0], w);
                Assert.That(stream.GetLocalToRootRotation(rotConstraintData.Index), Is.EqualTo(weightedRot).Using(RotationComparer));
            }

            buffer.Dispose();
            rotConstraintData.SourceRotations.Dispose();
            rotConstraintData.SourceOffsets.Dispose();
            rotConstraintData.SourceWeights.Dispose();
        }
Esempio n. 20
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();
            }
        public void ParentConstraintFollowsSources()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var parentConstraintData = Core.ParentConstraintData.Default();

            parentConstraintData.Index         = 1;
            parentConstraintData.SourceTx      = new NativeArray <RigidTransform>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            parentConstraintData.SourceOffsets = new NativeArray <RigidTransform>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            parentConstraintData.SourceWeights = new NativeArray <float>(2, Allocator.Temp, NativeArrayOptions.ClearMemory);

            for (int i = 0; i < 2; ++i)
            {
                parentConstraintData.SourceTx[i]      = RigidTransform.identity;
                parentConstraintData.SourceOffsets[i] = RigidTransform.identity;
            }

            RigidTransform defaultTx;

            stream.GetLocalToRootTR(parentConstraintData.Index, out defaultTx.pos, out defaultTx.rot);

            // w0 = 0, w1 = 0
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(defaultTx.pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(defaultTx.rot).Using(RotationComparer));

            // Displace sources
            parentConstraintData.SourceTx[0] = new RigidTransform(mathex.mul(defaultTx.rot, quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(-90))), defaultTx.pos + new float3(0f, 1f, 0f));
            parentConstraintData.SourceTx[1] = new RigidTransform(mathex.mul(defaultTx.rot, quaternion.AxisAngle(new float3(0f, 0f, 1f), math.radians(60))), defaultTx.pos + new float3(0f, 0f, 1f));

            // w0 = 1, w1 = 0
            parentConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[0].pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[0].rot).Using(RotationComparer));

            // w0 = 0, w1 = 1
            parentConstraintData.SourceWeights[0] = 0f;
            parentConstraintData.SourceWeights[1] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[1].pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(parentConstraintData.SourceTx[1].rot).Using(RotationComparer));

            // w0 = 1, w1 = 1
            parentConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveParentConstraint(ref stream, parentConstraintData, 1f);

            var posRes = (parentConstraintData.SourceTx[0].pos + parentConstraintData.SourceTx[1].pos) * 0.5f;
            var rotRes = math.normalizesafe(mathex.add(parentConstraintData.SourceTx[0].rot.value * 0.5f, parentConstraintData.SourceTx[1].rot.value * 0.5f));

            Assert.That(stream.GetLocalToRootTranslation(parentConstraintData.Index), Is.EqualTo(posRes).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(parentConstraintData.Index), Is.EqualTo(rotRes).Using(RotationComparer));

            buffer.Dispose();
            parentConstraintData.SourceTx.Dispose();
            parentConstraintData.SourceOffsets.Dispose();
            parentConstraintData.SourceWeights.Dispose();
        }
        public void AimConstraintFollowsSources()
        {
            var buffer = new NativeArray <AnimatedData>(m_Rig.Value.Bindings.StreamSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var stream = AnimationStream.Create(m_Rig, buffer);

            AnimationStreamUtils.SetDefaultValues(ref stream);

            var aimConstraintData = Core.AimConstraintData.Default();

            aimConstraintData.Index           = 1;
            aimConstraintData.LocalAimAxis    = new float3(1f, 0f, 0f);
            aimConstraintData.SourcePositions = new NativeArray <float3>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            aimConstraintData.SourceOffsets   = new NativeArray <quaternion>(2, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            aimConstraintData.SourceWeights   = new NativeArray <float>(2, Allocator.Temp, NativeArrayOptions.ClearMemory);

            RigidTransform defaultTx;

            stream.GetLocalToRootTR(aimConstraintData.Index, out defaultTx.pos, out defaultTx.rot);

            aimConstraintData.SourcePositions[0] = defaultTx.pos + new float3(1f, 3f, 0f);
            aimConstraintData.SourcePositions[1] = defaultTx.pos + new float3(1f, -3f, 0f);
            aimConstraintData.SourceOffsets[0]   = quaternion.identity;
            aimConstraintData.SourceOffsets[1]   = quaternion.identity;

            // w0 = 0, w1 = 0
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);
            Assert.That(stream.GetLocalToRootTranslation(aimConstraintData.Index), Is.EqualTo(defaultTx.pos).Using(TranslationComparer));
            Assert.That(stream.GetLocalToRootRotation(aimConstraintData.Index), Is.EqualTo(defaultTx.rot).Using(RotationComparer));

            // w0 = 1, w1 = 0
            aimConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);

            RigidTransform constrainedTx;

            stream.GetLocalToRootTR(aimConstraintData.Index, out constrainedTx.pos, out constrainedTx.rot);
            float3 currAim = math.mul(constrainedTx.rot, aimConstraintData.LocalAimAxis);
            float3 src0Dir = math.normalize(aimConstraintData.SourcePositions[0] - constrainedTx.pos);
            float3 src1Dir = math.normalize(aimConstraintData.SourcePositions[1] - constrainedTx.pos);

            Assert.AreEqual(0f, mathex.angle(currAim, src0Dir), k_Epsilon);
            Assert.AreNotEqual(0f, mathex.angle(currAim, src1Dir));

            // w0 = 0, w1 = 1
            aimConstraintData.SourceWeights[0] = 0f;
            aimConstraintData.SourceWeights[1] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);

            stream.GetLocalToRootTR(aimConstraintData.Index, out constrainedTx.pos, out constrainedTx.rot);
            currAim = math.mul(constrainedTx.rot, aimConstraintData.LocalAimAxis);
            src0Dir = math.normalize(aimConstraintData.SourcePositions[0] - constrainedTx.pos);
            src1Dir = math.normalize(aimConstraintData.SourcePositions[1] - constrainedTx.pos);
            Assert.AreNotEqual(0f, mathex.angle(currAim, src0Dir));
            Assert.AreEqual(0f, mathex.angle(currAim, src1Dir), k_Epsilon);

            // w0 = 1, w1 = 1
            // Since both sources are opposite, they should cancel each other out
            aimConstraintData.SourceWeights[0] = 1f;
            AnimationStreamUtils.SetDefaultValues(ref stream);
            Core.SolveAimConstraint(ref stream, aimConstraintData, 1f);

            stream.GetLocalToRootTR(aimConstraintData.Index, out constrainedTx.pos, out constrainedTx.rot);
            currAim = math.mul(constrainedTx.rot, aimConstraintData.LocalAimAxis);
            src0Dir = math.normalize(aimConstraintData.SourcePositions[0] - constrainedTx.pos);
            src1Dir = math.normalize(aimConstraintData.SourcePositions[1] - constrainedTx.pos);
            Assert.AreNotEqual(0f, mathex.angle(currAim, src0Dir));
            Assert.AreNotEqual(0f, mathex.angle(currAim, src1Dir));
            Assert.AreEqual(0f, mathex.angle(currAim, math.mul(defaultTx.rot, aimConstraintData.LocalAimAxis)), k_Epsilon);

            buffer.Dispose();
            aimConstraintData.SourcePositions.Dispose();
            aimConstraintData.SourceOffsets.Dispose();
            aimConstraintData.SourceWeights.Dispose();
        }