public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { this.NameJP = PMXParser.ReadString(br, importSettings.TextEncoding); this.NameEN = PMXParser.ReadString(br, importSettings.TextEncoding); byte flag = br.ReadByte(); //Ignored will be automatically generated on export. int refCount = br.ReadInt32(); for (int i = 0; i < refCount; i++) { byte refType = br.ReadByte(); switch (refType) { case PMXDisplaySlot.REF_IDENTIFY_BONE: int boneIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.References.Add(this.Model.Bones[boneIndex]); break; case PMXDisplaySlot.REF_IDENTIFY_MORPH: int morphIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.MorphIndexLength); this.References.Add(this.Model.Morphs[morphIndex]); break; } } }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameJP); PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameEN); bool isImportant = (this.Model.DisplaySlots.IndexOf(this) <= 1); //Root and EXP Displays if (isImportant) { bw.Write((byte)1); } else { bw.Write((byte)0); } bw.Write((Int32)this.References.Count); foreach (PMXBasePart rfr in this.References) { if (rfr is PMXBone) { bw.Write((byte)PMXDisplaySlot.REF_IDENTIFY_BONE); PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel((PMXBone)rfr, exportSettings, false)); } else if (rfr is PMXMorph) { bw.Write((byte)PMXDisplaySlot.REF_IDENTIFY_MORPH); PMXParser.WriteIndex(bw, exportSettings.BitSettings.MorphIndexLength, PMXMorph.CheckIndexInModel((PMXMorph)rfr, exportSettings, false)); } else { throw new InvalidDataException("Invalid reference in display slots. Only bones and morphs are supported!"); } } }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int mtIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.MaterialIndexLength); if (mtIndex < 0) { this.Material = null; } else { this.Material = this.Model.Materials[mtIndex]; } this.Type = (MaterialMorphOffsetType)(int)br.ReadByte(); this.Diffuse = PMXColorRGBA.LoadFromStreamStatic(br); this.Specular = PMXColorRGBA.LoadFromStreamStatic(br); this.Ambient = PMXColorRGB.LoadFromStreamStatic(br); this.EdgeColor = PMXColorRGBA.LoadFromStreamStatic(br); this.EdgeSize = br.ReadSingle(); this.TextureFactor = PMXColorRGBA.LoadFromStreamStatic(br); this.SphereTextureFactor = PMXColorRGBA.LoadFromStreamStatic(br); this.ToonTextureFactor = PMXColorRGBA.LoadFromStreamStatic(br); }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { PMXParser.WriteIndex(bw, exportSettings.BitSettings.VertexIndexLength, PMXVertex.CheckIndexInModel(this.Vertex, exportSettings)); this.UVTranslation.WriteToStream(bw); this.UVTranslation2.WriteToStream(bw); }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameJP); PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameEN); bw.Write((byte)(int)this.Type); PMXParser.WriteIndex(bw, exportSettings.BitSettings.RigidBodyIndexLength, PMXRigidBody.CheckIndexInModel(this.RigidBodyA, exportSettings)); PMXParser.WriteIndex(bw, exportSettings.BitSettings.RigidBodyIndexLength, PMXRigidBody.CheckIndexInModel(this.RigidBodyB, exportSettings)); } else { PMDParser.WriteString(bw, 20, exportSettings.TextEncoding, this.NameJP); PMXParser.WriteIndex(bw, 4, PMXRigidBody.CheckIndexInModel(this.RigidBodyA, exportSettings)); PMXParser.WriteIndex(bw, 4, PMXRigidBody.CheckIndexInModel(this.RigidBodyB, exportSettings)); } this.Position.WriteToStream(bw); this.Rotation.WriteToStream(bw); this.TranslationLimitMin.WriteToStream(bw); this.TranslationLimitMax.WriteToStream(bw); this.RotationLimitMin.WriteToStream(bw); this.RotationLimitMax.WriteToStream(bw); this.SpringConstantTranslation.WriteToStream(bw); this.SpringConstantRotation.WriteToStream(bw); }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { base.WriteToStream(bw, exportSettings); PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.Bone2, exportSettings)); bw.Write(this.Bone1Weight); } else { int b1i = PMXBone.CheckIndexInModel(this.Bone1, exportSettings); int b2i = PMXBone.CheckIndexInModel(this.Bone2, exportSettings); List <KeyValuePair <int, float> > sortKeys = new List <KeyValuePair <int, float> >(); if (b1i >= 0) { sortKeys.Add(new KeyValuePair <int, float>(b1i, this.Bone1Weight)); } if (b2i >= 0) { sortKeys.Add(new KeyValuePair <int, float>(b2i, 1.0f - this.Bone1Weight)); } this.ExportToPMDBase(sortKeys, bw); } }
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); }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int linkCount; if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { //PMX IK this.boneTargetIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.Loop = br.ReadInt32(); this.RadianLimit = br.ReadSingle(); linkCount = br.ReadInt32(); } else { //PMD IK this.boneTargetIndex = br.ReadUInt16(); linkCount = (int)br.ReadByte(); this.Loop = br.ReadUInt16(); this.RadianLimit = br.ReadSingle(); } for (int i = 0; i < linkCount; i++) { PMXIKLink link = new PMXIKLink(this.Model, this); link.LoadFromStream(br, importSettings); this.IKLinks.Add(link); } }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { byte indexLength = ((exportSettings.Format == MMDExportSettings.ModelFormat.PMX) ? exportSettings.BitSettings.VertexIndexLength : (byte)2); PMXParser.WriteIndex(bw, indexLength, PMXVertex.CheckIndexInModel(this.Vertex1, exportSettings)); PMXParser.WriteIndex(bw, indexLength, PMXVertex.CheckIndexInModel(this.Vertex2, exportSettings)); PMXParser.WriteIndex(bw, indexLength, PMXVertex.CheckIndexInModel(this.Vertex3, exportSettings)); }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int boneIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.Bone = this.Model.Bones[boneIndex]; this.Translation = PMXVector3.LoadFromStreamStatic(br); this.Rotation = PMXQuaternion.LoadFromStreamStatic(br); }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int vtxIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.VertexIndexLength); this.Vertex = this.Model.Vertices[vtxIndex]; this.UVTranslation = PMXVector2.LoadFromStreamStatic(br); this.UVTranslation2 = PMXVector2.LoadFromStreamStatic(br); }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { this.bone1Index = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.bone2Index = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.bone3Index = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.bone4Index = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.Bone1Weight = br.ReadSingle(); this.Bone2Weight = br.ReadSingle(); this.Bone3Weight = br.ReadSingle(); this.Bone4Weight = br.ReadSingle(); }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { //PMX PMXParser.WriteIndex(bw, exportSettings.BitSettings.VertexIndexLength, PMXVertex.CheckIndexInModel(this.Vertex, exportSettings)); } else { //PMD PMXParser.WriteIndex(bw, 4, exportSettings.BaseMorphVertices.IndexOf(this.Vertex)); } this.Translation.WriteToStream(bw); }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int boneIndex; if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { this.NameJP = PMXParser.ReadString(br, importSettings.TextEncoding); this.NameEN = PMXParser.ReadString(br, importSettings.TextEncoding); boneIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); } else { this.NameJP = PMDParser.ReadString(br, 20, importSettings.TextEncoding); this.NameEN = this.NameJP; boneIndex = br.ReadInt16(); } if (boneIndex < 0) { this.Bone = null; } else { this.Bone = this.Model.Bones[boneIndex]; } this.CollissionGroup = br.ReadByte(); this.NoCollissionGroups.LoadFromStream(br, importSettings); this.Shape = (BodyShape)(int)br.ReadByte(); this._shapeSize = PMXVector3.LoadFromStreamStatic(br); this.Position = PMXVector3.LoadFromStreamStatic(br); this.Rotation = PMXVector3.LoadFromStreamStatic(br); this.Mass = br.ReadSingle(); this.LinearDamping = br.ReadSingle(); this.AngularDamping = br.ReadSingle(); this.Repulsion = br.ReadSingle(); this.Friction = br.ReadSingle(); this.Type = (BodyType)(int)br.ReadByte(); if (importSettings.Format == MMDImportSettings.ModelFormat.PMD && this.Bone != null) { //PMD location fix this.Position += this.Bone.Position; } }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { PMXParser.WriteIndex(bw, exportSettings.BitSettings.MaterialIndexLength, PMXMaterial.CheckIndexInModel(this.Material, exportSettings, true)); bw.Write((byte)(int)this.Type); this.Diffuse.WriteToStream(bw); this.Specular.WriteToStream(bw); this.Ambient.WriteToStream(bw); this.EdgeColor.WriteToStream(bw); bw.Write(this.EdgeSize); this.TextureFactor.WriteToStream(bw); this.SphereTextureFactor.WriteToStream(bw); this.ToonTextureFactor.WriteToStream(bw); }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { //PMX format PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameJP); PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameEN); bw.Write((byte)(int)this.Panel); if (this.Offsets.Count == 0) { bw.Write((byte)PMXMorph.MORPH_IDENTIFY_VERTEX); bw.Write((Int32)0); } else { byte morphTypeId = this.Offsets[0].MorphTargetType; bw.Write((byte)morphTypeId); bw.Write((Int32)this.Offsets.Count); foreach (PMXMorphOffsetBase offset in this.Offsets) { if (offset.MorphTargetType != morphTypeId) { throw new InvalidDataException("Morph offset types mustn't be mixed types"); } offset.WriteToStream(bw, exportSettings); } } } //PMD format else { PMDParser.WriteString(bw, 20, exportSettings.TextEncoding, this.NameJP); bw.Write((Int32)this.Offsets.Count); bw.Write((byte)(int)this.Panel); foreach (PMXMorphOffsetBase offset in this.Offsets) { if (!(offset is PMXMorphOffsetVertex)) { throw new InvalidDataException("PMD only supports vertex morphs."); } offset.WriteToStream(bw, exportSettings); } } }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { //PMX format this.boneIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.HasLimits = (br.ReadByte() == 1); if (this.HasLimits) { this.Minimum = PMXVector3.LoadFromStreamStatic(br); this.Maximum = PMXVector3.LoadFromStreamStatic(br); } } else { this.boneIndex = br.ReadUInt16(); } }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameJP); PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameEN); PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.Bone, exportSettings, true)); } else { PMDParser.WriteString(bw, 20, exportSettings.TextEncoding, this.NameEN); PMXParser.WriteIndex(bw, 2, PMXBone.CheckIndexInModel(this.Bone, exportSettings, true)); } bw.Write((byte)this.CollissionGroup); this.NoCollissionGroups.WriteToStream(bw, exportSettings); bw.Write((byte)(int)this.Shape); this._shapeSize.WriteToStream(bw); if (exportSettings.Format == MMDExportSettings.ModelFormat.PMD && this.Bone != null) { //PMD location fix PMXVector3 pos = new PMXVector3(this.Position.X, this.Position.Y, this.Position.Z); pos -= this.Bone.Position; pos.WriteToStream(bw); } else { this.Position.WriteToStream(bw); } this.Rotation.WriteToStream(bw); bw.Write(this.Mass); bw.Write(this.LinearDamping); bw.Write(this.AngularDamping); bw.Write(this.Repulsion); bw.Write(this.Friction); bw.Write((byte)(int)this.Type); }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int index1, index2, index3; if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { //PMX index1 = PMXParser.ReadIndex(br, importSettings.BitSettings.VertexIndexLength); index2 = PMXParser.ReadIndex(br, importSettings.BitSettings.VertexIndexLength); index3 = PMXParser.ReadIndex(br, importSettings.BitSettings.VertexIndexLength); } else { //PMD index1 = (int)br.ReadUInt16(); index2 = (int)br.ReadUInt16(); index3 = (int)br.ReadUInt16(); } this.Vertex1 = this.Model.Vertices[index1]; this.Vertex2 = this.Model.Vertices[index2]; this.Vertex3 = this.Model.Vertices[index3]; }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { //PMX IK PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.Bone, exportSettings, true)); if (this.HasLimits) { bw.Write((byte)1); this.Minimum.WriteToStream(bw); this.Maximum.WriteToStream(bw); } else { bw.Write((byte)0); } } else { //PMD IK PMXParser.WriteIndex(bw, 2, PMXBone.CheckIndexInModel(this.Bone, exportSettings, true)); } }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { int rigidBodyIndexA, rigidBodyIndexB; if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { this.NameJP = PMXParser.ReadString(br, importSettings.TextEncoding); this.NameEN = PMXParser.ReadString(br, importSettings.TextEncoding); this.Type = (JointType)(int)br.ReadByte(); rigidBodyIndexA = PMXParser.ReadIndex(br, importSettings.BitSettings.RigidBodyIndexLength); rigidBodyIndexB = PMXParser.ReadIndex(br, importSettings.BitSettings.RigidBodyIndexLength); } else { this.NameJP = PMDParser.ReadString(br, 20, importSettings.TextEncoding); this.NameEN = this.NameJP; this.Type = JointType.SpringSixDOF; rigidBodyIndexA = br.ReadInt32(); rigidBodyIndexB = br.ReadInt32(); } this.RigidBodyA = this.Model.RigidBodies[rigidBodyIndexA]; this.RigidBodyB = this.Model.RigidBodies[rigidBodyIndexB]; this.Position = PMXVector3.LoadFromStreamStatic(br); this.Rotation = PMXVector3.LoadFromStreamStatic(br); this.TranslationLimitMin = PMXVector3.LoadFromStreamStatic(br); this.TranslationLimitMax = PMXVector3.LoadFromStreamStatic(br); this.RotationLimitMin = PMXVector3.LoadFromStreamStatic(br); this.RotationLimitMax = PMXVector3.LoadFromStreamStatic(br); this.SpringConstantTranslation = PMXVector3.LoadFromStreamStatic(br); this.SpringConstantRotation = PMXVector3.LoadFromStreamStatic(br); }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { //PMX IK PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.Target, exportSettings, true)); bw.Write((Int32)this.Loop); bw.Write(this.RadianLimit); bw.Write((Int32)this.IKLinks.Count); } else { //PMD PMXParser.WriteIndex(bw, 2, PMXBone.CheckIndexInModel(this.Target, exportSettings, true)); bw.Write((byte)this.IKLinks.Count); bw.Write((UInt16)this.Loop); bw.Write(this.RadianLimit); } foreach (PMXIKLink link in this.IKLinks) { link.WriteToStream(bw, exportSettings); } }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { PMXParser.WriteIndex(bw, exportSettings.BitSettings.MorphIndexLength, PMXMorph.CheckIndexInModel(this.MorphTarget, exportSettings, false)); bw.Write(this.Strength); }
public override void LoadFromStream(BinaryReader br, MMDImportSettings importSettings) { this.morphTargetIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.MorphIndexLength); this.Strength = br.ReadSingle(); }
/// <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 static PMXModel LoadFromPMXFile(string pmxFile, PMXModelDescriptor modelDescriptor) { FileStream fs = new FileStream(pmxFile, FileMode.Open, FileAccess.Read, FileShare.Read); byte[] buffer = new byte[3]; fs.Read(buffer, 0, 3); string head = Encoding.ASCII.GetString(buffer); fs.Seek(1, SeekOrigin.Current); if (head != "PMX") { throw new Exception("Not a PMX file!"); } BinaryReader br = new BinaryReader(fs); float PMXVersion = br.ReadSingle(); if (PMXVersion != 2.0f && PMXVersion != 2.1f) { throw new Exception("Unsupported PMX Version!"); } byte flags = br.ReadByte(); if (flags != 8) { throw new Exception("Invalid PMX bytes version!"); } MMDImportSettings settings = new MMDImportSettings(MMDImportSettings.ModelFormat.PMX); List <PMXBasePart> allParts = new List <PMXBasePart>(); byte text_encoding = br.ReadByte(); settings.TextEncoding = (text_encoding == 1 ? Encoding.UTF8 : (text_encoding == 0 ? Encoding.Unicode : Encoding.GetEncoding(932))); settings.ExtendedUV = br.ReadByte(); settings.ClassDescriptor = modelDescriptor; PMXModel md = new PMXModel(); settings.BitSettings.VertexIndexLength = br.ReadByte(); settings.BitSettings.TextureIndexLength = br.ReadByte(); settings.BitSettings.MaterialIndexLength = br.ReadByte(); settings.BitSettings.BoneIndexLength = br.ReadByte(); settings.BitSettings.MorphIndexLength = br.ReadByte(); settings.BitSettings.RigidBodyIndexLength = br.ReadByte(); md.NameJP = PMXParser.ReadString(br, settings.TextEncoding); md.NameEN = PMXParser.ReadString(br, settings.TextEncoding); md.DescriptionJP = PMXParser.ReadString(br, settings.TextEncoding); md.DescriptionEN = PMXParser.ReadString(br, settings.TextEncoding); //Vertices uint vertexCount = br.ReadUInt32(); for (int i = 0; i < vertexCount; i++) { PMXVertex v = (PMXVertex)Activator.CreateInstance(modelDescriptor.VertexType.StoredType, new object[] { md }); v.LoadFromStream(br, settings); md.Vertices.Add(v); allParts.Add(v); } //Triangles uint vertexRefCount = br.ReadUInt32(); if (vertexRefCount % 3 != 0) { throw new Exception("Invalid triangle count!"); } uint triangleCount = vertexRefCount / 3; List <PMXTriangle> importTriangles = new List <PMXTriangle>(); for (int i = 0; i < triangleCount; i++) { PMXTriangle t = (PMXTriangle)Activator.CreateInstance(modelDescriptor.TriangleType.StoredType, new object[] { md }); t.LoadFromStream(br, settings); importTriangles.Add(t); allParts.Add(t); } //Textures uint textureCount = br.ReadUInt32(); List <string> importTextures = new List <string>(); for (int i = 0; i < textureCount; i++) { string tex = PMXParser.ReadString(br, settings.TextEncoding); importTextures.Add(tex); } string[] textures = importTextures.ToArray(); //Materials uint materialCount = br.ReadUInt32(); for (int i = 0; i < materialCount; i++) { PMXMaterial mt = (PMXMaterial)Activator.CreateInstance(modelDescriptor.MaterialType.StoredType, new object[] { md }); mt.LoadFromStream(br, settings, textures, importTriangles); md.Materials.Add(mt); allParts.Add(mt); } if (importTriangles.Count > 0) { throw new InvalidDataException("Model materials don't cover all triangles!"); } //Bones uint boneCount = br.ReadUInt32(); for (int i = 0; i < boneCount; i++) { PMXBone bn = (PMXBone)Activator.CreateInstance(modelDescriptor.BoneType.StoredType, new object[] { md }); bn.LoadFromStream(br, settings); md.Bones.Add(bn); allParts.Add(bn); } //Morphs uint morphCount = br.ReadUInt32(); for (int i = 0; i < morphCount; i++) { PMXMorph mrph = (PMXMorph)Activator.CreateInstance(modelDescriptor.MorphType.StoredType, new object[] { md }); mrph.LoadFromStream(br, settings); md.Morphs.Add(mrph); allParts.Add(mrph); } //Display frames md.DisplaySlots.Clear(); uint displayCount = br.ReadUInt32(); for (int i = 0; i < displayCount; i++) { PMXDisplaySlot ds = new PMXDisplaySlot(md); ds.LoadFromStream(br, settings); md.DisplaySlots.Add(ds); allParts.Add(ds); } //Rigid bodies uint rigidBodyCount = br.ReadUInt32(); for (int i = 0; i < rigidBodyCount; i++) { PMXRigidBody rb = (PMXRigidBody)Activator.CreateInstance(modelDescriptor.RigidBodyType.StoredType, new object[] { md }); rb.LoadFromStream(br, settings); md.RigidBodies.Add(rb); allParts.Add(rb); } //Joints uint jointsCount = br.ReadUInt32(); for (int i = 0; i < jointsCount; i++) { PMXJoint jt = (PMXJoint)Activator.CreateInstance(modelDescriptor.JointType.StoredType, new object[] { md }); jt.LoadFromStream(br, settings); md.Joints.Add(jt); allParts.Add(jt); } br.BaseStream.Close(); br = null; fs = null; foreach (PMXBasePart part in allParts) { part.FinaliseAfterImport(); } return(md); }
public override void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings) { PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.Bone, exportSettings, false)); this.Translation.WriteToStream(bw); this.Rotation.WriteToStream(bw); }
public void WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings, PMXBone[] ikBones) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { //PMX export short flags = 0x0000; flags |= (short)(this.HasChildBone ? PMXBone.BONE_TAILPOS_IS_BONE : 0x0000); flags |= (short)(this.Rotatable ? PMXBone.BONE_CAN_ROTATE : 0x0000); flags |= (short)(this.Translatable ? PMXBone.BONE_CAN_TRANSLATE : 0x0000); flags |= (short)(this.Visible ? PMXBone.BONE_IS_VISIBLE : 0x0000); flags |= (short)(this.Operating ? PMXBone.BONE_CAN_MANIPULATE : 0x0000); flags |= (short)((this.ExternalModificationType == BoneExternalModificationType.Both || this.ExternalModificationType == BoneExternalModificationType.Rotation) ? PMXBone.BONE_IS_EXTERNAL_ROTATION : 0x0000); flags |= (short)((this.ExternalModificationType == BoneExternalModificationType.Both || this.ExternalModificationType == BoneExternalModificationType.Translation) ? PMXBone.BONE_IS_EXTERNAL_TRANSLATION : 0x0000); flags |= (short)(this.FixedAxis ? PMXBone.BONE_HAS_FIXED_AXIS : 0x0000); flags |= (short)(this.LocalCoordinates ? PMXBone.BONE_HAS_LOCAL_COORDINATE : 0x0000); flags |= (short)(this.HasExternalParent ? PMXBone.BONE_IS_EXTERNAL_PARENT_DEFORM : 0x0000); flags |= (short)(this.TransformPhysicsFirst ? PMXBone.BONE_IS_AFTER_PHYSICS_DEFORM : 0x0000); flags |= (short)((this.IK != null) ? PMXBone.BONE_IS_IK : 0x0000); PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameJP); PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameEN); this.Position.WriteToStream(bw); PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.Parent, exportSettings, true)); bw.Write((Int32)this.Layer); bw.Write((Int16)flags); if (this.HasChildBone) { PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.ChildBone, exportSettings, true)); } else { this.ChildVector.WriteToStream(bw); } if (this.ExternalModificationType != BoneExternalModificationType.None) { PMXParser.WriteIndex(bw, exportSettings.BitSettings.BoneIndexLength, PMXBone.CheckIndexInModel(this.ExternalBone, exportSettings, true)); bw.Write(this.ExternalBoneEffect); } if (this.FixedAxis) { this.AxisLimit.WriteToStream(bw); } if (this.LocalCoordinates) { this.LocalCoordinatesX.WriteToStream(bw); this.LocalCoordinatesZ.WriteToStream(bw); } if (this.HasExternalParent) { bw.Write((Int32)this.ExternalParentKey); } if (this.IK != null) { this.IK.WriteToStream(bw, exportSettings); } } else { //PMD format PMDParser.WriteString(bw, 20, exportSettings.TextEncoding, this.NameJP); bw.Write((Int16)PMXBone.CheckIndexInModel(this.Parent, exportSettings, true)); if (this.HasChildBone) { bw.Write((Int16)PMXBone.CheckIndexInModel(this.ChildBone, exportSettings, true)); } else { bw.Write((Int16)(-1)); } byte type = PMD_BONE_TYPE_ROTATE; short ikIndex = 0; if (this.Translatable) { type = PMD_BONE_TYPE_ROTATE_MOVE; } if (this.IK != null) { type = PMD_BONE_TYPE_IK; } if (this.IK != null) { bool isIkTarget = false; foreach (PMXBone ikBone in ikBones) { foreach (PMXIKLink link in ikBone.IK.IKLinks) { if (link.Bone == this) { ikIndex = (Int16)PMXBone.CheckIndexInModel(ikBone, exportSettings, true); isIkTarget = true; break; } } if (isIkTarget) { break; } } if (isIkTarget) { type = (this.Visible ? PMD_BONE_TYPE_IK_CHILD:PMD_BONE_TYPE_IK_TARGET); } else if (!this.Visible) { type = PMD_BONE_TYPE_INVISIBLE; } else if (this.FixedAxis) { type = (this.Visible ? PMD_BONE_TYPE_TWIST : PMD_BONE_TYPE_TWIST_INVISIBLE); } else if (this.ExternalModificationType != BoneExternalModificationType.Both) { type = PMD_BONE_TYPE_EXTERNAL_ROTATOR; ikIndex = (Int16)PMXBone.CheckIndexInModel(this.ExternalBone, exportSettings, true); } } bw.Write(type); bw.Write(ikIndex); this.Position.WriteToStream(bw); } }
public void LoadFromStream(BinaryReader br, MMDImportSettings importSettings, out int pmdIKIndex) { pmdIKIndex = -1; if (importSettings.Format == MMDImportSettings.ModelFormat.PMX) { //PMX this.NameJP = PMXParser.ReadString(br, importSettings.TextEncoding); this.NameEN = PMXParser.ReadString(br, importSettings.TextEncoding); this.Position = PMXVector3.LoadFromStreamStatic(br); this.parentIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.Layer = br.ReadInt32(); short flags = br.ReadInt16(); this.HasChildBone = ((flags & PMXBone.BONE_TAILPOS_IS_BONE) != 0); if (this.HasChildBone) { this.childBoneIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); } else { this.ChildVector = PMXVector3.LoadFromStreamStatic(br); } this.Rotatable = ((flags & PMXBone.BONE_CAN_ROTATE) != 0); this.Translatable = ((flags & PMXBone.BONE_CAN_TRANSLATE) != 0); this.Visible = ((flags & PMXBone.BONE_IS_VISIBLE) != 0); this.Operating = ((flags & PMXBone.BONE_CAN_MANIPULATE) != 0); bool extRotation = ((flags & PMXBone.BONE_IS_EXTERNAL_ROTATION) != 0); bool extTranslation = ((flags & PMXBone.BONE_IS_EXTERNAL_TRANSLATION) != 0); int rotFlag = 0; if (extRotation) { rotFlag |= 1; } if (extTranslation) { rotFlag |= 2; } this.ExternalModificationType = (BoneExternalModificationType)rotFlag; if (this.ExternalModificationType != BoneExternalModificationType.None) { this.externalBoneIndex = PMXParser.ReadIndex(br, importSettings.BitSettings.BoneIndexLength); this.ExternalBoneEffect = br.ReadSingle(); } this.FixedAxis = ((flags & PMXBone.BONE_HAS_FIXED_AXIS) != 0); if (this.FixedAxis) { this.AxisLimit = PMXVector3.LoadFromStreamStatic(br); } this.LocalCoordinates = ((flags & PMXBone.BONE_HAS_LOCAL_COORDINATE) != 0); if (this.LocalCoordinates) { this.LocalCoordinatesX = PMXVector3.LoadFromStreamStatic(br); this.LocalCoordinatesZ = PMXVector3.LoadFromStreamStatic(br); } this.HasExternalParent = ((flags & PMXBone.BONE_IS_EXTERNAL_PARENT_DEFORM) != 0); if (this.HasExternalParent) { this.ExternalParentKey = br.ReadInt32(); } this.TransformPhysicsFirst = ((flags & PMXBone.BONE_IS_AFTER_PHYSICS_DEFORM) != 0); bool isIKBone = ((flags & PMXBone.BONE_IS_IK) != 0); if (isIKBone) { PMXIK ikData = new PMXIK(this.Model, this); ikData.LoadFromStream(br, importSettings); this.IK = ikData; } else { this.IK = null; } } else { //PMD this.NameJP = PMDParser.ReadString(br, 20, importSettings.TextEncoding); this.parentIndex = br.ReadInt16(); this.HasChildBone = true; this.childBoneIndex = br.ReadUInt16(); byte type = br.ReadByte(); ushort ikIndex = br.ReadUInt16(); this.Position = PMXVector3.LoadFromStreamStatic(br); switch (type) { case PMD_BONE_TYPE_ROTATE: //Default break; case PMD_BONE_TYPE_ROTATE_MOVE: this.Translatable = true; break; case PMD_BONE_TYPE_IK: //IK parameters will be initialised later this.Translatable = true; break; case PMD_BONE_TYPE_IK_CHILD: //PMX doesn't even bother about these break; case PMD_BONE_TYPE_EXTERNAL_ROTATOR: this.ExternalModificationType = BoneExternalModificationType.Rotation; this.externalBoneIndex = (int)ikIndex; break; case PMD_BONE_TYPE_IK_TARGET: //PMX doesn't bother either this.Visible = false; break; case PMD_BONE_TYPE_INVISIBLE: this.Visible = false; break; case PMD_BONE_TYPE_TWIST: //PMX handles these differently this._isPMDTwist = true; break; case PMD_BONE_TYPE_TWIST_INVISIBLE: //PMX handles these differently this._isPMDTwist = true; this.Visible = false; break; } } }
/// <summary> /// Saves a model to a stream. /// </summary> /// <param name="stream"></param> public void SaveToStream(Stream stream) { List <string> requiredTextureList = new List <string>(); //List of textures to export int triangleCount = 0; foreach (PMXMaterial mat in this.Materials) { this.AddToListIfRequired(requiredTextureList, mat.DiffuseTexture); this.AddToListIfRequired(requiredTextureList, mat.SphereTexture); if (!mat.StandardToon) { this.AddToListIfRequired(requiredTextureList, mat.NonStandardToonTexture); } triangleCount += mat.Triangles.Count; } int maxAddUV = 0; foreach (PMXVertex v in this.Vertices) { maxAddUV = Math.Max(v.AddedUVs.Count, maxAddUV); } if (maxAddUV > 4) { throw new InvalidDataException("Maximum Add UV data is 4"); } MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); byte[] magic = Encoding.ASCII.GetBytes("PMX "); stream.Write(magic, 0, 4); Random rnd = new Random(); int randomNumber = rnd.Next(); MMDExportSettings settings = new MMDExportSettings(MMDExportSettings.ModelFormat.PMX); settings.Model = this; settings.ExportHash = randomNumber; settings.ExtendedUV = (byte)maxAddUV; float version = 2.0f; foreach (PMXJoint j in this.Joints) { if (j.Type != PMXJoint.JointType.SpringSixDOF) { version = 2.1f; break; } } bw.Write(version); //Flag length bw.Write((byte)8); //Encoding (UTF-16 LE only) settings.TextEncoding = Encoding.Unicode; bw.Write((byte)0); bw.Write((byte)settings.ExtendedUV); settings.BitSettings.VertexIndexLength = this.DetermineRequiredBitLength(this.Vertices.Count); settings.BitSettings.TextureIndexLength = this.DetermineRequiredBitLength(requiredTextureList.Count); settings.BitSettings.MaterialIndexLength = this.DetermineRequiredBitLength(this.Materials.Count); settings.BitSettings.BoneIndexLength = this.DetermineRequiredBitLength(this.Bones.Count); settings.BitSettings.MorphIndexLength = this.DetermineRequiredBitLength(this.Morphs.Count); settings.BitSettings.RigidBodyIndexLength = this.DetermineRequiredBitLength(this.RigidBodies.Count); bw.Write(settings.BitSettings.VertexIndexLength); bw.Write(settings.BitSettings.TextureIndexLength); bw.Write(settings.BitSettings.MaterialIndexLength); bw.Write(settings.BitSettings.BoneIndexLength); bw.Write(settings.BitSettings.MorphIndexLength); bw.Write(settings.BitSettings.RigidBodyIndexLength); PMXParser.WriteString(bw, settings.TextEncoding, this.NameJP); PMXParser.WriteString(bw, settings.TextEncoding, this.NameEN); PMXParser.WriteString(bw, settings.TextEncoding, this.DescriptionJP); PMXParser.WriteString(bw, settings.TextEncoding, this.DescriptionEN); //Vertices bw.Write((Int32)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); } } //Textures string[] textures = requiredTextureList.ToArray(); bw.Write((Int32)textures.Length); foreach (string textureFile in textures) { PMXParser.WriteString(bw, settings.TextEncoding, textureFile); } //Materials bw.Write((Int32)this.Materials.Count); foreach (PMXMaterial mat in this.Materials) { mat.WriteToStream(bw, settings, textures); } //Bones bw.Write((Int32)this.Bones.Count); foreach (PMXBone bn in this.Bones) { bn.WriteToStream(bw, settings); } //Morphs bw.Write((Int32)this.Morphs.Count); foreach (PMXMorph mrph in this.Morphs) { mrph.WriteToStream(bw, settings); } //Displays bw.Write((Int32)this.DisplaySlots.Count); foreach (PMXDisplaySlot dsp in this.DisplaySlots) { dsp.WriteToStream(bw, settings); } //Rigid bodies bw.Write((Int32)this.RigidBodies.Count); foreach (PMXRigidBody bdy in this.RigidBodies) { bdy.WriteToStream(bw, settings); } //Joints bw.Write((Int32)this.Joints.Count); foreach (PMXJoint jt in this.Joints) { jt.WriteToStream(bw, settings); } //Reset triangles 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; }