SamplingTime GetOutputPlayTime(DebugMemory debugMemory, SamplingTime samplingTime, SamplingTime closestMatch, DebugIdentifier outputTimeIdentifier)
        {
            if (!closestMatch.IsValid)
            {
                return(samplingTime);
            }

            int playAtTimeTypeCode = BurstRuntime.GetHashCode32 <PlayAtTimeDebug>();

            for (DebugReference reference = debugMemory.FirstOrDefault; reference.IsValid; reference = debugMemory.Next(reference))
            {
                if (reference.identifier.typeHashCode != playAtTimeTypeCode)
                {
                    continue;
                }

                PlayAtTimeDebug playAtTime = debugMemory.ReadObject <PlayAtTimeDebug>(reference);
                if (playAtTime.playTime.Equals(outputTimeIdentifier))
                {
                    return(closestMatch);
                }
            }

            return(samplingTime);
        }
        public bool MatchPose(PoseSet candidates,
                              SamplingTime samplingTime,
                              MatchOptions options   = MatchOptions.None,
                              float maxPoseDeviation = -1.0f)
        {
            if ((options & MatchOptions.DontMatchIfCandidateIsPlaying) > 0 && IsTimeInSequences(samplingTime, candidates.sequences))
            {
                if ((options & MatchOptions.LoopSegment) > 0)
                {
                    LoopSegmentIfEndReached(samplingTime);
                }

                return(true);
            }

            DebugPushGroup();

            SamplingTime closestMatch = FindClosestPoseMatch(candidates, samplingTime, maxPoseDeviation);

            if (closestMatch.IsValid)
            {
                PlayAtTime(closestMatch);
                return(true);
            }
            else
            {
                if ((options & MatchOptions.LoopSegment) > 0)
                {
                    LoopSegmentIfEndReached(samplingTime);
                }

                return(false);
            }
        }
예제 #3
0
        /// <summary>
        /// Reads a sampling time from the buffer.
        /// </summary>
        /// <returns>The sampling time that has been read from the buffer.</returns>
        public static SamplingTime ReadSamplingTime(this Buffer buffer)
        {
            var theta     = buffer.ReadSingle();
            var timeIndex = buffer.ReadTimeIndex();

            return(SamplingTime.Create(timeIndex, theta));
        }
        public static float DrawFragment(ref MotionSynthesizer synthesizer, SamplingTime samplingTime, Color color, float timeOffset, AffineTransform anchorTransform)
        {
            Assert.IsTrue(samplingTime.IsValid);

            AnimationSampleTimeIndex animSampleTime = synthesizer.Binary.GetAnimationSampleTimeIndex(samplingTime.timeIndex);
            string animFrameTxt = $"{animSampleTime.clipName} frame {animSampleTime.animFrameIndex}";

            ref Binary binary = ref synthesizer.Binary;
        public float GetAverageTrajectorySpeed(SamplingTime samplingTime, float timeOffset)
        {
            float deltaTime = math.rcp(SampleRate);

            float trajectoryTimeSpan = deltaTime * 2.0f;

            return(math.length(GetTrajectoryVelocity(samplingTime, timeHorizon * timeOffset, trajectoryTimeSpan)));
        }
        public void LoopSegmentIfEndReached(SamplingTime samplingTime)
        {
            int numSegmentFrames = Binary.GetSegment(samplingTime.segmentIndex).destination.NumFrames;

            if (samplingTime.frameIndex == numSegmentFrames - 1)
            {
                PlayAtTime(SamplingTime.Create(TimeIndex.Create(samplingTime.segmentIndex)));
            }
        }
 internal static DeltaSamplingTime Create(SamplingTime samplingTime, AffineTransform deltaTransform, BlittableBool crossedBoundary)
 {
     return(new DeltaSamplingTime
     {
         crossedBoundary = crossedBoundary,
         samplingTime = samplingTime,
         deltaTransform = deltaTransform
     });
 }
            internal PoseFragment(ref Binary binary, MetricIndex metricIndex)
            {
                samplingTime = SamplingTime.Invalid;

                this.metricIndex = metricIndex;

                var numFeatures = GetNumFeatures(ref binary, metricIndex);

                array = new NativeArray <float3>(numFeatures, Allocator.Temp);
            }
        public unsafe SamplingTime FindClosestPoseMatch(PoseSet candidates,
                                                        SamplingTime samplingTime,
                                                        float maxPoseDeviation = -1.0f)
        {
            if (!samplingTime.IsValid)
            {
                return(SamplingTime.Create(SelectFirstPose(candidates.sequences)));
            }

            ref Binary binary = ref Binary;
        public string GetFragmentDebugText(SamplingTime samplingTime, string fragmentName, float speedTimeOffset = -1.0f)
        {
            AnimationSampleTimeIndex animSampleTime = GetAnimationSampleTimeIndex(samplingTime.timeIndex);

            if (!animSampleTime.IsValid)
            {
                return($"<b>{fragmentName}:</b> Invalid fragment");
            }

            string speedText = speedTimeOffset >= 0.0f ? $", <b>Speed:</b> {GetAverageTrajectorySpeed(samplingTime, speedTimeOffset):0.000} m/s" : "";

            return($"<b>{fragmentName}:</b> {animSampleTime.clipName}, <b>Frame:</b> {animSampleTime.animFrameIndex}{speedText}");
        }
        bool IsTimeInSequences(SamplingTime samplingTime, NativeArray <PoseSequence> sequences)
        {
            var numSequences = sequences.Length;

            for (int i = 0; i < sequences.Length; ++i)
            {
                Binary.SegmentIndex segmentIndex = Binary.GetInterval(sequences[i].intervalIndex).segmentIndex;
                if (samplingTime.segmentIndex == segmentIndex)
                {
                    return(true);
                }
            }

            return(false);
        }
        public void Draw(Camera camera, ref MotionSynthesizer synthesizer, DebugMemory debugMemory, SamplingTime debugSamplingTime, ref DebugDrawOptions options)
        {
            if (!playTime.IsValid)
            {
                return;
            }

            SamplingTime samplingTime = debugMemory.ReadObjectFromIdentifier <SamplingTime>(playTime);
            string       text         = synthesizer.Binary.GetFragmentDebugText(samplingTime, "Play Clip", options.timeOffset);

            DebugDraw.SetMovableTextTitle(options.textWindowIdentifier, "Play At Time");
            DebugDraw.AddMovableTextLine(options.textWindowIdentifier, text, options.inputOutputFragTextColor);

            DebugDraw.DrawFragment(ref synthesizer, samplingTime, options.inputOutputFragmentColor, options.timeOffset, synthesizer.WorldRootTransform);
        }
예제 #13
0
        public void Update(AffineTransform worldRootTransform, SamplingTime samplingTime, float deltaTime)
        {
            Assert.IsTrue(samplingTime.IsValid);

            //
            // Sample target pose into temporary buffer
            //

            var targetPose = SamplePoseAt(samplingTime);

            //
            // Trigger transition if requested
            //

            TriggerTransition(ref targetPose.Ref, previousDeltaTime);

            ref var binary = ref Binary;
예제 #14
0
        /// <summary>
        /// Switches the pose generation stream to read
        /// from the sampling time passed as argument.
        /// </summary>
        /// <remarks>
        /// Animation poses are always generated continuously
        /// based on a time index. This method allows to switch
        /// to a new starting time. The motion synthesizer automatically
        /// handles any discrepancies between the old and the new pose.
        /// </remarks>
        /// <param name="samplingTime">New sampling time for the pose generation.</param>
        public void PlayAtTime(SamplingTime samplingTime)
        {
            DebugWriteBlittableObject(ref samplingTime);
            PlayAtTimeDebug playAtTimeDebug = new PlayAtTimeDebug()
            {
                playTime = samplingTime.debugIdentifier
            };

            DebugWriteBlittableObject(ref playAtTimeDebug);

            samplingTime.debugIdentifier = DebugIdentifier.Invalid;

            if (updateInProgress)
            {
                delayedPushTime = samplingTime.timeIndex;
            }
            else
            {
                ref Binary binary = ref Binary;

                if (!binary.IsValid(samplingTime))
                {
                    throw new ArgumentException("Invalid sampling time passed as argument");
                }

                if (!Time.timeIndex.Equals(samplingTime.timeIndex))
                {
                    this.samplingTime = samplingTime;

                    poseGenerator.TriggerTransition();
                }

                Assert.IsTrue(binary.IsValid(Time));

                lastSamplingTime = TimeIndex.Invalid;
            }
예제 #15
0
 /// <summary>
 /// Advances a sampling time by a certain amount of time.
 /// </summary>
 /// <remarks>
 /// This method advances a starting time by a certain amount of time.
 /// <para>
 /// It is valid to pass a negative delta time in order to step
 /// backward in time.
 /// </para>
 /// <para>
 /// The resulting time can belong to a different segment if boundary
 /// clips have been configured for the segment that the initial time
 /// belongs to.
 /// </para>
 /// <para>
 /// The resulting new sampling time will be clamped at segment boundaries
 /// if no boundary clips have been defined for the segment that the initial time belongs to.
 /// </para>
 /// </remarks>
 /// <param name="samplingTime">The reference time to advance from.</param>
 /// <param name="deltaTime">The time increment to advance by in seconds.</param>
 /// <returns>The resulting sampling time.</returns>
 public DeltaSamplingTime Advance(SamplingTime samplingTime, float deltaTime)
 {
     ref var segment = ref GetSegment(samplingTime.segmentIndex);
예제 #16
0
 /// <summary>
 /// Switches the pose generation stream to read
 /// from the time index passed as argument.
 /// </summary>
 /// <remarks>
 /// Animation poses are always generated continuously
 /// based on a sampling time. This method allows to switch
 /// to a new starting time. The motion synthesizer automatically
 /// handles any discrepancies between the old and the new pose.
 /// </remarks>
 /// <param name="timeIndex">New starting time index for the pose generation.</param>
 public void PlayAtTime(TimeIndex timeIndex)
 {
     PlayAtTime(
         SamplingTime.Create(
             timeIndex, Time.theta));
 }
        internal string GetFragmentDebugText(ref MotionSynthesizer synthesizer, string fragmentName, SamplingTime time, float timeOffset, ref DeviationTable deviationTable, bool addCost = true)
        {
            Assert.IsTrue(time.IsValid);

            string text = synthesizer.Binary.GetFragmentDebugText(time, fragmentName, timeOffset);

            if (!addCost)
            {
                return(text);
            }


            string costInfo = GetCostInformation(ref synthesizer.Binary, ref deviationTable, time);

            if (!string.IsNullOrEmpty(costInfo))
            {
                text = text + costInfo;
            }

            return(text);
        }
예제 #18
0
 public void Draw(Camera camera, ref MotionSynthesizer synthesizer, DebugMemory debugMemory, SamplingTime debugSamplingTime, ref DebugDrawOptions options)
 {
     ref var binary = ref synthesizer.Binary;
        string GetCostInformation(ref Binary binary, ref DeviationTable deviationTable, SamplingTime samplingTime)
        {
            if (!deviationTable.IsValid || !samplingTime.IsValid)
            {
                return("");
            }

            DeviationScore deviation = deviationTable.GetDeviation(ref binary, samplingTime.timeIndex);

            if (!deviation.IsValid)
            {
                return($"\nThis fragment wasn't considered during the query");
            }

            if (deviation.trajectoryDeviation >= 0.0f)
            {
                return($"\n<b>Pose cost:</b> {deviation.poseDeviation:0.000}, <b>Trajectory:</b> {deviation.trajectoryDeviation:0.000}, <b>Total:</b> {deviation.poseDeviation + deviation.trajectoryDeviation:0.000}");
            }
            else
            {
                return($"\n<b>Pose cost:</b> {deviation.poseDeviation:0.000}");
            }
        }
예제 #20
0
 public void Draw(Camera camera, ref MotionSynthesizer synthesizer, DebugMemory debugMemory, SamplingTime debugSamplingTime, ref DebugDrawOptions options)
 {
     DrawPath();
 }
        public bool MatchPoseAndTrajectory(PoseSet candidates,
                                           SamplingTime samplingTime,
                                           Trajectory trajectory,
                                           MatchOptions options         = MatchOptions.None,
                                           float trajectoryWeight       = 0.6f,
                                           float minTrajectoryDeviation = 0.03f,
                                           float maxTotalDeviation      = -1.0f)
        {
            if ((options & MatchOptions.DontMatchIfCandidateIsPlaying) > 0 && IsTimeInSequences(samplingTime, candidates.sequences))
            {
                if ((options & MatchOptions.LoopSegment) > 0)
                {
                    LoopSegmentIfEndReached(samplingTime);
                }

                return(true);
            }


            if (!trajectory.debugIdentifier.IsValid)
            {
                DebugPushGroup();
                DebugWriteUnblittableObject(ref trajectory);
            }

            DebugWriteUnblittableObject(ref candidates);
            DebugWriteBlittableObject(ref samplingTime);


            SamplingTime closestMatch = FindClosestPoseAndTrajectoryMatch(candidates, samplingTime, trajectory, trajectoryWeight, maxTotalDeviation);

            if (closestMatch.IsValid)
            {
                bool validMatch = true;
                if (minTrajectoryDeviation >= 0.0f)
                {
                    float trajectoryDeviation = RelativeDeviation(closestMatch.timeIndex, trajectory);
                    validMatch = trajectoryDeviation >= minTrajectoryDeviation;

                    SamplingTime outputTime = closestMatch;
                    outputTime.debugIdentifier = DebugIdentifier.Invalid;
                    DebugWriteBlittableObject(ref outputTime, true);

                    TrajectoryHeuristicDebug heuristicDebug = new TrajectoryHeuristicDebug()
                    {
                        desiredTrajectory      = trajectory.debugIdentifier,
                        candidate              = samplingTime.debugIdentifier,
                        closestMatch           = closestMatch.debugIdentifier,
                        outputTime             = outputTime.debugIdentifier,
                        trajectoryDeviation    = trajectoryDeviation,
                        minTrajectoryDeviation = minTrajectoryDeviation
                    };
                    DebugWriteBlittableObject(ref heuristicDebug);

                    closestMatch = outputTime;
                }

                if (validMatch)
                {
                    PlayAtTime(closestMatch);
                    return(true);
                }
            }

            if ((options & MatchOptions.LoopSegment) > 0)
            {
                LoopSegmentIfEndReached(samplingTime);
            }

            return(false);
        }
        public void Draw(Camera camera, ref MotionSynthesizer synthesizer, DebugMemory debugMemory, SamplingTime debugSamplingTime, ref DebugDrawOptions options)
        {
            int fragmentSlot = 0;

            DebugDraw.SetMovableTextTitle(options.textWindowIdentifier, DebugWindowTitle);

            DeviationTable deviationTable = this.deviationTable.IsValid ? debugMemory.ReadObjectFromIdentifier <DeviationTable>(this.deviationTable) : DeviationTable.CreateInvalid();

            SamplingTime samplingTime = GetSamplingTime(debugMemory, this.samplingTime);

            if (samplingTime.IsValid)
            {
                if ((options.drawFlags & DebugDrawFlags.InputFragment) > 0)
                {
                    DebugDraw.DrawFragment(ref synthesizer, samplingTime, options.inputOutputFragmentColor, options.timeOffset, synthesizer.WorldRootTransform);
                    ++fragmentSlot;
                }
                DebugDraw.AddMovableTextLine(options.textWindowIdentifier, GetFragmentDebugText(ref synthesizer, "Input Clip", samplingTime, options.timeOffset, ref deviationTable), options.inputOutputFragTextColor);
            }

            SamplingTime    closestMatch         = GetSamplingTime(debugMemory, this.closestMatch);
            DebugIdentifier outputTimeIdentifier = this.closestMatch;

            if (closestMatch.IsValid)
            {
                if ((options.drawFlags & DebugDrawFlags.BestFragment) > 0)
                {
                    DebugDraw.DrawFragment(ref synthesizer, closestMatch, options.bestFragmentColor, options.timeOffset, GetAnchor(synthesizer.WorldRootTransform, fragmentSlot++ *options.distanceOffset, camera));

                    DebugDraw.AddMovableTextLine(options.textWindowIdentifier, GetFragmentDebugText(ref synthesizer, "Best Match Fragment", closestMatch, options.timeOffset, ref deviationTable), options.bestFragTextColor);
                    if (maxDeviation >= 0.0f)
                    {
                        string deviationMsg = GetDeviationText();
                        DebugDraw.AddMovableTextLine(options.textWindowIdentifier, deviationMsg, options.bestFragTextColor);
                    }

                    Nullable <TrajectoryHeuristicDebug> trajectoryHeuristic = FindTrajectoryHeuristic(debugMemory);
                    if (trajectoryHeuristic.HasValue)
                    {
                        trajectoryHeuristic.Value.DrawDebugText(ref options);

                        outputTimeIdentifier = trajectoryHeuristic.Value.outputTime;
                    }
                }
            }

            SamplingTime outputTime = GetOutputPlayTime(debugMemory, samplingTime, closestMatch, outputTimeIdentifier);

            if ((options.drawFlags & DebugDrawFlags.OutputFragment) > 0)
            {
                DebugDraw.DrawFragment(ref synthesizer, outputTime, options.inputOutputFragmentColor, options.timeOffset, GetAnchor(synthesizer.WorldRootTransform, fragmentSlot++ *options.distanceOffset, camera));
                DebugDraw.AddMovableTextLine(options.textWindowIdentifier, GetFragmentDebugText(ref synthesizer, "Output Clip", outputTime, options.timeOffset, ref deviationTable, false), options.inputOutputFragTextColor);
            }

            if (debugSamplingTime.IsValid)
            {
                if ((options.drawFlags & DebugDrawFlags.SelectedFragment) > 0)
                {
                    int slot = fragmentSlot > 0 ? -1 : 0;
                    DebugDraw.DrawFragment(ref synthesizer, debugSamplingTime, options.selectedFragmentColor, options.timeOffset, GetAnchor(synthesizer.WorldRootTransform, slot * options.distanceOffset, camera));
                    DebugDraw.AddMovableTextLine(options.textWindowIdentifier, GetFragmentDebugText(ref synthesizer, "Selected Clip", debugSamplingTime, options.timeOffset, ref deviationTable), options.selectedFragTextColor);
                }
            }

            deviationTable.Dispose();

            if ((options.drawFlags & DebugDrawFlags.Trajectory) > 0 && this.trajectory.IsValid)
            {
                using (Trajectory trajectory = debugMemory.ReadObjectFromIdentifier <Trajectory>(this.trajectory))
                {
                    Binary.TrajectoryFragmentDisplay.Options trajectoryOptions = Binary.TrajectoryFragmentDisplay.Options.Create();

                    DebugExtensions.DebugDrawTrajectory(synthesizer.WorldRootTransform,
                                                        trajectory,
                                                        synthesizer.Binary.SampleRate,
                                                        options.inputTrajectoryColor,
                                                        options.inputTrajectoryColor,
                                                        trajectoryOptions.showForward);
                }
            }
        }
 /// <summary>
 /// Writes a sampling time to the buffer.
 /// </summary>
 /// <param name="samplingTime">The sampling time that should be written to the buffer.</param>
 public static void Write(this Buffer buffer, SamplingTime samplingTime)
 {
     buffer.Write(samplingTime.theta);
     buffer.Write(samplingTime.timeIndex);
 }