Skip to content

Instantly share code, notes, and snippets.

@ousttrue
Created January 12, 2015 20:48
Show Gist options
  • Save ousttrue/f8a6e05e8db5c55f7aa0 to your computer and use it in GitHub Desktop.
Save ousttrue/f8a6e05e8db5c55f7aa0 to your computer and use it in GitHub Desktop.
PmdModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VVVV.Utils.VColor;
using VVVV.Utils.VMath;
using SlimDX;
namespace VVVV.Nodes
{
static class MathExtensions
{
public static Vector3D ToVVVV(this SlimDX.Vector3 src)
{
return new Vector3D(src.X, src.Y, src.Z);
}
public static Vector2D ToVVVV(this SlimDX.Vector2 src)
{
return new Vector2D(src.X, src.Y);
}
}
public class CustomBinaryReader : System.IO.BinaryReader
{
public CustomBinaryReader(System.IO.Stream s)
: base(s)
{
}
public String ReadStringBytes(int length, Encoding encoding=null)
{
if (encoding == null)
{
encoding = Encoding.ASCII;
}
return encoding.GetString(ReadBytes(length).TakeWhile(b => b!=0).ToArray());
}
public RGBAColor ReadColor3()
{
return new RGBAColor(ReadSingle(), ReadSingle(), ReadSingle(), 1.0f);
}
public RGBAColor ReadColor4()
{
return new RGBAColor(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle());
}
}
public class PmdModel
{
public struct Vertex
{
public Vector3 Position;
public Vector3 Normal;
public Vector2 UV;
public Color4 Color;
public Single EdgeFactor;
}
public enum SkinningType
{
BDEF1,
BDEF2,
BDEF4,
SDEF,
}
public struct Skinning
{
public SkinningType SkinningType;
public Int32[] BoneIndices;
public Single[] BoneWeights;
public Vector3 SdefC;
public Vector3 SdefR0;
public Vector3 SdefR1;
}
[Flags]
public enum MaterialFlag : byte
{
None = 0,
BothSide = 1,
GroundShadow = 1 << 1,
SelfShadowMap = 1 << 2,
SelfShadow = 1 << 3,
Edge = 1 << 4,
}
public enum SphereMode : byte
{
None = 0,
Mul = 1,
Add = 2,
SubTexture = 3,
}
public enum ToonMode : byte
{
Own = 0,
Shared = 1,
}
public class Material
{
public String Name { get; set; }
public String NameEnglish { get; set; }
public Color4 Diffuse { get; set; }
public Color3 Specular { get; set; }
public Single Shininess { get; set; }
public Color3 Ambient { get; set; }
public MaterialFlag Flags { get; set; }
public Color4 EdgeColor { get; set; }
public Single EdgeSize { get; set; }
public Int32 TextureIndex { get; set; }
public Int32 SphereTextureIndex { get; set; }
public SphereMode SphereMode { get; set; }
public ToonMode ToonMode { get; set; }
public Int32 ToonTextureIndex { get; set; }
public String Comment { get; set; }
}
public class SubMesh
{
public Int32 Count { get; set; }
public Int32 Offset { get; set; }
public SubMesh(int count, int offset = 0)
{
Count = count;
Offset = offset;
}
}
public String Path { get; set; }
public Single FormatVersion { get; set; }
public String Name { get; set; }
public String NameEnglish { get; set; }
public String Comment { get; set; }
public String CommentEnglish { get; set; }
public List<Vertex> Vertices { get; set; }
public List<Int32> Indices { get; set; }
public List<Skinning> SkinningList { get; set; }
public List<String> Textures { get; set; }
public List<Material> Materials { get; set; }
public List<SubMesh> SubMeshes { get; set; }
public PmdModel()
{
}
public override string ToString()
{
return String.Format("[{0}: {1}verts]", Name, Vertices.Count);
}
public static PmdModel Load(String path)
{
using(var s=new System.IO.FileStream(path, System.IO.FileMode.Open)){
if(s!=null){
var bytes=new Byte[s.Length];
s.Read(bytes, 0, bytes.Length);
var model=Load(bytes);
if (model != null)
{
model.Path = path;
}
return model;
}
}
return null;
}
public static PmdModel Load(Byte[] bytes)
{
var model = new PmdModel();
var r = new CustomBinaryReader(new System.IO.MemoryStream(bytes));
var magic = r.ReadStringBytes(3);
if (magic != "Pmd")
{
return null;
}
model.FormatVersion = r.ReadSingle();
var cp932Encoding=Encoding.GetEncoding(932);
model.Name = r.ReadStringBytes(20, cp932Encoding);
model.Comment = r.ReadStringBytes(256, cp932Encoding);
var vertexCount = r.ReadInt32();
model.Vertices = new List<Vertex>(vertexCount);
model.SkinningList = new List<Skinning>(vertexCount);
for (int i = 0; i < vertexCount; ++i)
{
var vertex=new Vertex
{
Position = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()),
Normal = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()),
UV = new Vector2(r.ReadSingle(), r.ReadSingle()),
};
var skinning=new Skinning
{
BoneIndices = new Int32[] { r.ReadUInt16(), r.ReadUInt16() },
};
var weight = r.ReadByte() / 255.0f;
skinning.BoneWeights = new[] { weight, 1.0f - weight };
vertex.EdgeFactor = r.ReadByte();
model.Vertices.Add(vertex);
model.SkinningList.Add(skinning);
}
var indexCount=r.ReadInt32();
model.Indices = Enumerable.Range(0, indexCount)
.Select(_ => (int)r.ReadUInt16()).ToList();
return model;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment