public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int vtxIndex; if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { //PMX vtxIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.VertexIndexLength); } else { //PMD vtxIndex = br.ReadInt32(); if (importSettings.BaseMorph != null) { if (vtxIndex < importSettings.BaseMorph.Offsets.Count) { PMXMorphOffsetVertex mov = (PMXMorphOffsetVertex)importSettings.BaseMorph.Offsets[vtxIndex]; vtxIndex = this.Model.Vertices.IndexOf(mov.Vertex); } } } this.Vertex = this.Model.Vertices[vtxIndex]; this.Translation = PMXVector3.LoadFromStreamStatic(br); }
/// <summary> /// Saves to a stream as PMD. /// </summary> /// <param name="fs"></param> public void SaveToStreamPMD(Stream stream) { List <string> requiredToons = new List <string>(); //List of textures to export string[] defaultToons = new string[] { "toon01.bmp", "toon02.bmp", "toon03.bmp", "toon04.bmp", "toon05.bmp", "toon06.bmp", "toon07.bmp", "toon08.bmp", "toon09.bmp", "toon10.bmp" }; int triangleCount = 0; foreach (PMXMaterial mat in this.Materials) { //this.AddToListIfRequired(requiredToons, mat.DiffuseTexture); if (mat.StandardToon) { this.AddToListIfRequired(requiredToons, defaultToons[mat.StandardToonIndex]); } else { this.AddToListIfRequired(requiredToons, mat.NonStandardToonTexture); } triangleCount += mat.Triangles.Count; } string[] toonFiles = new string[10]; for (int i = 0; i < 10; i++) { if (i < requiredToons.Count) { toonFiles[i] = requiredToons[i]; } else { toonFiles[i] = defaultToons[i]; } } MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); byte[] magic = Encoding.ASCII.GetBytes("Pmd"); ms.Write(magic, 0, 3); Random rnd = new Random(); int randomNumber = rnd.Next(); MMDExportSettings settings = new MMDExportSettings(MMDExportSettings.ModelFormat.PMD); settings.Model = this; settings.ExportHash = randomNumber; settings.TextEncoding = Encoding.GetEncoding(932); float version = 1.0f; bw.Write(version); PMDParser.WriteString(bw, 20, settings.TextEncoding, this.NameJP); PMDParser.WriteString(bw, 256, settings.TextEncoding, this.DescriptionJP); //Vertices bw.Write((int)this.Vertices.Count); int vtxIndex = 0; foreach (PMXVertex v in this.Vertices) { v.AddIndexForExport(settings, vtxIndex); v.WriteToStream(bw, settings); vtxIndex++; } //Triangles bw.Write((Int32)(triangleCount * 3)); foreach (PMXMaterial mat in this.Materials) { foreach (PMXTriangle t in mat.Triangles) { t.WriteToStream(bw, settings); } } //Materials bw.Write((Int32)this.Materials.Count); foreach (PMXMaterial mat in this.Materials) { mat.WriteToStream(bw, settings, toonFiles, defaultToons); } //Bones bw.Write((Int16)this.Bones.Count); List <PMXBone> ikBonesList = new List <PMXBone>(); foreach (PMXBone bn in this.Bones) { if (bn.IK != null) { ikBonesList.Add(bn); } } PMXBone[] ikBones = ikBonesList.ToArray(); foreach (PMXBone bn in this.Bones) { bn.WriteToStream(bw, settings, ikBones); } //PMD IKs bw.Write((Int16)ikBones.Length); foreach (PMXBone bn in ikBones) { PMXParser.WriteIndex(bw, 2, PMXBone.CheckIndexInModel(bn, settings, true)); bn.IK.WriteToStream(bw, settings); } //PMD Morphs List <PMXMorph> exportableMorphs = new List <PMXMorph>(); List <PMXVertex> baseVertices = new List <PMXVertex>(); foreach (PMXMorph mrph in this.Morphs) { bool exportable = true; foreach (PMXMorphOffsetBase mofb in mrph.Offsets) { if (!(mofb is PMXMorphOffsetVertex)) { exportable = false; } } if (exportable) { exportableMorphs.Add(mrph); foreach (PMXMorphOffsetBase mofb in mrph.Offsets) { PMXMorphOffsetVertex mofv = (PMXMorphOffsetVertex)mofb; if (!baseVertices.Contains(mofv.Vertex)) { baseVertices.Add(mofv.Vertex); } } } } settings.BaseMorphVertices = baseVertices; bw.Write((Int16)(exportableMorphs.Count + 1)); PMDParser.WriteString(bw, 20, settings.TextEncoding, "base"); bw.Write((Int32)baseVertices.Count); bw.Write((byte)0); foreach (PMXVertex vtx in baseVertices) { PMXParser.WriteIndex(bw, 4, PMXVertex.CheckIndexInModel(vtx, settings)); vtx.Position.WriteToStream(bw); } foreach (PMXMorph mrph in exportableMorphs) { mrph.WriteToStream(bw, settings); } //Display groups - kinda insanely set up for PMD //PMD doesn't have a root slot //Expression display slots List <PMXMorph> morphs = new List <PMXMorph>(); //List of facial expressions foreach (PMXDisplaySlot ds in this.DisplaySlots) { foreach (PMXBasePart reference in ds.References) { if (reference is PMXMorph) { morphs.Add((PMXMorph)reference); } } } bw.Write((byte)morphs.Count); foreach (PMXMorph mrph in morphs) { int morphId = this.Morphs.IndexOf(mrph) + 1; bw.Write((UInt16)morphId); } //Bone display slots bw.Write((byte)(this.DisplaySlots.Count - 2)); for (int dsidx = 2; dsidx < this.DisplaySlots.Count; dsidx++) { PMDParser.WriteString(bw, 50, settings.TextEncoding, this.DisplaySlots[dsidx].NameJP); } //We've got the names - now let's put the bones in uint totalBoneRefCount = 0; for (int dsidx = 2; dsidx < this.DisplaySlots.Count; dsidx++) { PMXDisplaySlot ds = this.DisplaySlots[dsidx]; foreach (PMXBasePart reference in ds.References) { if (reference is PMXBone) { totalBoneRefCount++; } } } bw.Write((uint)totalBoneRefCount); for (int dsidx = 2; dsidx < this.DisplaySlots.Count; dsidx++) { PMXDisplaySlot ds = this.DisplaySlots[dsidx]; foreach (PMXBasePart reference in ds.References) { if (reference is PMXBone) { PMXBone bref = (PMXBone)reference; bw.Write((UInt16)this.Bones.IndexOf(bref)); bw.Write((byte)(dsidx - 1)); } } } //Always write english names bw.Write((byte)1); PMDParser.WriteString(bw, 20, settings.TextEncoding, this.NameEN); PMDParser.WriteString(bw, 256, settings.TextEncoding, this.DescriptionEN); foreach (PMXBone bn in this.Bones) { PMDParser.WriteString(bw, 20, settings.TextEncoding, bn.NameEN); } foreach (PMXMorph mrph in exportableMorphs) { PMDParser.WriteString(bw, 20, settings.TextEncoding, mrph.NameEN); } for (int i = 2; i < this.DisplaySlots.Count; i++) { PMDParser.WriteString(bw, 50, settings.TextEncoding, this.DisplaySlots[i].NameEN); } //Toon files foreach (string toon in toonFiles) { PMDParser.WriteString(bw, 100, settings.TextEncoding, toon); } //Rigid bodies bw.Write((uint)this.RigidBodies.Count); foreach (PMXRigidBody rb in this.RigidBodies) { rb.WriteToStream(bw, settings); } //Joints bw.Write((uint)this.Joints.Count); foreach (PMXJoint jt in this.Joints) { jt.WriteToStream(bw, settings); } //Vertex restore foreach (PMXVertex v in this.Vertices) { v.RemoveIndexForExport(settings); } long length = ms.Position; ms.Seek(0, SeekOrigin.Begin); ms.CopyTo(stream); ms.Close(); ms = null; }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int offsets; byte morphType; if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { //PMX format this.NameJP = PMXParser.ReadString(br, importSettings.TextEncoding); this.NameEN = PMXParser.ReadString(br, importSettings.TextEncoding); this.Panel = (PanelType)(int)br.ReadByte(); morphType = br.ReadByte(); offsets = br.ReadInt32(); } else { //PMD format this.NameJP = PMDParser.ReadString(br, 20, importSettings.TextEncoding); offsets = br.ReadInt32(); this.Panel = (PanelType)(int)br.ReadByte(); morphType = PMXMorph.MORPH_IDENTIFY_VERTEX; } for (int i = 0; i < offsets; i++) { PMXMorphOffsetBase mb = null; switch (morphType) { case PMXMorph.MORPH_IDENTIFY_GROUP: mb = new PMXMorphOffsetGroup(this.Model, this); break; case PMXMorph.MORPH_IDENTIFY_VERTEX: mb = new PMXMorphOffsetVertex(this.Model, this); break; case PMXMorph.MORPH_IDENTIFY_BONE: mb = new PMXMorphOffsetBone(this.Model, this); break; case PMXMorph.MORPH_IDENTIFY_UV: mb = new PMXMorphOffsetUV(this.Model, this, PMXMorphOffsetUV.UVAddIndexType.UV); break; case PMXMorph.MORPH_IDENTIFY_UV_EXTENDED1: mb = new PMXMorphOffsetUV(this.Model, this, PMXMorphOffsetUV.UVAddIndexType.AddUV1); break; case PMXMorph.MORPH_IDENTIFY_UV_EXTENDED2: mb = new PMXMorphOffsetUV(this.Model, this, PMXMorphOffsetUV.UVAddIndexType.AddUV2); break; case PMXMorph.MORPH_IDENTIFY_UV_EXTENDED3: mb = new PMXMorphOffsetUV(this.Model, this, PMXMorphOffsetUV.UVAddIndexType.AddUV3); break; case PMXMorph.MORPH_IDENTIFY_UV_EXTENDED4: mb = new PMXMorphOffsetUV(this.Model, this, PMXMorphOffsetUV.UVAddIndexType.AddUV4); break; case PMXMorph.MORPH_IDENTIFY_MATERIAL: mb = new PMXMorphOffsetMaterial(this.Model, this); break; default: throw new InvalidDataException("Unknown morph type " + morphType); } mb.LoadFromStream(br, importSettings); this.Offsets.Add(mb); } }