Skip to content

Commit

Permalink
[MillionDance] Fix motions for MMD (part of #30)
Browse files Browse the repository at this point in the history
  • Loading branch information
hozuki committed Aug 8, 2020
1 parent 3c1dad9 commit 3ccae57
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 16 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ Export models, dance animations, morphs and camera motions to MMD equivalents. I

[Manual](https://github.com/OpenMLTD/MLTDTools/wiki/MillionDance-Manual)

Output animation data can be played in [MikuMikuMoving](https://sites.google.com/site/mikumikumovingeng/) (MMM) but not [MikuMikuDance](http://www.geocities.jp/higuchuu4/index_e.htm) (MMD) because the number of frames is huge due to technical limitations.
Animation conversion seems to fail only when you load the output with MMD; maybe I'll investigate this issue some day. Also, MMM takes much less time reading such big files.
Output animation data can be played in either [MikuMikuDance](http://www.geocities.jp/higuchuu4/index_e.htm) (MMD) or [MikuMikuMoving](https://sites.google.com/site/mikumikumovingeng/) (MMM). But, the number of frames is huge due to technical limitations.
MMM is much faster reading motions with large amount of frames. *Don't feed MMD with motions converted in 60 fps. It simply hangs for a long time and then crashes.*

**MLTD Dance Viewer**

Expand Down
45 changes: 31 additions & 14 deletions src/MillionDance/Core/VmdCreator.BoneAnimation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using AssetStudio.Extended.CompositeModels;
using Imas.Data.Serialized;
using JetBrains.Annotations;
Expand Down Expand Up @@ -137,19 +138,7 @@ private VmdBoneFrame[] CreateBoneFrames([NotNull] IBodyAnimationSource mainDance

for (var j = 0; j < animatedBoneCount; ++j) {
var keyFrame = animation.KeyFrames[keyFrameIndexStart + j];
string mltdBoneName;

if (boneNameCache.ContainsKey(keyFrame.Path)) {
mltdBoneName = boneNameCache[keyFrame.Path];
} else {
if (keyFrame.Path.Contains(BoneLookup.BoneNamePart_BodyScale)) {
mltdBoneName = keyFrame.Path.Replace(BoneLookup.BoneNamePart_BodyScale, string.Empty);
} else {
mltdBoneName = keyFrame.Path;
}

boneNameCache.Add(keyFrame.Path, mltdBoneName);
}
var mltdBoneName = GetMltdBoneNameWithoutBodyScale(boneNameCache, keyFrame);

// Uniqueness is asserted above
var targetBone = mltdHierarchy.Find(bone => bone.Name == mltdBoneName);
Expand Down Expand Up @@ -281,10 +270,13 @@ private VmdBoneFrame[] CreateBoneFrames([NotNull] IBodyAnimationSource mainDance
vmdFrameIndex = naturalFrameIndex;
}

var mltdBoneName = GetMltdBoneNameWithoutBodyScale(boneNameCache, mltdBone.Path);
var vmdBoneName = boneLookup.GetVmdBoneNameFromBoneName(mltdBone.Path);
var boneFrame = new VmdBoneFrame(vmdFrameIndex, vmdBoneName);

boneFrame.Position = t;
var isMovable = BoneLookup.IsBoneMovable(mltdBoneName);

boneFrame.Position = isMovable ? t : Vector3.Zero;
boneFrame.Rotation = q;

boneFrameList.Add(boneFrame);
Expand All @@ -298,6 +290,31 @@ private VmdBoneFrame[] CreateBoneFrames([NotNull] IBodyAnimationSource mainDance
return boneFrameList.ToArray();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
[NotNull]
private static string GetMltdBoneNameWithoutBodyScale([NotNull] Dictionary<string, string> boneNameCache, [NotNull] KeyFrame keyFrame) {
return GetMltdBoneNameWithoutBodyScale(boneNameCache, keyFrame.Path);
}

[NotNull]
private static string GetMltdBoneNameWithoutBodyScale([NotNull] Dictionary<string, string> boneNameCache, [NotNull] string fullBonePath) {
string mltdBoneName;

if (boneNameCache.ContainsKey(fullBonePath)) {
mltdBoneName = boneNameCache[fullBonePath];
} else {
if (fullBonePath.Contains(BoneLookup.BoneNamePart_BodyScale)) {
mltdBoneName = fullBonePath.Replace(BoneLookup.BoneNamePart_BodyScale, string.Empty);
} else {
mltdBoneName = fullBonePath;
}

boneNameCache.Add(fullBonePath, mltdBoneName);
}

return mltdBoneName;
}

private static int CalculateSeekFrameTarget(int naturalFrameIndex, [NotNull] TimedList<int, int> seekFrameControls, ref int lastSoughtFrame, ref int seekFrameCounter) {
if (seekFrameControls.TryGetCurrentValue(naturalFrameIndex, out var targetFrame)) {
int result;
Expand Down

0 comments on commit 3ccae57

Please sign in to comment.