private void WritePmxVertex([NotNull] PmxModel model, [NotNull] PmxVertex vertex) { _writer.Write(vertex.Position); _writer.Write(vertex.Normal); _writer.Write(vertex.UV); for (var i = 0; i < model.UvaCount && i < PmxVertex.MaxUvaCount; ++i) { _writer.Write(vertex.Uva[i]); } _writer.Write((byte)vertex.Deformation); switch (vertex.Deformation) { case Deformation.Bdef1: _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize); break; case Deformation.Bdef2: _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize); _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[1].BoneIndex, BoneElementSize); _writer.Write(vertex.BoneWeights[0].Weight); break; case Deformation.Bdef4: case Deformation.Qdef: _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize); _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[1].BoneIndex, BoneElementSize); _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[2].BoneIndex, BoneElementSize); _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[3].BoneIndex, BoneElementSize); _writer.Write(vertex.BoneWeights[0].Weight); _writer.Write(vertex.BoneWeights[1].Weight); _writer.Write(vertex.BoneWeights[2].Weight); _writer.Write(vertex.BoneWeights[3].Weight); break; case Deformation.Sdef: { _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[0].BoneIndex, BoneElementSize); _writer.WriteInt32AsVarLenInt(vertex.BoneWeights[1].BoneIndex, BoneElementSize); _writer.Write(vertex.BoneWeights[0].Weight); _writer.Write(vertex.C0); _writer.Write(vertex.R0); _writer.Write(vertex.R1); break; } default: throw new ArgumentOutOfRangeException(); } _writer.Write(vertex.EdgeScale); }
private void CreateMeshList(SkinnedMeshRenderer meshRender) { GameObject gameObject = meshRender.gameObject; Mesh mesh = meshRender.sharedMesh; BoneWeight[] boneWeights = mesh.boneWeights; vertexIndexMap.Add(gameObject.transform.parent.gameObject.name, pmxFile.VertexList.Count); if (SavePostion) { Mesh mesh2 = new Mesh(); meshRender.BakeMesh(mesh2); mesh = mesh2; } UnityEngine.Vector2[] uv = mesh.uv; UnityEngine.Vector2[] uv2 = mesh.uv2; UnityEngine.Vector3[] normals = mesh.normals; UnityEngine.Vector3[] vertices = mesh.vertices; for (int i = 0; i < mesh.subMeshCount; i++) { int[] triangles = mesh.GetTriangles(i); AddFaceList(triangles, vertexCount); CreateMaterial(meshRender.materials[i], triangles.Length); } vertexCount += mesh.vertexCount; for (int i = 0; i < mesh.vertexCount; i++) { PmxVertex pmxVertex = new PmxVertex(); pmxVertex.UV = new PmxLib.Vector2(uv[i].x, -uv[i].y); ConvertBoneWeight(pmxVertex.Weight, boneWeights[i], meshRender.bones); Transform t = gameObject.transform; UnityEngine.Vector3 n = normals[i]; n = t.TransformDirection(n); pmxVertex.Normal = ToPmxVec3(n); UnityEngine.Vector3 v = vertices[i]; v = t.TransformPoint(v); v *= scaleFactor; pmxVertex.Position = ToPmxVec3(v); pmxVertex.UpdateDeformType(); pmxFile.VertexList.Add(pmxVertex); } }
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; } }
private PmxVertex ReadPmxVertex() { var vertex = new PmxVertex(); vertex.Position = _reader.ReadVector3(); vertex.Normal = _reader.ReadVector3(); vertex.UV = _reader.ReadVector2(); for (var i = 0; i < UvaCount && i < PmxVertex.MaxUvaCount; ++i) { vertex.Uva[i] = _reader.ReadVector4(); } vertex.Deformation = (Deformation)_reader.ReadByte(); switch (vertex.Deformation) { case Deformation.Bdef1: vertex.BoneWeights[0].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[0].Weight = 1; break; case Deformation.Bdef2: vertex.BoneWeights[0].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[1].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[0].Weight = _reader.ReadSingle(); vertex.BoneWeights[1].Weight = 1 - vertex.BoneWeights[0].Weight; break; case Deformation.Bdef4: case Deformation.Qdef: vertex.BoneWeights[0].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[1].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[2].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[3].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[0].Weight = _reader.ReadSingle(); vertex.BoneWeights[1].Weight = _reader.ReadSingle(); vertex.BoneWeights[2].Weight = _reader.ReadSingle(); vertex.BoneWeights[3].Weight = _reader.ReadSingle(); break; case Deformation.Sdef: { vertex.BoneWeights[0].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[1].BoneIndex = _reader.ReadVarLenIntAsInt32(BoneElementSize); vertex.BoneWeights[0].Weight = _reader.ReadSingle(); vertex.BoneWeights[1].Weight = 1 - vertex.BoneWeights[0].Weight; vertex.C0 = _reader.ReadVector3(); vertex.R0 = _reader.ReadVector3(); vertex.R1 = _reader.ReadVector3(); var vec = vertex.R0 * vertex.BoneWeights[0].Weight + vertex.R1 * vertex.BoneWeights[1].Weight; vertex.RW0 = vertex.R0 - vec; vertex.RW1 = vertex.R1 - vec; } break; default: throw new ArgumentOutOfRangeException(); } vertex.EdgeScale = _reader.ReadSingle(); return(vertex); }
private static IReadOnlyList <PmxVertex> AddVertices([NotNull] Avatar combinedAvatar, [NotNull] Mesh combinedMesh, int bodyMeshVertexCount) { var vertexCount = combinedMesh.VertexCount; var vertices = new PmxVertex[vertexCount]; // In case that vertex count is more than skin count (ill-formed MLTD models: ch_ex005_022ser) var skinCount = combinedMesh.Skin.Count; for (var i = 0; i < vertexCount; ++i) { var vertex = new PmxVertex(); var position = combinedMesh.Vertices[i]; var normal = combinedMesh.Normals[i]; var uv = combinedMesh.UV1[i]; vertex.Position = position.ToOpenTK().FixUnityToOpenTK(); if (ConversionConfig.Current.ScaleToPmxSize) { vertex.Position = vertex.Position * ScalingConfig.ScaleUnityToPmx; } vertex.Normal = normal.ToOpenTK().FixUnityToOpenTK(); OpenTK.Vector2 fixedUv; // Body, then head. // TODO: For heads, inverting/flipping is different among models? // e.g. ss001_015siz can be processed via the method below; gs001_201xxx's head UVs are not inverted but some are flipped. if (i < bodyMeshVertexCount) { // Invert UV! fixedUv = new OpenTK.Vector2(uv.X, 1 - uv.Y); } else { fixedUv = uv.ToOpenTK(); } vertex.UV = fixedUv; vertex.EdgeScale = 1.0f; var skin = i < skinCount ? combinedMesh.Skin[i] : null; var affectiveInfluenceCount = skin != null?skin.Count(inf => inf != null) : 0; switch (affectiveInfluenceCount) { case 0: // This vertex is static. It is not attached to any bone. break; case 1: vertex.Deformation = Deformation.Bdef1; break; case 2: vertex.Deformation = Deformation.Bdef2; break; case 3: throw new NotSupportedException($"Not supported: vertex #{i} has 3 influences."); case 4: vertex.Deformation = Deformation.Bdef4; break; default: throw new ArgumentOutOfRangeException(nameof(affectiveInfluenceCount), "Unsupported number of bones."); } for (var j = 0; j < affectiveInfluenceCount; ++j) { var boneId = combinedMesh.BoneNameHashes[skin[j].BoneIndex]; var realBoneIndex = combinedAvatar.AvatarSkeleton.NodeIDs.FindIndex(boneId); if (realBoneIndex < 0) { throw new ArgumentOutOfRangeException(nameof(realBoneIndex)); } vertex.BoneWeights[j].BoneIndex = realBoneIndex; vertex.BoneWeights[j].Weight = skin[j].Weight; } vertices[i] = vertex; } return(vertices); }
// 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); }