private void ProcessStreams(IReadOnlyList <StreamedFrame> streamFrames, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos) { float[] curveValues = new float[4]; for (int frameIndex = 1; frameIndex < streamFrames.Count - 2; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (int curveIndex = 0; curveIndex < frame.Curves.Count;) { StreamedCurveKey curve = frame.Curves[curveIndex]; if (!GetGenericBinding(bindings, curve.Index, out GenericBinding binding)) { curveIndex++; continue; } string path = GetCurvePath(tos, binding.Path); int dimension = binding.BindingType.GetDimension(); for (int key = 0; key < dimension; key++) { curveValues[key] = frame.Curves[curveIndex + key].Value; } AddComplexCurve(frame.Time, binding.BindingType, curveValues, 0, path); curveIndex += dimension; } } }
private void FindNextCurve(IReadOnlyList <StreamedFrame> streamFrames, int index, int currentFrameIndex, out int frameIndex, out int curveIndex) { for (frameIndex = currentFrameIndex + 1; frameIndex < streamFrames.Count; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (curveIndex = 0; curveIndex < frame.Curves.Count; curveIndex++) { StreamedCurveKey curve = frame.Curves[curveIndex]; if (curve.Index == index) { return; } } } // if there is no next curve, use current one frameIndex = currentFrameIndex; StreamedFrame currentFrame = streamFrames[currentFrameIndex]; for (curveIndex = 0; curveIndex < currentFrame.Curves.Count; curveIndex++) { StreamedCurveKey curve = currentFrame.Curves[curveIndex]; if (curve.Index == index) { return; } } throw new Exception($"There is no curve with index {index} in any of current or next frames"); }
private void ProcessStreams(IReadOnlyList <StreamedFrame> streamFrames, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos, float sampleRate) { float[] curveValues = new float[4]; float[] inSlopeValues = new float[4]; float[] outSlopeValues = new float[4]; float interval = 1.0f / sampleRate; // first (index [0]) stream frame is for slope calculation for the first real frame (index [1]) // last one (index [count - 1]) is +Infinity // it is made for slope processing, but we don't need them for (int frameIndex = 1; frameIndex < streamFrames.Count - 1; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (int curveIndex = 0; curveIndex < frame.Curves.Length;) { StreamedCurveKey curve = frame.Curves[curveIndex]; GenericBinding binding = bindings.FindBinding(curve.Index); string path = GetCurvePath(tos, binding.Path); if (binding.IsTransform) { GetPreviousFrame(streamFrames, curve.Index, frameIndex, out int prevFrameIndex, out int prevCurveIndex); int dimension = binding.TransformType.GetDimension(); for (int key = 0; key < dimension; key++) { StreamedCurveKey keyCurve = frame.Curves[curveIndex]; StreamedFrame prevFrame = streamFrames[prevFrameIndex]; StreamedCurveKey prevKeyCurve = prevFrame.Curves[prevCurveIndex + key]; float deltaTime = frame.Time - prevFrame.Time; curveValues[key] = keyCurve.Value; inSlopeValues[key] = prevKeyCurve.CalculateNextInSlope(deltaTime, keyCurve.Value); outSlopeValues[key] = keyCurve.OutSlope; curveIndex = GetNextCurve(frame, curveIndex); } AddTransformCurve(frame.Time, binding.TransformType, curveValues, inSlopeValues, outSlopeValues, 0, path); } else if (binding.CustomType == BindingCustomType.None) { AddDefaultCurve(binding, path, frame.Time, frame.Curves[curveIndex].Value); curveIndex = GetNextCurve(frame, curveIndex); } else { AddCustomCurve(bindings, binding, path, frame.Time, frame.Curves[curveIndex].Value); curveIndex = GetNextCurve(frame, curveIndex); } } } }
private int GetNextCurve(StreamedFrame frame, int currentCurve) { StreamedCurveKey curve = frame.Curves[currentCurve]; int i = currentCurve + 1; for (; i < frame.Curves.Length; i++) { if (frame.Curves[i].Index != curve.Index) { return(i); } } return(i); }
private void GetPreviousFrame(IReadOnlyList <StreamedFrame> streamFrames, int curveID, int currentFrame, out int frameIndex, out int curveIndex) { for (frameIndex = currentFrame - 1; frameIndex >= 0; frameIndex--) { StreamedFrame frame = streamFrames[frameIndex]; for (curveIndex = 0; curveIndex < frame.Curves.Length; curveIndex++) { StreamedCurveKey curve = frame.Curves[curveIndex]; if (curve.Index == curveID) { return; } } } throw new Exception($"There is no curve with index {curveID} in any of previous frames"); }
private void ProcessStreams(IReadOnlyList <StreamedFrame> streamFrames, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos) { float[] curveValues = new float[4]; float[] inSlopeValues = new float[4]; float[] outSlopeValues = new float[4]; // first (index [0]) stream frame is for slope calculation for the first real frame (index [1]) // last one (index [count - 1]) is +Infinity // it is made for slope processing, but we don't need them for (int frameIndex = 1; frameIndex < streamFrames.Count - 1; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (int curveIndex = 0; curveIndex < frame.Curves.Count;) { StreamedCurveKey curve = frame.Curves[curveIndex]; if (!GetGenericBinding(bindings, curve.Index, out GenericBinding binding)) { curveIndex++; continue; } //FindPreviousCurve(streamFrames, curve.Index, frameIndex, out int prevFrameIndex, out int prevCurveIndex); //FindNextCurve(streamFrames, curve.Index, frameIndex, out int nextFrameIndex, out int nextCurveIndex); string path = GetCurvePath(tos, binding.Path); int dimension = binding.BindingType.GetDimension(); for (int key = 0; key < dimension; key++) { StreamedCurveKey keyCurve = frame.Curves[curveIndex + key]; //StreamedFrame prevFrame = streamFrames[prevFrameIndex]; //StreamedFrame nextFrame = streamFrames[nextFrameIndex]; //StreamedCurveKey prevKeyCurve = prevFrame.Curves[prevCurveIndex + key]; //StreamedCurveKey nextKeyCurve = nextFrame.Curves[nextCurveIndex + key]; curveValues[key] = keyCurve.Value; #warning TODO: TCB to in/out slope //inSlopeValues[key] = prevKeyCurve.CalculateNextInTangent(keyCurve.Value, nextKeyCurve.Value); //outSlopeValues[key] = keyCurve.CalculateOutTangent(prevKeyCurve.Value, nextKeyCurve.Value); } AddComplexCurve(frame.Time, binding.BindingType, curveValues, inSlopeValues, outSlopeValues, 0, path); curveIndex += dimension; } } }
public IReadOnlyList <StreamedFrame> GenerateFrames(Version version, Platform platform, TransferInstructionFlags flags) { List <StreamedFrame> frames = new List <StreamedFrame>(); byte[] memStreamBuffer = new byte[m_data.Length * sizeof(uint)]; Buffer.BlockCopy(m_data, 0, memStreamBuffer, 0, memStreamBuffer.Length); using (MemoryStream stream = new MemoryStream(memStreamBuffer)) { using (AssetReader reader = new AssetReader(stream, version, platform, flags)) { while (reader.BaseStream.Position < reader.BaseStream.Length) { StreamedFrame frame = new StreamedFrame(); frame.Read(reader); frames.Add(frame); } } } return(frames); }
public IReadOnlyList <StreamedFrame> GenerateFrames(IAssetsExporter exporter) { List <StreamedFrame> frames = new List <StreamedFrame>(); byte[] memStreamBuffer = new byte[m_data.Length * sizeof(uint)]; Buffer.BlockCopy(m_data, 0, memStreamBuffer, 0, memStreamBuffer.Length); using (MemoryStream memStream = new MemoryStream(memStreamBuffer)) { using (AssetStream stream = new AssetStream(memStream, exporter.Version, exporter.Platform)) { while (stream.BaseStream.Position < stream.BaseStream.Length) { StreamedFrame frame = new StreamedFrame(); frame.Read(stream); frames.Add(frame); } } } return(frames); }
public IReadOnlyList <StreamedFrame> GenerateFrames() { List <StreamedFrame> frames = new List <StreamedFrame>(); byte[] memStreamBuffer = new byte[m_data.Length * sizeof(uint)]; Buffer.BlockCopy(m_data, 0, memStreamBuffer, 0, memStreamBuffer.Length); using (MemoryStream memStream = new MemoryStream(memStreamBuffer)) { using (EndianStream stream = new EndianStream(memStream, EndianType.LittleEndian)) { while (stream.BaseStream.Position < stream.BaseStream.Length) { StreamedFrame frame = new StreamedFrame(); frame.Read(stream); frames.Add(frame); } } } return(frames); }
public void ExportGenericData(IExportContainer container, YAMLMappingNode node, IReadOnlyDictionary <uint, string> tos) { StreamedClip streamedClip = MuscleClip.Clip.StreamedClip; DenseClip denseClip = MuscleClip.Clip.DenseClip; ConstantClip constantClip = MuscleClip.Clip.ConstantClip; IReadOnlyList <StreamedFrame> streamedFrames = streamedClip.GenerateFrames(container); Dictionary <uint, Vector3Curve> translations = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, QuaternionCurve> rotations = new Dictionary <uint, QuaternionCurve>(); Dictionary <uint, Vector3Curve> scales = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, Vector3Curve> eulers = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, FloatCurve> floats = new Dictionary <uint, FloatCurve>(); int frameCount = Math.Max(denseClip.FrameCount - 1, streamedFrames.Count - 2); float[] frameCurvesValue = new float[streamedClip.CurveCount]; for (int frame = 0, streamFrame = 1; frame < frameCount; frame++, streamFrame++) { bool isAdd = true; float time; StreamedFrame streamedFrame = new StreamedFrame(); if (streamFrame < streamedFrames.Count) { streamedFrame = streamedFrames[streamFrame]; time = streamedFrame.Time; } else { time = (float)frame / SampleRate; } bool isStreamFrame = streamFrame < (streamedFrames.Count - 1); bool isDenseFrame = frame < (denseClip.FrameCount - 1); // number of stream curves which has key in current frame int streamFrameCurveCount = isStreamFrame ? streamedFrame.Curves.Count : 0; int denseFrameCurveCount = (int)denseClip.CurveCount; // total amount of curves which has key in current frame int frameCurveCount = streamFrameCurveCount + denseFrameCurveCount + constantClip.Constants.Count; int streamOffset = (int)streamedClip.CurveCount - streamFrameCurveCount; for (int curve = 0; curve < frameCurveCount;) { int curveIndex; IReadOnlyList <float> curvesValue; int offset; if (isStreamFrame && curve < streamedFrame.Curves.Count) { #warning TODO: read TCB and convert to in/out slope for (int key = curve; key < Math.Min(curve + 5, streamedFrame.Curves.Count); key++) { frameCurvesValue[key] = streamedFrame.Curves[key].Value; } curveIndex = streamedFrame.Curves[curve].Index; curvesValue = frameCurvesValue; offset = 0; } else if (isDenseFrame && curve < streamFrameCurveCount + denseFrameCurveCount) { curveIndex = curve + streamOffset; curvesValue = denseClip.SampleArray; offset = streamFrameCurveCount - frame * denseFrameCurveCount; } else if (!isDenseFrame && curve < streamFrameCurveCount + denseFrameCurveCount) { curve += denseFrameCurveCount; curveIndex = curve + streamOffset; curvesValue = constantClip.Constants; offset = streamFrameCurveCount + denseFrameCurveCount; isAdd = frame == 0 || frame == frameCount - 1; } else { curveIndex = curve + streamOffset; curvesValue = constantClip.Constants; offset = streamFrameCurveCount + denseFrameCurveCount; isAdd = frame == 0 || frame == frameCount - 1; } GenericBinding binding = ClipBindingConstant.FindBinding(curveIndex); uint pathHash = binding.Path; if (pathHash == 0) { curve++; continue; } if (!tos.TryGetValue(pathHash, out string path)) { path = "dummy" + pathHash; //Logger.Log(LogType.Debug, LogCategory.Export, $"Can't find path '{binding.Path}' in TOS for {ToLogString()}"); } switch (binding.BindingType) { case BindingType.Translation: // HACK: TEMP: if (curve + 3 > curvesValue.Count) { curve += 3; break; } float x = curvesValue[curve++ - offset]; float y = curvesValue[curve++ - offset]; float z = curvesValue[curve++ - offset]; float w = 0; if (isAdd) { Vector3f trans = new Vector3f(x, y, z); if (!translations.TryGetValue(pathHash, out Vector3Curve transCurve)) { transCurve = new Vector3Curve(path); translations[pathHash] = transCurve; } Vector3f defWeight = new Vector3f(1.0f / 3.0f); KeyframeTpl <Vector3f> transKey = new KeyframeTpl <Vector3f>(time, trans, defWeight); transCurve.Curve.Curve.Add(transKey); } break; case BindingType.Rotation: // HACK: TEMP: if (curve + 4 > curvesValue.Count) { curve += 4; break; } x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; w = curvesValue[curve++ - offset]; if (isAdd) { Quaternionf rot = new Quaternionf(x, y, z, w); if (!rotations.TryGetValue(pathHash, out QuaternionCurve rotCurve)) { rotCurve = new QuaternionCurve(path); rotations[pathHash] = rotCurve; } Quaternionf defWeight = new Quaternionf(1.0f / 3.0f); KeyframeTpl <Quaternionf> rotKey = new KeyframeTpl <Quaternionf>(time, rot, defWeight); rotCurve.Curve.Curve.Add(rotKey); } break; case BindingType.Scaling: // HACK: TEMP: if (curve + 3 > curvesValue.Count) { curve += 3; break; } x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; if (isAdd) { Vector3f scale = new Vector3f(x, y, z); if (!scales.TryGetValue(pathHash, out Vector3Curve scaleCurve)) { scaleCurve = new Vector3Curve(path); scales[pathHash] = scaleCurve; } Vector3f defWeight = new Vector3f(1.0f / 3.0f); KeyframeTpl <Vector3f> scaleKey = new KeyframeTpl <Vector3f>(time, scale, defWeight); scaleCurve.Curve.Curve.Add(scaleKey); } break; case BindingType.EulerRotation: // HACK: TEMP: if (curve + 3 > curvesValue.Count) { curve += 3; break; } x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; if (isAdd) { Vector3f euler = new Vector3f(x, y, z); if (!eulers.TryGetValue(pathHash, out Vector3Curve eulerCurve)) { eulerCurve = new Vector3Curve(path); eulers[pathHash] = eulerCurve; } Vector3f defWeight = new Vector3f(1.0f / 3.0f); KeyframeTpl <Vector3f> eulerKey = new KeyframeTpl <Vector3f>(time, euler, defWeight); eulerCurve.Curve.Curve.Add(eulerKey); } break; case BindingType.Floats: float value = curvesValue[curve++ - offset]; if (isAdd) { Float @float = new Float(value); if (!floats.TryGetValue(pathHash, out FloatCurve floatCurve)) { floatCurve = new FloatCurve(path); floats[pathHash] = floatCurve; } Float defWeight = new Float(1.0f / 3.0f); KeyframeTpl <Float> floatKey = new KeyframeTpl <Float>(time, @float, defWeight); floatCurve.Curve.Curve.Add(floatKey); } break; default: #warning TODO: ??? curve++; //throw new NotImplementedException(binding.BindingType.ToString()); break; } } } node.Add("m_RotationCurves", rotations.Values.ExportYAML(container)); node.Add("m_CompressedRotationCurves", YAMLSequenceNode.Empty); node.Add("m_EulerCurves", eulers.Values.ExportYAML(container)); node.Add("m_PositionCurves", translations.Values.ExportYAML(container)); node.Add("m_ScaleCurves", scales.Values.ExportYAML(container)); node.Add("m_FloatCurves", floats.Values.ExportYAML(container)); }