Skip to content

Commit

Permalink
Merge branch 'release/1.0.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
paralleltree committed Nov 1, 2019
2 parents a81e48e + ad5e8b8 commit f6f97a0
Show file tree
Hide file tree
Showing 15 changed files with 239 additions and 18 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ var project = new Project().Load(@"path\to\project.pmm");
// project.Models...
```

var pose = new Pose().Load(@"path\to\pose.vpd");
// pose.Bones...

## Contributing

Bug reports and pull requests are welcome on [GitHub](https://github.com/paralleltree/Scallion).
Expand Down
2 changes: 1 addition & 1 deletion Scallion.Tests/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
[assembly: ComVisible(false)]
[assembly: Guid("2b69216b-f367-46a9-8d9b-56b16771019c")]

[assembly: AssemblyVersion("0.10.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
1 change: 1 addition & 0 deletions Scallion.Tests/Scallion.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
<Compile Include="Internal\NumericsExtensions.cs" />
<Compile Include="UnitTests\Core\MoSerializerTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UnitTests\DomainModels\InterpolationTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Scallion\Scallion.csproj">
Expand Down
31 changes: 31 additions & 0 deletions Scallion.Tests/UnitTests/DomainModels/InterpolationTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using NUnit.Framework;
using Scallion.DomainModels.Components;

namespace Scallion.Tests.UnitTests.DomainModels
{
[TestFixture]
internal class InterpolationTest
{
private object[] interpolationParams = new[]
{
new object[] { new InterpolationParameter(20, 20), new InterpolationParameter(107, 107), 0.2f, 0.2f },
new object[] { new InterpolationParameter(20, 20), new InterpolationParameter(107, 107), 0.7f, 0.7f },
new object[] { new InterpolationParameter(84, 84), new InterpolationParameter(10, 108), 0.3f, 0.402165f },
new object[] { new InterpolationParameter(84, 84), new InterpolationParameter(10, 108), 0.4f, 0.684518f },
};

[Test]
[TestCaseSource("interpolationParams")]
public void CalculateInterpolatedValueTest(InterpolationParameter first, InterpolationParameter second, float t, float y)
{
var interpolation = new Interpolation(first, second);
Assert.AreEqual(y, interpolation.GetInterpolatedValue(t), 1e-5);
}
}
}
14 changes: 7 additions & 7 deletions Scallion/DomainModels/Components/BoneReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public class BoneReference
public Model TargetModel { get; }

/// <summary>
/// Gets the parent bone of <see cref="TargetModel"/>.
/// The null value represents the root of model.
/// Gets the parent bone index of <see cref="TargetModel"/>.
/// The value "-1" represents the root of model.
/// </summary>
public Bone TargetBone { get; }
public int TargetBoneIndex { get; } = -1;

/// <summary>
/// Initializes a new instance of the <see cref="BoneReference"/> class.
Expand All @@ -31,13 +31,13 @@ public BoneReference()
/// Initializes a new instance of the <see cref="BoneReference"/> class from the model and bone.
/// </summary>
/// <param name="model">The parent model</param>
/// <param name="bone">The parent bone being a part of <paramref name="model"/></param>
public BoneReference(Model model, Bone bone)
/// <param name="boneIndex">The parent bone index of <paramref name="model"/></param>
public BoneReference(Model model, int boneIndex)
{
if (!model.Bones.Contains(bone))
if (boneIndex < -1 || boneIndex >= model.Bones.Count)
throw new ArgumentException("The collection of bones of model must contain the bone.");
TargetModel = model;
TargetBone = bone;
TargetBoneIndex = boneIndex;
}
}
}
24 changes: 24 additions & 0 deletions Scallion/DomainModels/Components/Interpolation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ public Interpolation(InterpolationParameter first, InterpolationParameter second
First = first;
Second = second;
}

/// <summary>
/// Get interpolated value using this interpolation.
/// </summary>
/// <param name="pos">The parameter moving from 0 to 1</param>
/// <returns>The interpolated value moving from 0 to 1</returns>
public float GetInterpolatedValue(float pos)
{
if (pos < 0 || pos > 1) throw new ArgumentOutOfRangeException("pos");
float f(float t, float p2, float p3) => 3 * (1 - t) * (1 - t) * t * p2 + 3 * (1 - t) * t * t * p3 + t * t * t;
float x2 = First.X / 127f;
float x3 = Second.X / 127f;
float upper = 1f;
float lower = 0;
for (int i = 0; i < 16; i++)
{
float x = (upper + lower) / 2;
float d = f(x, x2, x3) - pos;
if (Math.Abs(d) < 1e-6) break;
if (d < 0) lower = x;
else upper = x;
}
return f((upper + lower) / 2, First.Y / 127f, Second.Y / 127f);
}
}

/// <summary>
Expand Down
72 changes: 72 additions & 0 deletions Scallion/DomainModels/Pose.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;

using Scallion.Core;
using Scallion.DomainModels.Components;

namespace Scallion.DomainModels
{
/// <summary>
/// Represents MMD Pose File(.vpd).
/// </summary>
public class Pose : IMMDFile<Pose>
{
/// <summary>
/// Gets or sets the name of a model which the pose made for.
/// </summary>
public string ModelName { get; set; }

/// <summary>
/// Gets or sets a value of <see cref="BoneState"/> associated with the bone name.
/// <see cref="BoneState.Interpolation"/> and <see cref="BoneState.ExternalParent"/> in these values will be ignored.
/// </summary>
public Dictionary<string, BoneState> Bones { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="Pose"/> class.
/// </summary>
public Pose()
{
Bones = new Dictionary<string, BoneState>();
}

/// <summary>
/// Loads a pose from the specified file.
/// </summary>
/// <param name="path">The file path to load a pose</param>
/// <returns>The self instance assigned values from the file</returns>
/// <exception cref="ArgumentException">
/// Thrown when the specified file is invalid or unsupported file.
/// </exception>
public Pose Load(string path)
{
var raw = new Raw.Pose().Load(path);
ModelName = raw.ModelName;
Bones = raw.Bones.ToDictionary(p => p.Name, p => new BoneState()
{
Position = p.Position,
Quaternion = p.Quaternion
});
return this;
}

/// <summary>
/// Saves this pose to the specified file.
/// </summary>
/// <param name="path">The file path to save this pose</param>
public void Save(string path)
{
new Raw.Pose()
{
ModelName = this.ModelName,
Bones = Bones.Select(p => new Raw.Components.Pose.Bone()
{
Name = p.Key,
Position = p.Value.Position,
Quaternion = p.Value.Quaternion
}).ToList()
}.Save(path);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public DomainModels.Project Convert(Raw.Project src, DomainModels.Project obj)
{
Reference = reference.ModelIndex == -1 ? new BoneReference() : new BoneReference(
model: modeldic[reference.ModelIndex],
bone: reference.BoneIndex == -1 ? null : modeldic[reference.ModelIndex].Bones[reference.BoneIndex])
boneIndex: reference.BoneIndex)
},
IsSelected = keyframe.IsSelected
});
Expand Down Expand Up @@ -62,7 +62,7 @@ public DomainModels.Project Convert(Raw.Project src, DomainModels.Project obj)
var reference = model.ExternalParentStatuses[i].ExternalParent;
modeldic[model.Index].Bones[bone].CurrentStatus.ExternalParent = reference.ModelIndex == -1 ? new BoneReference() : new BoneReference(
model: modeldic[reference.ModelIndex],
bone: reference.BoneIndex == -1 ? null : modeldic[reference.ModelIndex].Bones[reference.BoneIndex]);
boneIndex: reference.BoneIndex);
}

// current ik
Expand Down Expand Up @@ -126,7 +126,7 @@ public Raw.Project ConvertBack(DomainModels.Project src, Raw.Project obj)
{
var reference = p.Value.Value.Reference;
return reference.TargetModel == null ? Raw.Components.Project.BoneReference.Empty :
new Raw.Components.Project.BoneReference(reference.TargetModel.Index, reference.TargetBone == null ? -1 : boneIndexDic[reference.TargetModel][reference.TargetBone]);
new Raw.Components.Project.BoneReference(reference.TargetModel.Index, reference.TargetBoneIndex);
}).ToList();
modelKeyFrames.Add(new Raw.Components.Project.ModelKeyFrame()
{
Expand All @@ -153,7 +153,7 @@ public Raw.Project ConvertBack(DomainModels.Project src, Raw.Project obj)
if (p == -1) return new Raw.Components.Project.ExternalParentState() { ExternalParent = Raw.Components.Project.BoneReference.Empty };
var reference = model.Bones[p].CurrentStatus.ExternalParent;
var indexRef = reference.TargetModel == null ? Raw.Components.Project.BoneReference.Empty :
new Raw.Components.Project.BoneReference(reference.TargetModel.Index, reference.TargetBone == null ? -1 : boneIndexDic[reference.TargetModel][reference.TargetBone]);
new Raw.Components.Project.BoneReference(reference.TargetModel.Index, reference.TargetBoneIndex);
return new Raw.Components.Project.ExternalParentState()
{
ExternalParent = indexRef,
Expand Down
4 changes: 2 additions & 2 deletions Scallion/Internal/Converters/Project/ProjectConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public DomainModels.Project Convert(Raw.Project src, DomainModels.Project obj)
BoneReference ResolveReference(Raw.Components.Project.BoneReference reference)
{
return reference.ModelIndex == -1 ? new BoneReference() :
new BoneReference(modeldic[reference.ModelIndex], modeldic[reference.ModelIndex].Bones[reference.BoneIndex]);
new BoneReference(modeldic[reference.ModelIndex], reference.BoneIndex);
}

// for bones
Expand Down Expand Up @@ -90,7 +90,7 @@ public Raw.Project ConvertBack(DomainModels.Project src, Raw.Project obj)
Raw.Components.Project.BoneReference ResolveReference(BoneReference reference)
{
return reference.TargetModel == null ? Raw.Components.Project.BoneReference.Empty :
new Raw.Components.Project.BoneReference(reference.TargetModel.Index, boneIndexDic[reference.TargetModel][reference.TargetBone]);
new Raw.Components.Project.BoneReference(reference.TargetModel.Index, reference.TargetBoneIndex);
}

new ModelKeyFrameConverter().ConvertBack(src, obj);
Expand Down
2 changes: 1 addition & 1 deletion Scallion/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[assembly: ComVisible(false)]
[assembly: Guid("3934e015-89f5-4214-80df-71b57f62c2cd")]

[assembly: AssemblyVersion("0.10.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]

// Exposes internal components to the testing project.
[assembly: InternalsVisibleTo("Scallion.Tests")]
15 changes: 15 additions & 0 deletions Scallion/Raw/Components/Pose/Bone.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;

using System.Numerics;

namespace Scallion.Raw.Components.Pose
{
internal class Bone
{
public string Name { get; set; }
public Vector3 Position { get; set; }
public Quaternion Quaternion { get; set; }
}
}
4 changes: 2 additions & 2 deletions Scallion/Raw/Motion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace Scallion.Raw
{
internal class Motion : MMDFile<Motion>
{
public readonly string Signature = "Vocaloid Motion Data 0002";
public readonly string CameraName = "カメラ・照明\0on Data";
public static readonly string Signature = "Vocaloid Motion Data 0002";
public static readonly string CameraName = "カメラ・照明\0on Data";

public string ModelName { get; set; }
public List<BoneKeyFrame> BoneKeyFrames { get; set; }
Expand Down
72 changes: 72 additions & 0 deletions Scallion/Raw/Pose.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

using System.Numerics;
using Scallion.Core;
using Scallion.Raw.Components.Pose;

namespace Scallion.Raw
{
internal class Pose : IMMDFile<Pose>
{
public static readonly string Signature = "Vocaloid Pose Data file";

public string ModelName { get; set; }
public List<Bone> Bones { get; set; }

public Pose Load(string path)
{
using (var reader = new StreamReader(path, Encoding.GetEncoding("shift_jis")))
{
if (Signature != reader.ReadLine())
throw new ArgumentException("Unsupported or invalid .vpd file");
reader.ReadLine();
ModelName = Regex.Match(reader.ReadLine(), @".*(?=\.osm)").Value;
int bonesCount = int.Parse(Regex.Match(reader.ReadLine(), @"\d+").Value);
reader.ReadLine();

Bones = new List<Bone>(bonesCount);
for (int i = 0; i < bonesCount; i++)
{
string name = Regex.Match(reader.ReadLine(), @"(?<={).*").Value;
float[] pos = Array.ConvertAll(Regex.Match(reader.ReadLine(), @"(?<=\s*).+(?=;)").Value.Split(','), float.Parse);
float[] q = Array.ConvertAll(Regex.Match(reader.ReadLine(), @"(?<=\s*).+(?=;)").Value.Split(','), float.Parse);
Bones.Add(new Bone()
{
Name = name,
Position = new Vector3(pos[0], pos[1], pos[2]),
Quaternion = new Quaternion(q[0], q[1], q[2], q[3])
});
reader.ReadLine();
reader.ReadLine();
}
}
return this;
}

public void Save(string path)
{
using (var writer = new StreamWriter(path, false, Encoding.GetEncoding("shift_jis")))
{
writer.WriteLine(Signature);
writer.WriteLine();
writer.WriteLine("{0}.osm;", ModelName);
writer.WriteLine("{0};", Bones.Count);
writer.WriteLine();
for (int i = 0; i < Bones.Count; i++)
{
writer.WriteLine(@"Bone{0}{{{1}", i, Bones[i].Name);
writer.WriteLine(" {0},{1},{2};", Bones[i].Position.X, Bones[i].Position.Y, Bones[i].Position.Z);
writer.WriteLine(" {0},{1},{2},{3};", Bones[i].Quaternion.X, Bones[i].Quaternion.Y, Bones[i].Quaternion.Z, Bones[i].Quaternion.W);
writer.WriteLine("}");
writer.WriteLine();
}
writer.WriteLine();
}
}
}
}
2 changes: 1 addition & 1 deletion Scallion/Raw/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Scallion.Raw
{
internal class Project : MMDFile<Project>
{
public readonly string Signature = "Polygon Movie maker 0002";
public static readonly string Signature = "Polygon Movie maker 0002";

public Size OutputSize { get; set; }
public int TimelinePanelWidth { get; set; }
Expand Down
3 changes: 3 additions & 0 deletions Scallion/Scallion.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="DomainModels\Components\SelfShadow.cs" />
<Compile Include="DomainModels\Components\KeyFrame.cs" />
<Compile Include="DomainModels\Components\View.cs" />
<Compile Include="DomainModels\Pose.cs" />
<Compile Include="DomainModels\Project.cs" />
<Compile Include="Internal\Converters\Motion\BoneConverter.cs" />
<Compile Include="Internal\Converters\Converter.cs" />
Expand Down Expand Up @@ -107,6 +108,7 @@
<Compile Include="Raw\Components\Motion\ModelKeyFrame.cs" />
<Compile Include="Raw\Components\Motion\MorphKeyFrame.cs" />
<Compile Include="Raw\Components\Motion\SelfShadowKeyFrame.cs" />
<Compile Include="Raw\Components\Pose\Bone.cs" />
<Compile Include="Raw\Components\Project\Accessory.cs" />
<Compile Include="Raw\Components\Project\BoneInterpolationImpl.cs" />
<Compile Include="Raw\Components\Project\BoneKeyFrame.cs" />
Expand All @@ -126,6 +128,7 @@
<Compile Include="Raw\Components\Project\SelfShadow.cs" />
<Compile Include="Raw\Components\Project\TimelinePanelState.cs" />
<Compile Include="Raw\Motion.cs" />
<Compile Include="Raw\Pose.cs" />
<Compile Include="Raw\Project.cs" />
</ItemGroup>
<ItemGroup>
Expand Down

0 comments on commit f6f97a0

Please sign in to comment.