Esempio n. 1
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 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();
        }
            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 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 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 ctx, KernelData data, ref KernelDefs ports)
            {
                var input  = ctx.Resolve(ports.Input);
                var output = ctx.Resolve(ref ports.Output);

                if (input.Length != output.Length)
                {
                    throw new InvalidOperationException($"AimConstrainNode: Input Length '{input.Length}' doesn't match Output Length '{output.Length}'");
                }

                data.ProfilerMarker.Begin();

                output.CopyFrom(input);
                var stream = AnimationStream.Create(data.RigDefinition, output);

                if (stream.IsNull)
                {
                    throw new ArgumentNullException($"AimConstrainNode: Invalid output stream");
                }

                var srcPositionPorts = ctx.Resolve(ports.SourcePositions);
                var srcOffsetPorts   = ctx.Resolve(ports.SourceOffsets);
                var srcWeightPorts   = ctx.Resolve(ports.SourceWeights);

                if (srcPositionPorts.Length != srcOffsetPorts.Length || srcOffsetPorts.Length != srcWeightPorts.Length)
                {
                    throw new ArgumentException($"AimConstrainNode: SourcePositions, SourceOffsets and SourceWeights sizes must be the same");
                }

                var srcPositionArray = new NativeArray <float3>(srcPositionPorts.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                var srcOffsetArray   = new NativeArray <quaternion>(srcOffsetPorts.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                var srcWeightArray   = new NativeArray <float>(srcWeightPorts.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

                srcPositionPorts.CopyTo(srcPositionArray);
                srcOffsetPorts.CopyTo(srcOffsetArray);
                srcWeightPorts.CopyTo(srcWeightArray);

                var localOffset     = ctx.Resolve(ports.LocalOffset);
                var localOffsetQuat = math.lengthsq(localOffset) > 0f ?
                                      quaternion.Euler(localOffset, ctx.Resolve(ports.LocalOffsetRotationOrder)) : quaternion.identity;

                var constraintData = new Core.AimConstraintData
                {
                    Index           = data.Index,
                    LocalOffset     = localOffsetQuat,
                    LocalAimAxis    = data.LocalAimAxis,
                    LocalAxesMask   = data.LocalAxesMask,
                    MinAngleLimit   = math.radians(ctx.Resolve(ports.MinAngleLimit)),
                    MaxAngleLimit   = math.radians(ctx.Resolve(ports.MaxAngleLimit)),
                    SourcePositions = srcPositionArray,
                    SourceOffsets   = srcOffsetArray,
                    SourceWeights   = srcWeightArray
                };

                Core.SolveAimConstraint(ref stream, constraintData, ctx.Resolve(ports.Weight));

                data.ProfilerMarker.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();
        }
        unsafe public static AnimationStream CreateReadOnly(BlobAssetReference <RigDefinition> rig, NativeArray <AnimatedData> buffer)
        {
            if (rig == default || buffer.Length == 0 || buffer.Length != rig.Value.Bindings.StreamSize)
            {
                return(AnimationStream.Null);
            }

            return(AnimationStream.Create(rig, buffer.GetUnsafeReadOnlyPtr()));
        }
Esempio n. 13
0
            public void Execute(RenderContext ctx, KernelData data, ref KernelDefs ports)
            {
                var input  = ctx.Resolve(ports.Input);
                var output = ctx.Resolve(ref ports.Output);

                if (input.Length != output.Length)
                {
                    throw new InvalidOperationException($"ParentConstrainNode: Input Length '{input.Length}' doesn't match Output Length '{output.Length}'");
                }

                data.ProfilerMarker.Begin();

                output.CopyFrom(input);
                var stream = AnimationStream.Create(data.RigDefinition, output);

                if (stream.IsNull)
                {
                    throw new ArgumentNullException("ParentConstrainNode: Invalid output stream");
                }

                var srcTxPorts     = ctx.Resolve(ports.SourceTx);
                var srcOffsetPorts = ctx.Resolve(ports.SourceOffsets);
                var srcWeightPorts = ctx.Resolve(ports.SourceWeights);

                if (srcTxPorts.Length != srcOffsetPorts.Length || srcOffsetPorts.Length != srcWeightPorts.Length)
                {
                    throw new ArgumentException("ParentConstrainNode: SourceTx, SourceOffsets and SourceWeights sizes must be the same");
                }

                var srcTxArray     = new NativeArray <RigidTransform>(srcTxPorts.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                var srcOffsetArray = new NativeArray <RigidTransform>(srcOffsetPorts.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                var srcWeightArray = new NativeArray <float>(srcWeightPorts.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

                srcWeightPorts.CopyTo(srcWeightArray);

                // TODO: Optimize
                for (int i = 0; i < srcTxPorts.Length; ++i)
                {
                    srcTxArray[i]     = math.RigidTransform(srcTxPorts[i]);
                    srcOffsetArray[i] = math.RigidTransform(srcOffsetPorts[i]);
                }

                var constraintData = new Core.ParentConstraintData
                {
                    Index = data.Index,
                    LocalTranslationAxesMask = data.LocalTranslationAxesMask,
                    LocalRotationAxesMask    = data.LocalRotationAxesMask,
                    SourceTx      = srcTxArray,
                    SourceOffsets = srcOffsetArray,
                    SourceWeights = srcWeightArray
                };

                Core.SolveParentConstraint(ref stream, constraintData, ctx.Resolve(ports.Weight));

                data.ProfilerMarker.End();
            }
Esempio n. 14
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();
        }
            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(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();
            }
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($"MixerBeginNode Output is invalid.");
                }

                data.ProfileMixerBegin.Begin();

                Core.MixerBegin(ref outputStream);

                context.Resolve(ref ports.SumWeight) = 0.0f;

                data.ProfileMixerBegin.End();
            }
Esempio n. 19
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($"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();
            }
        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 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();
            }
Esempio n. 25
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();
            }
Esempio n. 26
0
            public void Execute(RenderContext context, KernelData data, ref KernelDefs ports)
            {
                if (data.RigDefinition == default)
                {
                    throw new System.InvalidOperationException($"ClipNode has invalid RigDefinition.");
                }

                if (data.ClipInstance == default)
                {
                    throw new System.InvalidOperationException($"ClipNode has invalid Clip.");
                }

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

                if (outputStream.IsNull)
                {
                    return;
                }

                data.ProfileSampleClip.Begin();
                Core.EvaluateClip(data.ClipInstance, context.Resolve(ports.Time), ref outputStream, data.Additive);
                data.ProfileSampleClip.End();
            }
            public void Execute(RenderContext ctx, KernelData data, ref KernelDefs ports)
            {
                var input  = ctx.Resolve(ports.Input);
                var output = ctx.Resolve(ref ports.Output);

                if (input.Length != output.Length)
                {
                    throw new InvalidOperationException($"TwoBoneIKNode: Input Length '{input.Length}' does not match Output Length '{output.Length}'");
                }

                data.ProfilerMarker.Begin();

                output.CopyFrom(input);
                var stream = AnimationStream.Create(data.RigDefinition, output);

                if (stream.IsNull)
                {
                    throw new ArgumentNullException("TwoBoneIKNode: Invalid output stream");
                }

                var ikData = new Core.TwoBoneIKData
                {
                    RootIndex            = data.RootIndex,
                    MidIndex             = data.MidIndex,
                    TipIndex             = data.TipIndex,
                    TargetOffset         = data.TargetOffset,
                    LimbLengths          = data.LimbLengths,
                    Target               = new RigidTransform(ctx.Resolve(ports.Target)),
                    Hint                 = ctx.Resolve(ports.Hint),
                    TargetPositionWeight = ctx.Resolve(ports.TargetPositionWeight),
                    TargetRotationWeight = ctx.Resolve(ports.TargetRotationWeight),
                    HintWeight           = ctx.Resolve(ports.HintWeight)
                };

                Core.SolveTwoBoneIK(ref stream, ikData, ctx.Resolve(ports.Weight));
                data.ProfilerMarker.End();
            }
        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. 29
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();
        }