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) { 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 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 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); }
/// <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; }
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 WriteToStream(BinaryWriter bw, MMDExportSettings exportSettings, string[] textures, string[] defaultToons = null) { if (exportSettings.Format == MMDExportSettings.ModelFormat.PMX) { //PMX Export if (textures == null) { textures = new string[0]; } PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameJP); PMXParser.WriteString(bw, exportSettings.TextEncoding, this.NameEN); this.Diffuse.WriteToStream(bw); bw.Write(this.Alpha); this.Specular.WriteToStream(bw); bw.Write(this.SpecularFactor); this.Ambient.WriteToStream(bw); byte flags = (byte)(((int)this.GroundShadowType) << 6); flags |= (byte)(this.DoubleSided ? PMXMaterial.MATERIAL_DOUBLE_SIDED : 0); flags |= (byte)(this.GroundShadow ? PMXMaterial.MATERIAL_GROUND_SHADOW : 0); flags |= (byte)(this.SelfShadow ? PMXMaterial.MATERIAL_SELF_SHADOW : 0); flags |= (byte)(this.SelfShadowPlus ? PMXMaterial.MATERIAL_SELF_SHADOW_PLUS : 0); flags |= (byte)(this.EdgeEnabled ? PMXMaterial.MATERIAL_EDGE_ENABLED : 0); flags |= (byte)(this.VertexColor ? PMXMaterial.MATERIAL_VERTEX_COLOR : 0); bw.Write(flags); this.EdgeColor.WriteToStream(bw); bw.Write(this.EdgeSize); PMXParser.WriteIndex(bw, exportSettings.BitSettings.TextureIndexLength, this.GetTextureIndex(this.DiffuseTexture, textures)); PMXParser.WriteIndex(bw, exportSettings.BitSettings.TextureIndexLength, this.GetTextureIndex(this.SphereTexture, textures)); bw.Write((byte)this.SphereMode); if (this.StandardToon) { bw.Write((byte)1); bw.Write(this.StandardToonIndex); } else { bw.Write((byte)0); PMXParser.WriteIndex(bw, exportSettings.BitSettings.TextureIndexLength, this.GetTextureIndex(this.NonStandardToonTexture, textures)); } PMXParser.WriteString(bw, exportSettings.TextEncoding, this.Comment); int triangleVerticesCount = (this.Triangles.Count * 3); bw.Write((Int32)triangleVerticesCount); } else { if (defaultToons == null || textures == null) { throw new InvalidDataException("Toon data required for PMD."); } //PMD format this.Diffuse.WriteToStream(bw); bw.Write(this.Alpha); bw.Write(this.SpecularFactor); this.Specular.WriteToStream(bw); this.Ambient.WriteToStream(bw); int toonIndex = -1; string toonFile = null; if (this.StandardToon && this.StandardToonIndex >= 0) { if (this.StandardToonIndex < 10) { toonFile = defaultToons[this.StandardToonIndex]; } } else if (!this.StandardToon) { toonFile = this.NonStandardToonTexture; } if (toonFile != null) { int index = Array.IndexOf <string>(textures, toonFile); if (index >= 0 && index < 10) { toonIndex = index; } } bw.Write((sbyte)toonIndex); bw.Write((byte)(this.EdgeEnabled ? 1 : 0)); bw.Write((Int32)(this.Triangles.Count * 3)); string textureFile = ""; if (this.DiffuseTexture != null) { textureFile += this.DiffuseTexture; } if (this.SphereTexture != null) { textureFile += "*" + this.DiffuseTexture; } PMDParser.WriteString(bw, 20, exportSettings.TextEncoding, textureFile); } }