// Set to binding pose ("T" pose) public static void SetToBindingPose([NotNull] this PmxBone bone) { if (bone.IsTransformCalculated) { return; } var parent = bone.Parent; Vector3 localPosition; if (parent == null) { localPosition = bone.InitialPosition; } else { parent.SetToBindingPose(); localPosition = bone.InitialPosition - parent.InitialPosition; } bone.LocalMatrix = CalculateTransform(localPosition, Quaternion.Identity); bone.WorldMatrix = bone.CalculateWorldMatrix(); bone.IsTransformCalculated = true; }
// https://github.com/sn0w75/MMP/blob/master/libmmp/motioncontroller.cpp internal static void SetToVmdPose([NotNull] this PmxBone bone) { if (bone.IsTransformCalculated) { return; } bone.CurrentRotation = bone.AnimatedRotation; var parent = bone.ParentBone; Vector3 localPosition; if (parent == null) { localPosition = bone.AnimatedTranslation + bone.InitialPosition; } else { parent.SetToVmdPose(); localPosition = bone.AnimatedTranslation + bone.InitialPosition - parent.InitialPosition; } bone.LocalMatrix = CalculateTransform(localPosition, bone.CurrentRotation); bone.WorldMatrix = bone.CalculateWorldMatrix(); bone.IsTransformCalculated = true; }
public void UpdateMatrix(int frame) { var pos = DxMath.Vector3.Zero; var rot = DxMath.Quaternion.Identity; foreach (var layer in MMMBone.Layers) { var data = layer.Frames.GetFrame(frame); pos += data.Position; rot *= data.Quaternion; } PmxBone.Pos = Pos = pos.Convert(); PmxBone.Rot = Rot = rot.Convert(); foreach (var bone in ParentBones) { bone.UpdateMatrix(frame); } PmxBone.UpdateLocalMatrix(); PmxBone.UpdateWorldMatrix(); LocalMat = PmxBone.LocalMat; CurrentWorldMat = new Matrix4(LocalCoordinate * PmxBone.WorldMat.Rotation, PmxBone.WorldMat.Translation); }
internal static void SetToVmdPose([NotNull] this PmxBone bone, bool forced = false) { if (!forced && bone.IsTransformCalculated) { return; } // Ignore append parent. bone.CurrentRotation = bone.AnimatedRotation; var parent = bone.Parent; Vector3 localPosition; if (parent == null) { localPosition = bone.AnimatedTranslation + bone.InitialPosition; } else { parent.SetToVmdPose(); localPosition = bone.AnimatedTranslation + bone.InitialPosition - parent.InitialPosition; } bone.LocalMatrix = CalculateTransform(localPosition, bone.CurrentRotation); bone.WorldMatrix = bone.CalculateWorldMatrix(); bone.SkinMatrix = bone.BindingPoseMatrixInverse * bone.WorldMatrix; bone.CurrentPosition = Vector3.TransformPosition(bone.InitialPosition, bone.SkinMatrix); bone.IsTransformCalculated = true; }
internal static void SetInitialRotationFromRotationAxes([NotNull] this PmxBone bone, Vector3 localX, Vector3 localY, Vector3 localZ) { var rotationMatrix = new Matrix3( localX.X, localX.Y, localX.Z, localY.X, localY.Y, localY.Z, localZ.X, localZ.Y, localZ.Z); bone.InitialRotation = Quaternion.FromMatrix(rotationMatrix); bone.CurrentRotation = bone.InitialRotation; }
private void WritePmxBone([NotNull] PmxBone bone) { WriteString(bone.Name); WriteString(bone.NameEnglish); _writer.Write(bone.InitialPosition); _writer.WriteInt32AsVarLenInt(bone.ParentIndex, BoneElementSize); _writer.Write(bone.Level); _writer.Write((ushort)bone.Flags); if (bone.HasFlag(BoneFlags.ToBone)) { _writer.WriteInt32AsVarLenInt(bone.To_Bone, BoneElementSize); } else { _writer.Write(bone.To_Offset); } if (bone.HasFlag(BoneFlags.AppendRotation) || bone.HasFlag(BoneFlags.AppendTranslation)) { _writer.WriteInt32AsVarLenInt(bone.AppendParentIndex, BoneElementSize); _writer.Write(bone.AppendRatio); } if (bone.HasFlag(BoneFlags.FixedAxis)) { _writer.Write(bone.Axis); } if (bone.HasFlag(BoneFlags.LocalFrame)) { var rotation = bone.InitialRotation; var mat = Matrix4.CreateFromQuaternion(rotation); var localX = mat.Row0.Xyz; var localZ = mat.Row2.Xyz; localX.Normalize(); localZ.Normalize(); _writer.Write(localX); _writer.Write(localZ); } if (bone.HasFlag(BoneFlags.ExternalParent)) { _writer.Write(bone.ExternalParentIndex); } if (bone.HasFlag(BoneFlags.IK) && bone.IK != null) { WritePmxIK(bone.IK); } }
public static void SetFlag([NotNull] this PmxBone bone, BoneFlags flags, bool set) { if (set) { SetFlag(bone, flags); } else { ClearFlag(bone, flags); } }
private static Matrix CalculateWorldMatrix([NotNull] this PmxBone bone) { if (bone.ParentBone != null) { return(bone.LocalMatrix * bone.ParentBone.WorldMatrix); } else { return(bone.LocalMatrix); } }
public static Matrix4 CalculateWorldMatrix([NotNull] this PmxBone bone) { if (bone.Parent == null) { return(bone.LocalMatrix); } else { return(bone.LocalMatrix * bone.Parent.WorldMatrix); } }
private void CreateBoneList() { for (int i = 0; i < this.boneList.Count; i++) { Transform bone = this.boneList[i]; PmxBone pmxBone = new PmxBone(); pmxBone.Name = bone.name; pmxBone.NameE = bone.name; if (this.boneParent[i] >= 0) { pmxBone.Parent = this.boneParent[i]; } UnityEngine.Vector3 vector = bone.position * scaleFactor; pmxBone.Position = ToPmxVec3(vector); this.pmxFile.BoneList.Add(pmxBone); } }
private void CreateBoneList() { List <PmxBone> pmxBoneList = pmxFile.BoneList; for (int i = 0; i < boneList.Count; i++) { Transform bone = boneList[i]; PmxBone pmxBone = new PmxBone(); pmxBone.Name = bone.name; pmxBone.NameE = bone.name; if (boneParent[i] >= 0) { pmxBone.Parent = boneParent[i]; } UnityEngine.Vector3 vector = bone.position * scaleFactor; pmxBone.Position = ToPmxVec3(vector); pmxBone.To_Offset = ToPmxVec3(bone.rotation * UnityEngine.Vector3.left * scaleFactor / 16f); if (bone.name.EndsWith("_SCL_") || bone.name.Contains("twist")) { pmxBone.SetFlag(PmxBone.BoneFlags.Visible, false); } pmxBoneList.Add(pmxBone); } for (int i = 0; i < pmxBoneList.Count; i++) { PmxBone pmxBone = pmxBoneList[i]; int children = 0; int lastChildIndex = -1; for (int j = 0; j < pmxBoneList.Count; j++) { PmxBone pmxOtherBone = pmxBoneList[j]; if (pmxOtherBone.Parent == i && pmxOtherBone.GetFlag(PmxBone.BoneFlags.Visible)) { children++; lastChildIndex = j; } } if (children == 1) { Debug.Log($"Pointing Bone {pmxBone.NameE} to {pmxBoneList[lastChildIndex].NameE}"); pmxBone.SetFlag(PmxBone.BoneFlags.ToBone, true); pmxBone.To_Bone = lastChildIndex; } } }
private PmxBone ReadPmxBone() { var bone = new PmxBone(); bone.Name = ReadString() ?? string.Empty; bone.NameEnglish = ReadString() ?? string.Empty; bone.InitialPosition = _reader.ReadVector3(); bone.CurrentPosition = bone.InitialPosition; bone.ParentIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); bone.Level = _reader.ReadInt32(); bone.Flags = (BoneFlags)_reader.ReadUInt16(); if (bone.HasFlag(BoneFlags.ToBone)) { bone.To_Bone = _reader.ReadVarLenIntAsInt32(BoneElementSize); } else { bone.To_Offset = _reader.ReadVector3(); } if (bone.HasFlag(BoneFlags.AppendRotation) || bone.HasFlag(BoneFlags.AppendTranslation)) { bone.AppendParentIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); bone.AppendRatio = _reader.ReadSingle(); } if (bone.HasFlag(BoneFlags.FixedAxis)) { bone.Axis = _reader.ReadVector3(); } if (bone.HasFlag(BoneFlags.LocalFrame)) { var localX = _reader.ReadVector3(); var localZ = _reader.ReadVector3(); localX.Normalize(); localZ.Normalize(); var localY = Vector3.Cross(localZ, localX); localZ = Vector3.Cross(localX, localY); localY.Normalize(); localZ.Normalize(); bone.SetInitialRotationFromRotationAxes(localX, localY, localZ); } else { bone.InitialRotation = Quaternion.Identity; bone.CurrentRotation = Quaternion.Identity; } if (bone.HasFlag(BoneFlags.ExternalParent)) { bone.ExternalParentIndex = _reader.ReadInt32(); } if (bone.HasFlag(BoneFlags.IK)) { bone.IK = ReadPmxIK(); } return(bone); }
public static void SetVmdAnimation([NotNull] this PmxBone bone, Vector3 vmdTranslation, Quaternion vmdRotation) { bone.AnimatedTranslation = vmdTranslation; bone.AnimatedRotation = vmdRotation; }
public static bool HasFlag([NotNull] this PmxBone bone, BoneFlags flags) { return((bone.Flags & flags) != 0); }
internal static void UpdateSkinMatrix([NotNull] this PmxBone bone) { bone.SkinMatrix = bone.BindPoseMatrixInverse * bone.WorldMatrix; bone.CurrentPosition = Vector3.Transform(bone.InitialPosition, bone.SkinMatrix); }
public static void ClearFlag([NotNull] this PmxBone bone, BoneFlags flags) { bone.Flags &= ~flags; }
public static void SetFlag([NotNull] this PmxBone bone, BoneFlags flags) { bone.Flags |= flags; }
private static IReadOnlyList <PmxBone> AddBones([NotNull] Avatar combinedAvatar, [NotNull] Mesh combinedMesh, [NotNull, ItemNotNull] IReadOnlyList <PmxVertex> vertices) { var boneCount = combinedAvatar.AvatarSkeleton.NodeIDs.Length; var bones = new List <PmxBone>(boneCount); var hierachy = BoneUtils.BuildBoneHierarchy(combinedAvatar); for (var i = 0; i < boneCount; ++i) { var bone = new PmxBone(); var transform = combinedAvatar.AvatarSkeletonPose.Transforms[i]; var boneNode = hierachy[i]; var pmxBoneName = BoneUtils.GetPmxBoneName(boneNode.Path); bone.Name = pmxBoneName; bone.NameEnglish = BoneUtils.TranslateBoneName(pmxBoneName); // PMX's bone positions are in world coordinate system. // Unity's are in local coords. bone.InitialPosition = boneNode.InitialPositionWorld; bone.CurrentPosition = bone.InitialPosition; bone.ParentIndex = boneNode.Parent?.Index ?? -1; bone.BoneIndex = i; var singleDirectChild = GetDirectSingleChildOf(boneNode); if (singleDirectChild != null) { bone.SetFlag(BoneFlags.ToBone); bone.To_Bone = singleDirectChild.Index; } else { // TODO: Fix this; it should point to a world position. bone.To_Offset = transform.Translation.ToOpenTK().FixUnityToOpenTK(); } // No use. This is just a flag to specify more details to rotation/translation limitation. //bone.SetFlag(BoneFlags.LocalFrame); bone.InitialRotation = transform.Rotation.ToOpenTK().FixUnityToOpenTK(); bone.CurrentRotation = bone.InitialRotation; //bone.Level = boneNode.Level; bone.Level = 0; if (BoneUtils.IsBoneMovable(boneNode.Path)) { bone.SetFlag(BoneFlags.Rotation | BoneFlags.Translation); } else { bone.SetFlag(BoneFlags.Rotation); } if (ConversionConfig.Current.HideUnityGeneratedBones) { if (BoneUtils.IsNameGenerated(boneNode.Path)) { bone.ClearFlag(BoneFlags.Visible); } } bones.Add(bone); } if (ConversionConfig.Current.FixMmdCenterBones) { // Add master (全ての親) and center (センター), recompute bone hierarchy. PmxBone master = new PmxBone(), center = new PmxBone(); master.Name = "全ての親"; master.NameEnglish = "master"; center.Name = "センター"; center.NameEnglish = "center"; master.ParentIndex = 0; // "" bone center.ParentIndex = 1; // "master" bone master.CurrentPosition = master.InitialPosition = Vector3.Zero; center.CurrentPosition = center.InitialPosition = Vector3.Zero; master.SetFlag(BoneFlags.Translation | BoneFlags.Rotation); center.SetFlag(BoneFlags.Translation | BoneFlags.Rotation); bones.Insert(1, master); bones.Insert(2, center); //// Fix "MODEL_00" bone //do { // var model00 = bones.Find(b => b.Name == "グルーブ"); // if (model00 == null) { // throw new ArgumentException("MODEL_00 mapped bone is not found."); // } // model00.ParentIndex = 2; // "center" bone //} while (false); const int numBonesAdded = 2; // Fix vertices and other bones foreach (var vertex in vertices) { foreach (var boneWeight in vertex.BoneWeights) { if (boneWeight.BoneIndex == 0 && boneWeight.Weight <= 0) { continue; } if (boneWeight.BoneIndex >= 1) { boneWeight.BoneIndex += numBonesAdded; } } } for (var i = numBonesAdded + 1; i < bones.Count; ++i) { var bone = bones[i]; bone.ParentIndex += numBonesAdded; if (bone.HasFlag(BoneFlags.ToBone)) { bone.To_Bone += numBonesAdded; } } } if (ConversionConfig.Current.AppendIKBones) { // Add IK bones. PmxBone[] CreateLegIK(string leftRightJp, string leftRightEn) { var startBoneCount = bones.Count; PmxBone ikParent = new PmxBone(), ikBone = new PmxBone(); ikParent.Name = leftRightJp + "足IK親"; ikParent.NameEnglish = "leg IKP_" + leftRightEn; ikBone.Name = leftRightJp + "足IK"; ikBone.NameEnglish = "leg IK_" + leftRightEn; PmxBone master; do { master = bones.Find(b => b.Name == "全ての親"); if (master == null) { throw new ArgumentException("Missing master bone."); } } while (false); ikParent.ParentIndex = bones.IndexOf(master); ikBone.ParentIndex = startBoneCount; // IKP ikParent.SetFlag(BoneFlags.ToBone); ikBone.SetFlag(BoneFlags.ToBone); ikParent.To_Bone = startBoneCount + 1; // IK ikBone.To_Bone = -1; PmxBone ankle, knee, leg; do { var ankleName = leftRightJp + "足首"; ankle = bones.Find(b => b.Name == ankleName); var kneeName = leftRightJp + "ひざ"; knee = bones.Find(b => b.Name == kneeName); var legName = leftRightJp + "足"; leg = bones.Find(b => b.Name == legName); if (ankle == null) { throw new ArgumentException("Missing ankle bone."); } if (knee == null) { throw new ArgumentException("Missing knee bone."); } if (leg == null) { throw new ArgumentException("Missing leg bone."); } } while (false); ikBone.CurrentPosition = ikBone.InitialPosition = ankle.InitialPosition; ikParent.CurrentPosition = ikParent.InitialPosition = new Vector3(ikBone.InitialPosition.X, 0, ikBone.InitialPosition.Z); ikParent.SetFlag(BoneFlags.Translation | BoneFlags.Rotation); ikBone.SetFlag(BoneFlags.Translation | BoneFlags.Rotation | BoneFlags.IK); var ik = new PmxIK(); ik.LoopCount = 10; ik.AngleLimit = MathHelper.DegreesToRadians(114.5916f); ik.TargetBoneIndex = bones.IndexOf(ankle); var links = new IKLink[2]; links[0] = new IKLink(); links[0].BoneIndex = bones.IndexOf(knee); links[0].IsLimited = true; links[0].LowerBound = new Vector3(MathHelper.DegreesToRadians(-180), 0, 0); links[0].UpperBound = new Vector3(MathHelper.DegreesToRadians(-0.5f), 0, 0); links[1] = new IKLink(); links[1].BoneIndex = bones.IndexOf(leg); ik.Links = links; ikBone.IK = ik; return(new[] { ikParent, ikBone }); } PmxBone[] CreateToeIK(string leftRightJp, string leftRightEn) { PmxBone ikParent, ikBone = new PmxBone(); do { var parentName = leftRightJp + "足IK"; ikParent = bones.Find(b => b.Name == parentName); Debug.Assert(ikParent != null, nameof(ikParent) + " != null"); } while (false); ikBone.Name = leftRightJp + "つま先IK"; ikBone.NameEnglish = "toe IK_" + leftRightEn; ikBone.ParentIndex = bones.IndexOf(ikParent); ikBone.SetFlag(BoneFlags.ToBone); ikBone.To_Bone = -1; PmxBone toe, ankle; do { var toeName = leftRightJp + "つま先"; toe = bones.Find(b => b.Name == toeName); var ankleName = leftRightJp + "足首"; ankle = bones.Find(b => b.Name == ankleName); if (toe == null) { throw new ArgumentException("Missing toe bone."); } if (ankle == null) { throw new ArgumentException("Missing ankle bone."); } } while (false); ikBone.CurrentPosition = ikBone.InitialPosition = toe.InitialPosition; ikBone.SetFlag(BoneFlags.Translation | BoneFlags.Rotation | BoneFlags.IK); var ik = new PmxIK(); ik.LoopCount = 10; ik.AngleLimit = MathHelper.DegreesToRadians(114.5916f); ik.TargetBoneIndex = bones.IndexOf(toe); var links = new IKLink[1]; links[0] = new IKLink(); links[0].BoneIndex = bones.IndexOf(ankle); ik.Links = links.ToArray(); ikBone.IK = ik; return(new[] { ikBone }); } var leftLegIK = CreateLegIK("左", "L"); bones.AddRange(leftLegIK); var rightLegIK = CreateLegIK("右", "R"); bones.AddRange(rightLegIK); var leftToeIK = CreateToeIK("左", "L"); bones.AddRange(leftToeIK); var rightToeIK = CreateToeIK("右", "R"); bones.AddRange(rightToeIK); } if (ConversionConfig.Current.AppendEyeBones) { (int VertexStart1, int VertexCount1, int VertexStart2, int VertexCount2) FindEyesVerticeRange() { var meshNameIndex = -1; var cm = combinedMesh as CompositeMesh; Debug.Assert(cm != null, nameof(cm) + " != null"); for (var i = 0; i < cm.Names.Count; i++) { var meshName = cm.Names[i]; if (meshName == "eyes") { meshNameIndex = i; break; } } if (meshNameIndex < 0) { throw new ArgumentException("Mesh \"eyes\" is missing."); } var subMeshMaps = cm.ParentMeshIndices.Enumerate().Where(s => s.Value == meshNameIndex).ToArray(); Debug.Assert(subMeshMaps.Length == 2, "There should be 2 sub mesh maps."); Debug.Assert(subMeshMaps[1].Index - subMeshMaps[0].Index == 1, "The first sub mesh map should contain one element."); var vertexStart1 = (int)cm.SubMeshes[subMeshMaps[0].Index].FirstVertex; var vertexCount1 = (int)cm.SubMeshes[subMeshMaps[0].Index].VertexCount; var vertexStart2 = (int)cm.SubMeshes[subMeshMaps[1].Index].FirstVertex; var vertexCount2 = (int)cm.SubMeshes[subMeshMaps[1].Index].VertexCount; return(vertexStart1, vertexCount1, vertexStart2, vertexCount2); } Vector3 GetEyeBonePosition(int vertexStart, int vertexCount) { var centerPos = Vector3.Zero; var leftMostPos = new Vector3(float.MinValue, 0, 0); var rightMostPos = new Vector3(float.MaxValue, 0, 0); int leftMostIndex = -1, rightMostIndex = -1; for (var i = vertexStart; i < vertexStart + vertexCount; ++i) { var pos = vertices[i].Position; centerPos += pos; if (pos.X > leftMostPos.X) { leftMostPos = pos; leftMostIndex = i; } if (pos.X < rightMostPos.X) { rightMostPos = pos; rightMostIndex = i; } } Debug.Assert(leftMostIndex >= 0, nameof(leftMostIndex) + " >= 0"); Debug.Assert(rightMostIndex >= 0, nameof(rightMostIndex) + " >= 0"); centerPos = centerPos / vertexCount; // "Eyeball". You got the idea? var leftMostNorm = vertices[leftMostIndex].Normal; var rightMostNorm = vertices[rightMostIndex].Normal; var k1 = leftMostNorm.Z / leftMostNorm.X; var k2 = rightMostNorm.Z / rightMostNorm.X; float x1 = leftMostPos.X, x2 = rightMostPos.X, z1 = leftMostPos.Z, z2 = rightMostPos.Z; var d1 = (z2 - k2 * x2 + k2 * x1 - z1) / (k1 - k2); var x = x1 + d1; var z = z1 + k1 * d1; return(new Vector3(x, centerPos.Y, z)); } Vector3 GetEyesBonePosition(int vertexStart1, int vertexCount1, int vertexStart2, int vertexCount2) { var result = new Vector3(); for (var i = vertexStart1; i < vertexStart1 + vertexCount1; ++i) { result += vertices[i].Position; } for (var i = vertexStart2; i < vertexStart2 + vertexCount2; ++i) { result += vertices[i].Position; } result = result / (vertexCount1 + vertexCount2); return(new Vector3(0, result.Y + 0.5f, -0.6f)); } var(vs1, vc1, vs2, vc2) = FindEyesVerticeRange(); PmxBone head; do { head = bones.Find(b => b.Name == "頭"); if (head == null) { throw new ArgumentException("Missing head bone."); } } while (false); var eyes = new PmxBone(); eyes.Name = "両目"; eyes.NameEnglish = "eyes"; eyes.Parent = head; eyes.ParentIndex = bones.IndexOf(head); eyes.CurrentPosition = eyes.InitialPosition = GetEyesBonePosition(vs1, vc1, vs2, vc2); eyes.SetFlag(BoneFlags.Visible | BoneFlags.Rotation | BoneFlags.ToBone); eyes.To_Bone = -1; bones.Add(eyes); PmxBone leftEye = new PmxBone(), rightEye = new PmxBone(); leftEye.Name = "左目"; leftEye.NameEnglish = "eye_L"; rightEye.Name = "右目"; rightEye.NameEnglish = "eye_R"; leftEye.Parent = head; leftEye.ParentIndex = bones.IndexOf(head); rightEye.Parent = head; rightEye.ParentIndex = bones.IndexOf(head); leftEye.SetFlag(BoneFlags.Visible | BoneFlags.Rotation | BoneFlags.ToBone | BoneFlags.AppendRotation); rightEye.SetFlag(BoneFlags.Visible | BoneFlags.Rotation | BoneFlags.ToBone | BoneFlags.AppendRotation); leftEye.To_Bone = -1; rightEye.To_Bone = -1; leftEye.AppendParent = eyes; rightEye.AppendParent = eyes; leftEye.AppendParentIndex = bones.IndexOf(eyes); rightEye.AppendParentIndex = bones.IndexOf(eyes); leftEye.AppendRatio = 1; rightEye.AppendRatio = 1; leftEye.CurrentPosition = leftEye.InitialPosition = GetEyeBonePosition(vs1, vc1); rightEye.CurrentPosition = rightEye.InitialPosition = GetEyeBonePosition(vs2, vc2); bones.Add(leftEye); bones.Add(rightEye); // Fix vertices { var leftEyeIndex = bones.IndexOf(leftEye); var rightEyeIndex = bones.IndexOf(rightEye); for (var i = vs1; i < vs1 + vc1; ++i) { var skin = vertices[i]; // Eyes are only affected by "KUBI/ATAMA" bone by default. So we only need to set one element's values. skin.BoneWeights[0].BoneIndex = leftEyeIndex; Debug.Assert(Math.Abs(skin.BoneWeights[0].Weight - 1) < 0.000001f, "Total weight in the skin of left eye should be 1."); } for (var i = vs2; i < vs2 + vc2; ++i) { var skin = vertices[i]; // Eyes are only affected by "KUBI/ATAMA" bone by default. So we only need to set one element's values. skin.BoneWeights[0].BoneIndex = rightEyeIndex; Debug.Assert(Math.Abs(skin.BoneWeights[0].Weight - 1) < 0.000001f, "Total weight in the skin of right eye should be 1."); } } } // Finally, set the indices. The values will be used later. for (var i = 0; i < bones.Count; i++) { bones[i].BoneIndex = i; } return(bones.ToArray()); }
public EntityBone(World world, PmxBone bone, Bone mmmBone) : base(world) { PmxBone = bone; MMMBone = mmmBone; }
private PmxModel ReadPmxModel() { var model = new PmxModel(); model.Name = ReadString() ?? string.Empty; model.NameEnglish = ReadString() ?? string.Empty; model.Comment = ReadString() ?? string.Empty; model.CommentEnglish = ReadString() ?? string.Empty; ReadVertexInfo(); ReadFaceInfo(); ReadTextureInfo(); ReadMaterialInfo(); ReadBoneInfo(); ReadMorphInfo(); ReadNodeInfo(); ReadRigidBodyInfo(); ReadJointInfo(); ReadSoftBodyInfo(); return(model); void ReadVertexInfo() { var vertexCount = _reader.ReadInt32(); var vertices = new PmxVertex[vertexCount]; for (var i = 0; i < vertexCount; ++i) { vertices[i] = ReadPmxVertex(); } model.Vertices = vertices; } void ReadFaceInfo() { var faceCount = _reader.ReadInt32(); var faceIndices = new int[faceCount]; for (var i = 0; i < faceCount; ++i) { faceIndices[i] = _reader.ReadVarLenIntAsInt32(VertexElementSize, true); } model.FaceTriangles = faceIndices; } void ReadTextureInfo() { var textureCount = _reader.ReadInt32(); var textureNameMap = new Dictionary <int, string>(); var textureIndexLookup = new Dictionary <string, int>(); for (var i = 0; i < textureCount; ++i) { var textureName = ReadString() ?? string.Empty; textureNameMap[i] = textureName; textureIndexLookup[textureName] = i; } textureNameMap[-1] = string.Empty; TextureNameMap = textureNameMap; TextureIndexLookup = textureIndexLookup; } void ReadMaterialInfo() { var materialCount = _reader.ReadInt32(); var materials = new PmxMaterial[materialCount]; for (var i = 0; i < materialCount; ++i) { materials[i] = ReadPmxMaterial(); } model.Materials = materials; } void ReadBoneInfo() { var boneCount = _reader.ReadInt32(); var bones = new PmxBone[boneCount]; for (var i = 0; i < boneCount; ++i) { bones[i] = ReadPmxBone(); bones[i].BoneIndex = i; } model.Bones = bones; model.BonesDictionary = bones.ToDictionary(bone => bone.Name); var rootBoneIndexList = new List <int>(); for (var i = 0; i < bones.Length; ++i) { var bone = bones[i]; if (bone.ParentIndex < 0) { rootBoneIndexList.Add(i); } else { bone.Parent = bones[bone.ParentIndex]; } if (bone.AppendParentIndex >= 0) { bone.AppendParent = bones[bone.AppendParentIndex]; } if (bone.ExternalParentIndex >= 0) { bone.ExternalParent = bones[bone.ExternalParentIndex]; } if (bone.HasFlag(BoneFlags.IK)) { var ik = bone.IK; Debug.Assert(ik != null, nameof(ik) + " != null"); ik.TargetBone = bones[ik.TargetBoneIndex]; foreach (var link in ik.Links) { if (link.BoneIndex >= 0) { link.Bone = bones[link.BoneIndex]; } } } } model.RootBoneIndices = rootBoneIndexList.ToArray(); foreach (var bone in bones) { bone.SetToBindingPose(); } } void ReadMorphInfo() { var morphCount = _reader.ReadInt32(); var morphs = new PmxMorph[morphCount]; for (var i = 0; i < morphCount; ++i) { morphs[i] = ReadPmxMorph(); } model.Morphs = morphs; } void ReadNodeInfo() { var nodeCount = _reader.ReadInt32(); var nodes = new PmxNode[nodeCount]; for (var i = 0; i < nodeCount; ++i) { var node = ReadPmxNode(); nodes[i] = node; if (node.IsSystemNode) { if (node.Name == "Root") { model.RootNodeIndex = i; } else if (node.Name == "表情") { model.FacialExpressionNodeIndex = i; } } } model.Nodes = nodes; } void ReadRigidBodyInfo() { var bodyCount = _reader.ReadInt32(); var bodies = new PmxRigidBody[bodyCount]; for (var i = 0; i < bodyCount; ++i) { bodies[i] = ReadPmxRigidBody(); } model.RigidBodies = bodies; } void ReadJointInfo() { var jointCount = _reader.ReadInt32(); var joints = new PmxJoint[jointCount]; for (var i = 0; i < jointCount; ++i) { joints[i] = ReadPmxJoint(); } model.Joints = joints; } void ReadSoftBodyInfo() { if (DetailedVersion < 2.1f) { return; } var bodyCount = _reader.ReadInt32(); var bodies = new PmxSoftBody[bodyCount]; for (var i = 0; i < bodyCount; ++i) { bodies[i] = ReadPmxSoftBody(); } model.SoftBodies = bodies; } }
// PMDEditor.Pmx internal static Pmx FromStream(Stream s, PmxElementFormat f = null) { var Ret = new Pmx(); var pmxHeader = new PmxHeader(2f); pmxHeader.FromStreamEx(s, null); Ret.Header = pmxHeader; if (pmxHeader.Ver <= 1f) { var mMD_Pmd = new MMD_Pmd(); s.Seek(0L, SeekOrigin.Begin); mMD_Pmd.FromStreamEx(s, null); Ret.FromPmx(PmxConvert.PmdToPmx(mMD_Pmd)); return(Ret); } Ret.ModelInfo = new PmxModelInfo(); Ret.ModelInfo.FromStreamEx(s, pmxHeader.ElementFormat); var num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.VertexList = new List <PmxVertex>(); Ret.VertexList.Clear(); Ret.VertexList.Capacity = num; for (var i = 0; i < num; i++) { var pmxVertex = new PmxVertex(); pmxVertex.FromStreamEx(s, pmxHeader.ElementFormat); Ret.VertexList.Add(pmxVertex); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.FaceList = new List <int>(); Ret.FaceList.Clear(); Ret.FaceList.Capacity = num; for (var j = 0; j < num; j++) { var item = PmxStreamHelper.ReadElement_Int32(s, pmxHeader.ElementFormat.VertexSize, false); Ret.FaceList.Add(item); } var pmxTextureTable = new PmxTextureTable(); pmxTextureTable.FromStreamEx(s, pmxHeader.ElementFormat); num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.MaterialList = new List <PmxMaterial>(); Ret.MaterialList.Clear(); Ret.MaterialList.Capacity = num; for (var k = 0; k < num; k++) { var pmxMaterial = new PmxMaterial(); pmxMaterial.FromStreamEx_TexTable(s, pmxTextureTable, pmxHeader.ElementFormat); Ret.MaterialList.Add(pmxMaterial); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.BoneList = new List <PmxBone>(); Ret.BoneList.Clear(); Ret.BoneList.Capacity = num; for (var l = 0; l < num; l++) { var pmxBone = new PmxBone(); pmxBone.FromStreamEx(s, pmxHeader.ElementFormat); Ret.BoneList.Add(pmxBone); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.MorphList = new List <PmxMorph>(); Ret.MorphList.Clear(); Ret.MorphList.Capacity = num; for (var m = 0; m < num; m++) { var pmxMorph = new PmxMorph(); pmxMorph.FromStreamEx(s, pmxHeader.ElementFormat); Ret.MorphList.Add(pmxMorph); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.NodeList = new List <PmxNode>(); Ret.NodeList.Clear(); Ret.NodeList.Capacity = num; for (var n = 0; n < num; n++) { var pmxNode = new PmxNode(); pmxNode.FromStreamEx(s, pmxHeader.ElementFormat); Ret.NodeList.Add(pmxNode); if (Ret.NodeList[n].SystemNode) { if (Ret.NodeList[n].Name == "Root") { Ret.RootNode = Ret.NodeList[n]; } else if (Ret.NodeList[n].Name == "表情") { Ret.ExpNode = Ret.NodeList[n]; } } } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.BodyList = new List <PmxBody>(); Ret.BodyList.Clear(); Ret.BodyList.Capacity = num; for (var num2 = 0; num2 < num; num2++) { var pmxBody = new PmxBody(); pmxBody.FromStreamEx(s, pmxHeader.ElementFormat); Ret.BodyList.Add(pmxBody); } num = PmxStreamHelper.ReadElement_Int32(s, 4, true); Ret.JointList = new List <PmxJoint>(); Ret.JointList.Clear(); Ret.JointList.Capacity = num; for (var num3 = 0; num3 < num; num3++) { var pmxJoint = new PmxJoint(); pmxJoint.FromStreamEx(s, pmxHeader.ElementFormat); Ret.JointList.Add(pmxJoint); } return(Ret); }