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(); }
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(); }
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(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(); }
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(); }
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(); }