internal void WriteExpantion(BinaryWriter writer, float CoordZ, float scale) { Position[2] *= CoordZ; Rotation[0] *= CoordZ; Rotation[1] *= CoordZ; writer.Write(MMDModel1.GetBytes(Name, 20)); writer.Write(RelatedBoneIndex); writer.Write(GroupIndex); writer.Write(GroupTarget); writer.Write(ShapeType); writer.Write(ShapeWidth * scale); writer.Write(ShapeHeight * scale); writer.Write(ShapeDepth * scale); for (int i = 0; i < Position.Length; i++) { writer.Write(Position[i] * scale); } for (int i = 0; i < Rotation.Length; i++) { writer.Write(Rotation[i]); } writer.Write(Weight); writer.Write(LinerDamping); writer.Write(AngularDamping); writer.Write(Restitution); writer.Write(Friction); writer.Write(Type); }
internal void Write(BinaryWriter writer) { for (int i = 0; i < DiffuseColor.Length; i++) { writer.Write(DiffuseColor[i]); } writer.Write(Alpha); writer.Write(Specularity); for (int i = 0; i < SpecularColor.Length; i++) { writer.Write(SpecularColor[i]); } for (int i = 0; i < MirrorColor.Length; i++) { writer.Write(MirrorColor[i]); } writer.Write(ToonIndex); writer.Write(EdgeFlag); writer.Write(FaceVertCount); string FileName = TextureFileName; if (string.IsNullOrEmpty(FileName)) { FileName = SphereTextureFileName; } else { if (!string.IsNullOrEmpty(SphereTextureFileName)) { FileName += "*" + SphereTextureFileName; } } writer.Write(MMDModel1.GetBytes(FileName, 20)); }
internal void ReadExpantion(BinaryReader reader, float CoordZ, float scale) { Name = MMDModel1.GetString(reader.ReadBytes(20)); RelatedBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); GroupIndex = reader.ReadByte(); GroupTarget = BitConverter.ToUInt16(reader.ReadBytes(2), 0); ShapeType = reader.ReadByte(); ShapeWidth = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; ShapeHeight = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; ShapeDepth = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; for (int i = 0; i < Position.Length; i++) { Position[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; } for (int i = 0; i < Rotation.Length; i++) { Rotation[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } Weight = BitConverter.ToSingle(reader.ReadBytes(4), 0); LinerDamping = BitConverter.ToSingle(reader.ReadBytes(4), 0); AngularDamping = BitConverter.ToSingle(reader.ReadBytes(4), 0); Restitution = BitConverter.ToSingle(reader.ReadBytes(4), 0); Friction = BitConverter.ToSingle(reader.ReadBytes(4), 0); Type = reader.ReadByte(); Position[2] *= CoordZ; //メモ:左手→右手では位置が変換される際に一緒に回転成分が変換されるため、回転の変換は必要ない……のだが //剛体はモデルと違い、位置と回転情報だけなので、回転を変換する必要がある Rotation[0] *= CoordZ; Rotation[1] *= CoordZ; }
internal void Read(BinaryReader reader) { //モデル名 ModelName = MMDModel1.GetString(reader.ReadBytes(20)); //コメント Comment = MMDModel1.GetString(reader.ReadBytes(256)); }
internal void Write(BinaryWriter writer, float CoordZ, float scale) { writer.Write(MMDModel1.GetBytes(SkinName, 20)); writer.Write((DWORD)SkinVertDatas.Length); writer.Write(SkinType); for (int i = 0; i < SkinVertDatas.Length; i++) { SkinVertDatas[i].Write(writer, CoordZ, scale); } }
internal void Write(BinaryWriter writer, float CoordZ, float scale) { BoneHeadPos[2] = BoneHeadPos[2] * CoordZ * scale; writer.Write(MMDModel1.GetBytes(BoneName, 20)); writer.Write(ParentBoneIndex); writer.Write(TailPosBoneIndex); writer.Write(BoneType); writer.Write(IKParentBoneIndex); for (int i = 0; i < BoneHeadPos.Length; i++) { writer.Write(BoneHeadPos[i]); } }
} //表示名(char[20]、英語)(拡張) internal void Read(BinaryReader reader, float CoordZ, float scale) { SkinName = MMDModel1.GetString(reader.ReadBytes(20)); DWORD skin_vert_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); SkinType = reader.ReadByte(); SkinVertDatas = new ModelSkinVertexData[skin_vert_count]; for (int i = 0; i < SkinVertDatas.Length; i++) { SkinVertDatas[i] = new ModelSkinVertexData(); SkinVertDatas[i].Read(reader, CoordZ, scale); } SkinNameEnglish = null; }
internal void Read(BinaryReader reader, float CoordZ, float scale) { BoneHeadPos = new float[3]; BoneName = MMDModel1.GetString(reader.ReadBytes(20)); ParentBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); TailPosBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); BoneType = reader.ReadByte(); IKParentBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); for (int i = 0; i < BoneHeadPos.Length; i++) { BoneHeadPos[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; } //英名拡張はReadではnullにする(あるならReadEngilishで上書きされる) BoneNameEnglish = null; BoneHeadPos[2] = BoneHeadPos[2] * CoordZ; }
internal void ReadExpantion(BinaryReader reader, float CoordZ, float scale) { Name = MMDModel1.GetString(reader.ReadBytes(20)); RigidBodyA = BitConverter.ToUInt32(reader.ReadBytes(4), 0); RigidBodyB = BitConverter.ToUInt32(reader.ReadBytes(4), 0); for (int i = 0; i < Position.Length; i++) { Position[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; } for (int i = 0; i < Rotation.Length; i++) { Rotation[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } for (int i = 0; i < ConstrainPosition1.Length; i++) { ConstrainPosition1[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; } for (int i = 0; i < ConstrainPosition2.Length; i++) { ConstrainPosition2[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; } for (int i = 0; i < ConstrainRotation1.Length; i++) { ConstrainRotation1[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } for (int i = 0; i < ConstrainRotation2.Length; i++) { ConstrainRotation2[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } for (int i = 0; i < SpringPosition.Length; i++) { SpringPosition[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } for (int i = 0; i < SpringRotation.Length; i++) { SpringRotation[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } Position[2] *= CoordZ; //メモ:左手→右手では位置が変換される際に一緒に回転成分が変換されるため、回転の変換は必要ない //ただし、ジョイントの回転(使用してないっぽい)は変換しておく ConstrainRotation1[0] *= CoordZ; ConstrainRotation1[1] *= CoordZ; ConstrainRotation2[0] *= CoordZ; ConstrainRotation2[1] *= CoordZ; ConstrainPosition1[2] *= CoordZ; ConstrainPosition2[2] *= CoordZ; }
internal void WriteExpantion(BinaryWriter writer, float CoordZ, float scale) { Position[2] *= CoordZ; ConstrainRotation1[0] *= CoordZ; ConstrainRotation1[1] *= CoordZ; ConstrainRotation2[0] *= CoordZ; ConstrainRotation2[1] *= CoordZ; ConstrainPosition1[2] *= CoordZ; ConstrainPosition2[2] *= CoordZ; writer.Write(MMDModel1.GetBytes(Name, 20)); writer.Write(RigidBodyA); writer.Write(RigidBodyB); for (int i = 0; i < Position.Length; i++) { writer.Write(Position[i] * scale); } for (int i = 0; i < Rotation.Length; i++) { writer.Write(Rotation[i]); } for (int i = 0; i < ConstrainPosition1.Length; i++) { writer.Write(ConstrainPosition1[i] * scale); } for (int i = 0; i < ConstrainPosition2.Length; i++) { writer.Write(ConstrainPosition2[i] * scale); } for (int i = 0; i < ConstrainRotation1.Length; i++) { writer.Write(ConstrainRotation1[i]); } for (int i = 0; i < ConstrainRotation2.Length; i++) { writer.Write(ConstrainRotation2[i]); } for (int i = 0; i < SpringPosition.Length; i++) { writer.Write(SpringPosition[i] * scale); } for (int i = 0; i < SpringRotation.Length; i++) { writer.Write(SpringRotation[i]); } }
internal void Read(BinaryReader reader) { DiffuseColor = new float[3]; SpecularColor = new float[3]; MirrorColor = new float[3]; for (int i = 0; i < DiffuseColor.Length; i++) { DiffuseColor[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } Alpha = BitConverter.ToSingle(reader.ReadBytes(4), 0); Specularity = BitConverter.ToSingle(reader.ReadBytes(4), 0); for (int i = 0; i < SpecularColor.Length; i++) { SpecularColor[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } for (int i = 0; i < MirrorColor.Length; i++) { MirrorColor[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); } ToonIndex = reader.ReadByte(); EdgeFlag = reader.ReadByte(); FaceVertCount = BitConverter.ToUInt32(reader.ReadBytes(4), 0); string FileName = MMDModel1.GetString(reader.ReadBytes(20)); string[] FileNames = FileName.Split('*'); TextureFileName = ""; SphereTextureFileName = ""; foreach (string s in FileNames) { string ext = Path.GetExtension(s).ToLower(); if (ext == ".sph" || ext == ".spa") { SphereTextureFileName = s.Trim(); } else { TextureFileName = s.Trim(); } } }
/// <summary> /// ファイルからMMDモデルを読み込む /// </summary> /// <param name="filename">MMDモデルファイル</param> /// <param name="coordinate">変換先座標系</param> /// <param name="scale">スケーリング値</param> /// <returns>MMDモデルオブジェクト</returns> /// <remarks>MMDの座標系は右手座標系です</remarks> public static MMDModel Read(string filename, CoordinateType coordinate, float scale=1f) { //フルパス取得 filename = Path.GetFullPath(filename); //ファイルチェック if (!File.Exists(filename)) throw new FileNotFoundException("MMDモデルファイル:" + filename + "が見つかりません"); //戻り値用変数 MMDModel result = null; //ファイルリーダー using (FileStream fs = new FileStream(filename, FileMode.Open)) { BinaryReader reader = new BinaryReader(fs); //マジック文字列 string magic = MMDModel1.encoder.GetString(reader.ReadBytes(3)); if (magic != "Pmd") throw new FileLoadException("MMDモデルファイルではありません"); //バージョン float version = BitConverter.ToSingle(reader.ReadBytes(4), 0); if (OriginalObjects.ContainsKey(version) && OriginalObjects[version].BaseType == typeof(MMDModel)) {//このバージョンで使用し、利用可能型 result = (MMDModel)OriginalObjects[version].InvokeMember(null, System.Reflection.BindingFlags.CreateInstance, null, null, null); } else { if (version == 1.0) result = new MMDModel1(); else throw new FileLoadException("version=" + version.ToString() + "モデルは対応していません"); } result.Read(reader, coordinate, scale); if (fs.Length != fs.Position) Console.WriteLine("警告:ファイル末尾以降に不明データ?"); fs.Close(); } return result; }
internal void WriteExpantion(BinaryWriter writer) { writer.Write(MMDModel1.GetBytes(BoneDispNameEnglish, 50)); }
internal void Write(BinaryWriter writer) { writer.Write(MMDModel1.GetBytes(ModelName, 20)); writer.Write(MMDModel1.GetBytes(Comment, 256)); }
public static MeshContent BuildMesh(MMDModel1 model, string filename) { //メッシュ作成 MeshContent buildingMesh = new MeshContent(); //まずは頂点を登録。 //ひげねこ氏によるとモデルごとのローカル座標である必要があるようだが //pmdはモデル一つ=変換必要なし foreach (var vec in model.Vertexes) buildingMesh.Positions.Add(MMDXMath.ToVector3(vec.Pos)); //ジオメトリとマテリアルの作成 //メモ:頂点が3つ合わさって面、面が幾つか集まってジオメトリ。ジオメトリにマテリアルが付随。ジオメトリの集合がメッシュ long FaceIndex = 0; Dictionary<ushort, int> vertMap = new Dictionary<ushort, int>(); //ジオメトリとマテリアルの生成 for (int i = 0; i < model.Materials.Length; i++) { GeometryContent geometry = new GeometryContent(); BasicMaterialContent material = new BasicMaterialContent(); geometry.Material = material; //マテリアル設定 material.VertexColorEnabled = false;//頂点カラー無し material.Alpha = model.Materials[i].Alpha; material.DiffuseColor = MMDXMath.ToVector3(model.Materials[i].DiffuseColor); material.EmissiveColor = MMDXMath.ToVector3(model.Materials[i].MirrorColor); material.SpecularColor = MMDXMath.ToVector3(model.Materials[i].SpecularColor); material.SpecularPower = model.Materials[i].Specularity; if (!string.IsNullOrEmpty(model.Materials[i].TextureFileName)) material.Texture = new ExternalReference<TextureContent>(NormalizeFilepath(model.Materials[i].TextureFileName, filename)); if (!string.IsNullOrEmpty(model.Materials[i].SphereTextureFileName)) { if (Path.GetExtension(model.Materials[i].SphereTextureFileName).ToLower() == ".sph") { material.OpaqueData.Add("UseSphere", 1); } else if (Path.GetExtension(model.Materials[i].SphereTextureFileName).ToLower() == ".spa") { material.OpaqueData.Add("UseSphere", 2); } else throw new InvalidContentException("スフィアマップは*.sph, *.spaのみ指定可能です: " + model.Materials[i].SphereTextureFileName); material.Textures.Add("Sphere", new ExternalReference<TextureContent>(ProcessSphere(NormalizeFilepath(model.Materials[i].SphereTextureFileName, filename)))); } else { material.OpaqueData.Add("UseSphere", 0); } //トゥーンのテクスチャを入れる string toonTexPath = ToonTexManager.Instance.GetToonTexPath(model.Materials[i].ToonIndex, model.ToonFileNames, filename); if (!string.IsNullOrEmpty(toonTexPath)) { material.Textures.Add("ToonTex", new ExternalReference<TextureContent>(toonTexPath)); material.OpaqueData.Add("UseToon", true); } else material.OpaqueData.Add("UseToon", false); //一応エッジ情報突っ込んでおく material.OpaqueData.Add("Edge", (model.Materials[i].EdgeFlag != 0)); //ジオメトリのチャンネル設定 //法線 geometry.Vertices.Channels.Add(VertexChannelNames.Normal(0), typeof(Vector3), null); //テクスチャ if (!string.IsNullOrEmpty(model.Materials[i].TextureFileName)) geometry.Vertices.Channels.Add(VertexChannelNames.TextureCoordinate(0), typeof(Vector2), null); //ボーンウェイト geometry.Vertices.Channels.Add(VertexChannelNames.Weights(0), typeof(BoneWeightCollection), null); //面と頂点をジオメトリに登録 //このマテリアルに対応する面は今までのマテリアルの面数の合計からこのマテリアルの面数個分 vertMap.Clear(); //マテリアルに付随する面を取得 for (long j = FaceIndex; j < FaceIndex + model.Materials[i].FaceVertCount; j++) { //面から頂点番号取得 ushort VertIndex = model.FaceVertexes[j]; //ジオメトリに登録済みかどうか? int geoVertIndex; if (!vertMap.TryGetValue(VertIndex, out geoVertIndex)) { //未登録なので、ジオメトリに登録し、ジオメトリ頂点番号取得 geoVertIndex = geometry.Vertices.Add(VertIndex); //頂点マップに登録 vertMap.Add(VertIndex, geoVertIndex); //チャンネル情報の登録 int channelIndex = 0; //法線登録 geometry.Vertices.Channels.Get<Vector3>(channelIndex++)[geoVertIndex] = MMDXMath.ToVector3(model.Vertexes[VertIndex].NormalVector); //テクスチャ座標 if (!string.IsNullOrEmpty(model.Materials[i].TextureFileName)) geometry.Vertices.Channels.Get<Vector2>(channelIndex++)[geoVertIndex] = MMDXMath.ToVector2(model.Vertexes[VertIndex].UV); //ボーンウェイト BoneWeightCollection boneWeight = new BoneWeightCollection(); int boneNum = model.Vertexes[VertIndex].BoneNum[0]; if (boneNum >= 0 && boneNum < model.Bones.Length) boneWeight.Add(new BoneWeight(model.Bones[boneNum].BoneName, model.Vertexes[VertIndex].BoneWeight / 100f)); boneNum = model.Vertexes[VertIndex].BoneNum[1]; if (boneNum >= 0 && boneNum < model.Bones.Length) boneWeight.Add(new BoneWeight(model.Bones[boneNum].BoneName, 1.0f - model.Vertexes[VertIndex].BoneWeight / 100f)); geometry.Vertices.Channels.Get<BoneWeightCollection>(channelIndex++)[geoVertIndex] = boneWeight; } //インデックスに登録 geometry.Indices.Add(geoVertIndex); } //ジオメトリをモデルに追加 buildingMesh.Geometry.Add(geometry); //面頂点カウント進める FaceIndex += model.Materials[i].FaceVertCount; } //重複頂点データのマージ //MeshHelper.MergeDuplicatePositions(buildingMesh, 0); //MeshHelper.MergeDuplicateVertices(buildingMesh); //メッシュ出来たので返却 return buildingMesh; }
} //ボーン枠用枠名(英語、拡張) internal void Read(BinaryReader reader) { BoneDispName = MMDModel1.GetString(reader.ReadBytes(50)); BoneDispNameEnglish = null; }
internal void WriteExpantion(BinaryWriter writer) { writer.Write(MMDModel1.GetBytes(ModelNameEnglish, 20)); writer.Write(MMDModel1.GetBytes(CommentEnglish, 256)); }
internal void ReadExpantion(BinaryReader reader) { BoneDispNameEnglish = MMDModel1.GetString(reader.ReadBytes(50)); }
internal void Write(BinaryWriter writer) { writer.Write(MMDModel1.GetBytes(BoneDispName, 50)); }
internal void WriteExpantion(BinaryWriter writer) { writer.Write(MMDModel1.GetBytes(SkinNameEnglish, 20)); }
internal void ReadExpantion(BinaryReader reader) { ModelNameEnglish = MMDModel1.GetString(reader.ReadBytes(20)); CommentEnglish = MMDModel1.GetString(reader.ReadBytes(256)); }
internal void ReadExpantion(BinaryReader reader) { SkinNameEnglish = MMDModel1.GetString(reader.ReadBytes(20)); }