MMDのVMDファイルフォーマットの詳細

9081 ワード

MMDのVMDファイルフォーマットの詳細

  • MMDのVMDファイルフォーマットの詳細
  • Header
  • KeyFrameRecord
  • BoneKeyFrameRecord(byte*111)
  • MorphKeyFrameRecord(byte*47)
  • CameraKeyFrameRecord(byte*61)
  • LightKeyFrameRecord(byte*28)
  • Java Code

  • MMDのVMDファイルフォーマットの詳細


    VMDはバイナリ・ストリームのファイルです.

    Header


    VMDには2つのバージョンがあり、v 1とv 2と考えられます.最初の30バイトはバージョン記述です.ASCII符号化v 1は「Vocaloid Motion Data file」v 2は「Vocaloid Motion Data 0002」
    次は名前、ShiftJISコードv 1は10バイト、v 2は20バイト
    次のセクションの先頭はuint 32です.tは、この部分にどれだけのキーフレームがあるかを記録する.この項目は0(省略ではなく)と記録されていません.その後、対応する数の記録に従います.
    を選択します.
    説明する
    byte*30
    VersionInformation
    byte*(10/20)
    ModelName
    uint32_t
    BoneKeyFrameNumber
    byte * 111 * n
    BoneKeyFrameRecord
    uint32_t
    MorphKeyFrameNumber
    byte* 47 *n
    MorphKeyFrameRecord
    uint32_t
    CameraKeyFrameNumber
    byte* 61 *n
    CameraKeyFrameRecord
    uint32_t
    LightKeyFrameNumber
    byte* 28 *n
    LightKeyFrameRecord

    KeyFrameRecord


    BoneKeyFrameRecord(byte*111)


    を選択します.
    説明する
    byte*15(ShiftJIS)
    BoneName
    uint32_t
    FrameTime
    float*3
    Translation.xyz
    float*4
    Rotation.xyzw
    uint8_t*16
    XCurve
    uint8_t*16
    YCurve
    uint8_t*16
    ZCurve
    uint8_t*16
    RCurve
    uint8_tには冗長性があります.4つごとに1つだけ読めばいいです.

    MorphKeyFrameRecord(byte*47)


    を選択します.
    説明する
    byte*15(ShiftJIS)
    MorphName
    uint32_t
    FrameTime
    float
    Weight

    CameraKeyFrameRecord(byte*61)


    を選択します.
    説明する
    uint32_t
    FrameTime
    float
    Distance
    float*3
    Position.xyz
    float*3
    Rotation.xyz
    uint8_t*24
    Curve
    float
    ViewAngle
    uint8_t
    Orthographic

    LightKeyFrameRecord(byte*28)


    を選択します.
    説明する
    uint32_t
    FrameTime
    float*3
    Color.rgb
    float*3
    Direction.xyz

    Java Code

    package com.company;
    
    import java.io.*;
    import java.nio.ByteBuffer;
    
    public class Main {
    
        public static void main(String[] args) {
            try {
                FileInputStream fis = new FileInputStream("test.vmd");
                BufferedInputStream bis = new BufferedInputStream(fis);
                DataInputStream dis = new DataInputStream(bis);
    
                String headerString = readString(dis, 30);
    
                int version = 0;
                String modelName = null;
    
                if (headerString.startsWith("Vocaloid Motion Data file")){
                    version = 1;
                    modelName = readString(dis, 10);
                }else if (headerString.startsWith("Vocaloid Motion Data 0002")){
                    version = 2;
                    modelName = readString(dis, 20);
                }else{
                    throw new IOException("VmdReader: Not A VMD File!");
                }
    
                int numOfBoneRecord = readInt(dis);
    
                for (int i = 0; i < numOfBoneRecord; i++){
    
                    String BoneRecordNameString = readString(dis, 15);
    
                    int frameTime = readInt(dis);
    
                    float tx = readFloat(dis);
                    float ty = readFloat(dis);
                    float tz = readFloat(dis);
    
                    float rx = readFloat(dis);
                    float ry = readFloat(dis);
                    float rz = readFloat(dis);
                    float rw = readFloat(dis);
    
                    int txc1 = dis.readByte();
                    dis.skipBytes(3);
                    int txc2 = dis.readByte();
                    dis.skipBytes(3);
                    int txc3 = dis.readByte();
                    dis.skipBytes(3);
                    int txc4 = dis.readByte();
                    dis.skipBytes(3);
    
                    int tyc1 = dis.readByte();
                    dis.skipBytes(3);
                    int tyc2 = dis.readByte();
                    dis.skipBytes(3);
                    int tyc3 = dis.readByte();
                    dis.skipBytes(3);
                    int tyc4 = dis.readByte();
                    dis.skipBytes(3);
    
                    int tzc1 = dis.readByte();
                    dis.skipBytes(3);
                    int tzc2 = dis.readByte();
                    dis.skipBytes(3);
                    int tzc3 = dis.readByte();
                    dis.skipBytes(3);
                    int tzc4 = dis.readByte();
                    dis.skipBytes(3);
    
                    int rc1 = dis.readByte();
                    dis.skipBytes(3);
                    int rc2 = dis.readByte();
                    dis.skipBytes(3);
                    int rc3 = dis.readByte();
                    dis.skipBytes(3);
                    int rc4 = dis.readByte();
                    dis.skipBytes(3);
                }
                int numOfMorphRecord = readInt(dis);
                for (int i = 0; i < numOfMorphRecord; i++){
                    String name = readString(dis, 15);
                    int frameTime = readInt(dis);
                    float weight = readFloat(dis);
                }
                int numOfCameraRecord = readInt(dis);
                for (int i = 0; i < numOfCameraRecord; i++){
                    int frameTime = readInt(dis);
    
                    float distance = readFloat(dis);
    
                    float px = readFloat(dis);
                    float py = readFloat(dis);
                    float pz = readFloat(dis);
    
                    float rx = readFloat(dis);
                    float ry = readFloat(dis);
                    float rz = readFloat(dis);
    
                    int txc1 = dis.readByte();
                    int txc2 = dis.readByte();
                    int txc3 = dis.readByte();
                    int txc4 = dis.readByte();
    
                    int tyc1 = dis.readByte();
                    int tyc2 = dis.readByte();
                    int tyc3 = dis.readByte();
                    int tyc4 = dis.readByte();
    
                    int tzc1 = dis.readByte();
                    int tzc2 = dis.readByte();
                    int tzc3 = dis.readByte();
                    int tzc4 = dis.readByte();
    
                    int qc1 = dis.readByte();
                    int qc2 = dis.readByte();
                    int qc3 = dis.readByte();
                    int qc4 = dis.readByte();
    
                    int dc1 = dis.readByte();
                    int dc2 = dis.readByte();
                    int dc3 = dis.readByte();
                    int dc4 = dis.readByte();
    
                    int vc1 = dis.readByte();
                    int vc2 = dis.readByte();
                    int vc3 = dis.readByte();
                    int vc4 = dis.readByte();
    
                    float viewAngle = readFloat(dis);
                    byte orthographic = dis.readByte();
    
                }
    
    
    
    
            } catch (IOException e) {
                System.err.println(e);
                e.printStackTrace();
            }
    
        }
    
        private static int readInt(DataInputStream stream) throws IOException {
            byte intBytes[] = new byte[4];
            stream.read(intBytes);
            for (int j = 0; j < intBytes.length/2; j++){
                byte temp = intBytes[j];
                intBytes[j] = intBytes[intBytes.length -1 -j];
                intBytes[intBytes.length -1 -j] = temp;
            }
            return ByteBuffer.wrap(intBytes).getInt();
        }
        private static float readFloat(DataInputStream stream) throws IOException {
            byte floatBytes[] = new byte[4];
            stream.read(floatBytes);
            for (int j = 0; j < floatBytes.length/2; j++){
                byte temp = floatBytes[j];
                floatBytes[j] = floatBytes[floatBytes.length -1 -j];
                floatBytes[floatBytes.length -1 -j] = temp;
            }
            return ByteBuffer.wrap(floatBytes).getFloat();
        }
    
        private static String readString(DataInputStream stream, int length) throws IOException {
            byte[] name = new byte[length];
            stream.read(name);
            String nameString = new String(name, "Shift-jis");
            int indexOfNull = nameString.indexOf('\0');
            if (indexOfNull != -1){
                nameString = nameString.substring(0, indexOfNull);
            }
            return nameString;
        }
        private static String readString(DataInputStream stream, boolean utf8) throws IOException {
            int length = readInt(stream);
            byte[] name = new byte[length];
            stream.read(name);
            String string = null;
            if (utf8== false){
                for (int i = 0; i < name.length; i+=2){
                    byte temp = name[i];
                    name[i] = name[i+1];
                    name[i+1] = temp;
                }
                string = new String(name, "utf-16");
            }else{
                string = new String(name, "utf-8");
            }
            return string;
        }
    /*
        private static Vector2f readVector2f(DataInputStream stream) throws IOException {
            float x = readFloat(stream);
            float y = readFloat(stream);
            return new Vector3f(x,y);
        }
    
        private static Vector3f readVector3f(DataInputStream stream) throws IOException {
            float x = readFloat(stream);
            float y = readFloat(stream);
            float z = readFloat(stream);
            return new Vector3f(x,y,z);
        }
    */
    
    }