214 lines
7.0 KiB
C#

using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using Neo;
namespace UniversalEditor.ObjectModels.Multimedia3D.Model
{
public class ModelBone : ICloneable
{
public class ModelBoneCollection : Collection<ModelBone>
{
internal ModelObjectModel mvarParent = null;
public ModelBoneCollection(ModelObjectModel parent)
{
mvarParent = parent;
}
private Dictionary<string, ModelBone> bonesByName = new Dictionary<string, ModelBone>();
protected override void InsertItem(int index, ModelBone item)
{
if (!bonesByName.ContainsKey(item.Name))
{
bonesByName.Add(item.Name, item);
}
item.mvarParent = mvarParent;
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
string name = this[index].Name;
if (bonesByName.ContainsKey(name))
{
bonesByName.Remove(name);
}
this[index].mvarParent = null;
base.RemoveItem(index);
}
public ModelBone this[string Name]
{
get
{
if (bonesByName.ContainsKey(Name))
{
return bonesByName[Name];
}
return null;
}
}
}
private string mvarName = String.Empty;
public string Name { get { return mvarName; } set { mvarName = value; } }
private ModelBone mvarParentBone = null;
private ModelBone mvarChildBone = null;
private byte mvarCBRigidType = 0;
private short mvarIKNumber = 0;
private ModelAngleLimit mvarAngleLimit = new ModelAngleLimit();
public ModelAngleLimit AngleLimit { get { return mvarAngleLimit; } }
private PositionVector3 mvarOffset = default(PositionVector3);
public PositionVector3 Vector3Offset
{
get
{
return this.mvarOffset;
}
set
{
this.mvarOffset = value;
}
}
public ModelBone ParentBone { get { return mvarParentBone; } set { mvarParentBone = value; RecalculateOffset(); } }
public ModelBone ChildBone { get { return mvarChildBone; } set { mvarChildBone = value; } }
private PositionVector3 mvarPosition = default(PositionVector3);
public PositionVector3 Position
{
get { return mvarPosition; }
set { mvarPosition = value; }
}
private PositionVector4 mvarRotation = default(PositionVector4);
public PositionVector4 Rotation
{
get { return mvarRotation; }
set { mvarRotation = value; }
}
private PositionVector4 mvarOriginalRotation = default(PositionVector4);
public PositionVector4 OriginalRotation { get { return mvarOriginalRotation; } set { mvarOriginalRotation = value; } }
private PositionVector3 mvarOriginalPosition = default(PositionVector3);
public PositionVector3 OriginalPosition { get { return mvarOriginalPosition; } set { mvarOriginalPosition = value; UpdateInvTransformMatrix(); } }
private ModelBoneType mvarBoneType = ModelBoneType.Unknown;
public ModelBoneType BoneType { get { return mvarBoneType; } set { mvarBoneType = value; } }
public short IKNumber
{
get
{
return this.mvarIKNumber;
}
set
{
this.mvarIKNumber = value;
}
}
public object Clone()
{
ModelBone clone = new ModelBone();
#region Angle Limit
clone.AngleLimit.Enabled = mvarAngleLimit.Enabled;
clone.AngleLimit.Lower = (PositionVector3)mvarAngleLimit.Lower.Clone();
clone.AngleLimit.Upper = (PositionVector3)mvarAngleLimit.Upper.Clone();
#endregion
clone.ChildBone = mvarChildBone;
clone.IKNumber = mvarIKNumber;
clone.BoneType = mvarBoneType;
clone.Name = (mvarName.Clone() as string);
clone.ParentBone = mvarParentBone;
clone.Vector3Offset = (PositionVector3)mvarOffset.Clone();
clone.OriginalPosition = (PositionVector3)mvarOriginalPosition.Clone();
clone.OriginalRotation = (PositionVector4)mvarOriginalRotation.Clone();
clone.Position = (PositionVector3)mvarPosition.Clone();
clone.Rotation = (PositionVector4)mvarRotation.Clone();
return clone;
}
private ModelObjectModel mvarParent = null;
public ModelObjectModel Parent { get { return mvarParent; } }
private Matrix mvarLocalMatrix = new Matrix(4, 4);
private Matrix mvarSkinningMatrix = new Matrix(4, 4);
private Matrix mvarInvTransformMatrix = new Matrix(4, 4);
public Matrix GetLocalMatrix()
{
UpdateLocalMatrix();
return mvarLocalMatrix;
}
private void UpdateInvTransformMatrix()
{
mvarInvTransformMatrix = Matrix.Identity();
mvarInvTransformMatrix[3, 0] = -mvarOriginalPosition.X;
mvarInvTransformMatrix[3, 1] = -mvarOriginalPosition.Y;
mvarInvTransformMatrix[3, 2] = -mvarOriginalPosition.Z;
}
/// <summary>
/// ボーンの行列を更新。 Update the matrix of the bone.
/// </summary>
private void UpdateLocalMatrix()
{
// クォータニオンと移動値からボーンのローカルマトリックスを作成
// Create a local matrix of bones from quaternion value and move
mvarLocalMatrix = mvarRotation.ToMatrix();
mvarLocalMatrix[3, 0] = mvarPosition.X + mvarOffset.X;
mvarLocalMatrix[3, 1] = mvarPosition.Y + mvarOffset.Y;
mvarLocalMatrix[3, 2] = mvarPosition.Z + mvarOffset.Z;
// 親があるなら親の回転を受け継ぐE
// Inherit the rotation of the parent if there is a parent
if (mvarParentBone != null)
{
mvarLocalMatrix = mvarLocalMatrix * mvarParentBone.GetLocalMatrix();
}
}
/// <summary>
/// スキニング用行列を更新。 Update the matrix for skinning.
/// </summary>
public void UpdateSkinningMatrix()
{
UpdateInvTransformMatrix();
mvarSkinningMatrix = mvarInvTransformMatrix * GetLocalMatrix();
}
public void Reset()
{
mvarPosition = mvarOriginalPosition;
mvarRotation = mvarOriginalRotation;
mvarLocalMatrix = Matrix.Identity();
mvarLocalMatrix[3, 0] = mvarOriginalPosition.X;
mvarLocalMatrix[3, 1] = mvarOriginalPosition.Y;
mvarLocalMatrix[3, 2] = mvarOriginalPosition.Z;
}
public Matrix GetSkinningMatrix()
{
UpdateSkinningMatrix();
return mvarSkinningMatrix;
}
public void RecalculateOffset()
{
if (mvarParentBone != null)
{
mvarOffset = mvarOriginalPosition - mvarParentBone.OriginalPosition;
}
else
{
mvarOffset = mvarOriginalPosition;
}
}
}
}