public static List <ClipSegments> GenerateSegments(Asset asset, out int numSegments, out int numFrames) { List <ClipSegments> segments = new List <ClipSegments>(); int destinationIndex = 0; numSegments = 0; numFrames = 0; foreach (var animationClip in asset.GetAnimationClips()) { ClipSegments clipSegments = new ClipSegments() { clip = animationClip, segments = GenerateSegments(asset, animationClip) }; numSegments += clipSegments.NumSegments; foreach (var segment in clipSegments.segments) { Assert.IsTrue(segment.source.FirstFrame >= 0); Assert.IsTrue(segment.source.OnePastLastFrame <= animationClip.NumFrames); int numFramesSource = segment.source.NumFrames; int numFramesDestination = animationClip.ClipFramesToAssetFrames(asset, numFramesSource); int onePastLastFrame = destinationIndex + numFramesDestination; numFrames += numFramesDestination; segment.destination = new Interval(destinationIndex, onePastLastFrame); destinationIndex += numFramesDestination; } segments.Add(clipSegments); } return(segments); }
public IEnumerator BuildTransforms() { // // Now re-sample all animations according to the target // sample rate and adjust the segment information to // reference the transforms array. // // // Calculate total number of poses to be generated // (based on previously generated segments) // int numJoints = rig.NumJoints; if (numJoints < 2) { throw new ArgumentException($"Rig does not have enough joints. Only {numJoints} present."); } if (numFrames == 0) { throw new Exception("No animation frame to process, please make sure there is at least one single non-empty tag in your Kinematica asset."); } int numTransforms = numFrames * numJoints; using (NativeArray <AffineTransform> transforms = new NativeArray <AffineTransform>(numTransforms, Allocator.Persistent)) { int globalSegmentIndex = 0; int destinationFrameIndex = 0; for (int clipIndex = 0; clipIndex < clipSegments.Count; ++clipIndex) { ClipSegments segments = clipSegments[clipIndex]; AnimationClip clip = segments.Clip.GetOrLoadClipSync(); using (AnimationSampler animSampler = new AnimationSampler(rig, clip)) { float sourceSampleRate = clip.frameRate; float targetSampleRate = asset.SampleRate; float sampleRateRatio = sourceSampleRate / targetSampleRate; int numFrameResampledClip = (int)math.ceil(targetSampleRate * segments.Clip.DurationInSeconds); for (int segmentIndex = 0; segmentIndex < segments.NumSegments; ++segmentIndex, ++globalSegmentIndex) { Segment segment = segments[segmentIndex]; int firstFrame = Missing.roundToInt(segment.source.FirstFrame / sampleRateRatio); firstFrame = math.min(firstFrame, numFrameResampledClip - 1); SampleRange sampleRange = new SampleRange() { startFrameIndex = firstFrame, numFrames = segment.destination.NumFrames }; using (AnimationSampler.RangeSampler rangeSampler = animSampler.PrepareRangeSampler(asset.SampleRate, sampleRange, destinationFrameIndex, transforms)) { rangeSampler.Schedule(); progressFeedback?.Invoke(new ProgressInfo() { title = $"Sample clip {clip.name}", progress = (float)globalSegmentIndex / numSegments }); while (!rangeSampler.IsComplete) { yield return(null); if (bCancel) { rangeSampler.Complete(); yield break; } } rangeSampler.Complete(); } destinationFrameIndex += segment.destination.NumFrames; } } } WriteTransformsToBinary(transforms); } }