From cc0eb1f877ca54cc509f7442cb0a010494928044 Mon Sep 17 00:00:00 2001 From: George Wu Date: Sat, 22 Aug 2020 10:11:49 +0200 Subject: [PATCH] [MillionDance] Respect frame rate scaling of camera and dance in appeals (#38) --- src/MillionDance/Core/MvdCreator.Camera.cs | 38 +++++++++++++--------- src/MillionDance/Core/VmdCreator.Dance.cs | 29 ++++++++++------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/MillionDance/Core/MvdCreator.Camera.cs b/src/MillionDance/Core/MvdCreator.Camera.cs index 3b97ef6..d2ccb37 100644 --- a/src/MillionDance/Core/MvdCreator.Camera.cs +++ b/src/MillionDance/Core/MvdCreator.Camera.cs @@ -65,13 +65,14 @@ private MvdCameraFrame[] CreateFrames([NotNull] CharacterImasMotionAsset mainCam var cameraFrameList = new List(); - var appealTimes = AppealHelper.CollectAppealTimeInfo(baseScenario); + var appealTimes = appealType != AppealType.None ? AppealHelper.CollectAppealTimeInfo(baseScenario) : default; + var transform60FpsTo30Fps = _conversionConfig.Transform60FpsTo30Fps; var scaleToVmdSize = _conversionConfig.ScaleToVmdSize; var unityToVmdScale = _scalingConfig.ScaleUnityToVmd; for (var mltdFrameIndex = 0; mltdFrameIndex < animationFrameCount; ++mltdFrameIndex) { - if (_conversionConfig.Transform60FpsTo30Fps) { + if (transform60FpsTo30Fps) { if (mltdFrameIndex % 2 == 1) { continue; } @@ -81,14 +82,6 @@ private MvdCameraFrame[] CreateFrames([NotNull] CharacterImasMotionAsset mainCam var shouldUseAppeal = appealType != AppealType.None && (appealTimes.StartFrame <= mltdFrameIndex && mltdFrameIndex < appealTimes.EndFrame) && appealAnimation != null; var animation = shouldUseAppeal ? appealAnimation : mainAnimation; - int mvdFrameIndex; - - if (_conversionConfig.Transform60FpsTo30Fps) { - mvdFrameIndex = mltdFrameIndex / 2; - } else { - mvdFrameIndex = mltdFrameIndex; - } - int projectedFrameIndex; if (shouldUseAppeal) { @@ -98,16 +91,29 @@ private MvdCameraFrame[] CreateFrames([NotNull] CharacterImasMotionAsset mainCam indexInAppeal = appealAnimation.FrameCount - 1; } - projectedFrameIndex = indexInAppeal; + // `indexInAppeal`, unlike `mltdFrameIndex`, has not been scaled yet + if (transform60FpsTo30Fps) { + projectedFrameIndex = indexInAppeal / 2; + } else { + projectedFrameIndex = indexInAppeal; + } } else { projectedFrameIndex = mltdFrameIndex; } - var frame = animation.CameraFrames[projectedFrameIndex]; + var motionFrame = animation.CameraFrames[projectedFrameIndex]; + + int mvdFrameIndex; + + if (transform60FpsTo30Fps) { + mvdFrameIndex = mltdFrameIndex / 2; + } else { + mvdFrameIndex = mltdFrameIndex; + } var mvdFrame = new MvdCameraFrame(mvdFrameIndex); - var position = new Vector3(frame.PositionX, frame.PositionY, frame.PositionZ); + var position = new Vector3(motionFrame.PositionX, motionFrame.PositionY, motionFrame.PositionZ); position = position.FixUnityToMmd(); @@ -117,7 +123,7 @@ private MvdCameraFrame[] CreateFrames([NotNull] CharacterImasMotionAsset mainCam mvdFrame.Position = position; - var target = new Vector3(frame.TargetX, frame.TargetY, frame.TargetZ); + var target = new Vector3(motionFrame.TargetX, motionFrame.TargetY, motionFrame.TargetZ); target = target.FixUnityToMmd(); @@ -131,12 +137,12 @@ private MvdCameraFrame[] CreateFrames([NotNull] CharacterImasMotionAsset mainCam var q = CameraOrientation.QuaternionLookAt(in position, in target, in Vector3.UnitY); - var rotation = CameraOrientation.ComputeMmdOrientation(in q, frame.AngleZ); + var rotation = CameraOrientation.ComputeMmdOrientation(in q, motionFrame.AngleZ); mvdFrame.Rotation = rotation; // MVD has good support of dynamic FOV. So here we can animate its value. - var fov = FocalLengthToFov(frame.FocalLength); + var fov = FocalLengthToFov(motionFrame.FocalLength); mvdFrame.FieldOfView = MathHelper.DegreesToRadians(fov); cameraFrameList.Add(mvdFrame); diff --git a/src/MillionDance/Core/VmdCreator.Dance.cs b/src/MillionDance/Core/VmdCreator.Dance.cs index 67660eb..aa410a6 100644 --- a/src/MillionDance/Core/VmdCreator.Dance.cs +++ b/src/MillionDance/Core/VmdCreator.Dance.cs @@ -110,36 +110,39 @@ private VmdBoneFrame[] CreateBoneFrames([NotNull] IBodyAnimationSource mainDance var lastSoughtFrame = -1; // OK, now perform iterations - for (var naturalFrameIndex = 0; naturalFrameIndex < resultFrameCount; ++naturalFrameIndex) { + for (var mltdFrameIndex = 0; mltdFrameIndex < resultFrameCount; ++mltdFrameIndex) { if (transform60FpsTo30Fps) { - if (naturalFrameIndex % 2 == 1) { + if (mltdFrameIndex % 2 == 1) { continue; } } - var shouldUseAppeal = appealType != AppealType.None && (appealTimes.StartFrame <= naturalFrameIndex && naturalFrameIndex < appealTimes.EndFrame) && appealAnimation != null; + var shouldUseAppeal = appealType != AppealType.None && (appealTimes.StartFrame <= mltdFrameIndex && mltdFrameIndex < appealTimes.EndFrame) && appealAnimation != null; var animation = shouldUseAppeal ? appealAnimation : mainAnimation; - int keyFrameIndexStart; + int projectedFrameIndex; if (shouldUseAppeal) { - var indexInAppeal = naturalFrameIndex - appealTimes.StartFrame; + var indexInAppeal = mltdFrameIndex - appealTimes.StartFrame; if (indexInAppeal >= appealAnimation.FrameCount) { indexInAppeal = appealAnimation.FrameCount - 1; } - keyFrameIndexStart = indexInAppeal * animatedBoneCount; + // `indexInAppeal`, unlike `mltdFrameIndex`, has not been scaled yet + if (transform60FpsTo30Fps) { + projectedFrameIndex = indexInAppeal / 2; + } else { + projectedFrameIndex = indexInAppeal; + } } else { - var actualFrameIndex = CalculateSeekFrameTarget(naturalFrameIndex, seekFrameControls, ref lastSoughtFrame, ref seekFrameCounter); - - keyFrameIndexStart = actualFrameIndex * animatedBoneCount; + projectedFrameIndex = CalculateSeekFrameTarget(mltdFrameIndex, seekFrameControls, ref lastSoughtFrame, ref seekFrameCounter); } var formationList = shouldUseAppeal ? appealFormationList : baseFormationList; - formationList.TryGetCurrentValue(naturalFrameIndex, out var formations); + formationList.TryGetCurrentValue(mltdFrameIndex, out var formations); Vector4 idolOffset; @@ -149,6 +152,8 @@ private VmdBoneFrame[] CreateBoneFrames([NotNull] IBodyAnimationSource mainDance idolOffset = formations[formationNumber - 1]; } + var keyFrameIndexStart = projectedFrameIndex * animatedBoneCount; + for (var j = 0; j < animatedBoneCount; ++j) { var keyFrame = animation.KeyFrames[keyFrameIndexStart + j]; var mltdBoneName = GetMltdBoneNameWithoutBodyScale(boneNameCache, keyFrame); @@ -278,9 +283,9 @@ private VmdBoneFrame[] CreateBoneFrames([NotNull] IBodyAnimationSource mainDance int vmdFrameIndex; if (_conversionConfig.Transform60FpsTo30Fps) { - vmdFrameIndex = naturalFrameIndex / 2; + vmdFrameIndex = mltdFrameIndex / 2; } else { - vmdFrameIndex = naturalFrameIndex; + vmdFrameIndex = mltdFrameIndex; } var mltdBoneName = GetMltdBoneNameWithoutBodyScale(boneNameCache, mltdBone.Path);