MMDのVMDファイルフォーマットの詳細
9081 ワード
MMDのVMDファイルフォーマットの詳細
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);
}
*/
}
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);
}
*/
}