assimp/code/MMDVmdParser.h

367 lines
8.9 KiB
C++

#pragma once
#include <vector>
#include <string>
#include <memory>
#include <iostream>
#include <fstream>
#include <ostream>
#include "MMDCpp14.h"
namespace vmd
{
/// ボーンフレーム
class VmdBoneFrame
{
public:
/// ボーン名
std::string name;
/// フレーム番号
int frame;
/// 位置
float position[3];
/// 回転
float orientation[4];
/// 補間曲線
char interpolation[4][4][4];
void Read(std::istream* stream)
{
char buffer[15];
stream->read((char*) buffer, sizeof(char)*15);
name = std::string(buffer);
stream->read((char*) &frame, sizeof(int));
stream->read((char*) position, sizeof(float)*3);
stream->read((char*) orientation, sizeof(float)*4);
stream->read((char*) interpolation, sizeof(char) * 4 * 4 * 4);
}
void Write(std::ostream* stream)
{
stream->write((char*)name.c_str(), sizeof(char) * 15);
stream->write((char*)&frame, sizeof(int));
stream->write((char*)position, sizeof(float) * 3);
stream->write((char*)orientation, sizeof(float) * 4);
stream->write((char*)interpolation, sizeof(char) * 4 * 4 * 4);
}
};
/// 表情フレーム
class VmdFaceFrame
{
public:
/// 表情名
std::string face_name;
/// 表情の重み
float weight;
/// フレーム番号
uint32_t frame;
void Read(std::istream* stream)
{
char buffer[15];
stream->read((char*) &buffer, sizeof(char) * 15);
face_name = std::string(buffer);
stream->read((char*) &frame, sizeof(int));
stream->read((char*) &weight, sizeof(float));
}
void Write(std::ostream* stream)
{
stream->write((char*)face_name.c_str(), sizeof(char) * 15);
stream->write((char*)&frame, sizeof(int));
stream->write((char*)&weight, sizeof(float));
}
};
/// カメラフレーム
class VmdCameraFrame
{
public:
/// フレーム番号
int frame;
/// 距離
float distance;
/// 位置
float position[3];
/// 回転
float orientation[3];
/// 補間曲線
char interpolation[6][4];
/// 視野角
float angle;
/// 不明データ
char unknown[3];
void Read(std::istream *stream)
{
stream->read((char*) &frame, sizeof(int));
stream->read((char*) &distance, sizeof(float));
stream->read((char*) position, sizeof(float) * 3);
stream->read((char*) orientation, sizeof(float) * 3);
stream->read((char*) interpolation, sizeof(char) * 24);
stream->read((char*) &angle, sizeof(float));
stream->read((char*) unknown, sizeof(char) * 3);
}
void Write(std::ostream *stream)
{
stream->write((char*)&frame, sizeof(int));
stream->write((char*)&distance, sizeof(float));
stream->write((char*)position, sizeof(float) * 3);
stream->write((char*)orientation, sizeof(float) * 3);
stream->write((char*)interpolation, sizeof(char) * 24);
stream->write((char*)&angle, sizeof(float));
stream->write((char*)unknown, sizeof(char) * 3);
}
};
/// ライトフレーム
class VmdLightFrame
{
public:
/// フレーム番号
int frame;
/// 色
float color[3];
/// 位置
float position[3];
void Read(std::istream* stream)
{
stream->read((char*) &frame, sizeof(int));
stream->read((char*) color, sizeof(float) * 3);
stream->read((char*) position, sizeof(float) * 3);
}
void Write(std::ostream* stream)
{
stream->write((char*)&frame, sizeof(int));
stream->write((char*)color, sizeof(float) * 3);
stream->write((char*)position, sizeof(float) * 3);
}
};
/// IKの有効無効
class VmdIkEnable
{
public:
std::string ik_name;
bool enable;
};
/// IKフレーム
class VmdIkFrame
{
public:
int frame;
bool display;
std::vector<VmdIkEnable> ik_enable;
void Read(std::istream *stream)
{
char buffer[20];
stream->read((char*) &frame, sizeof(int));
stream->read((char*) &display, sizeof(uint8_t));
int ik_count;
stream->read((char*) &ik_count, sizeof(int));
ik_enable.resize(ik_count);
for (int i = 0; i < ik_count; i++)
{
stream->read(buffer, 20);
ik_enable[i].ik_name = std::string(buffer);
stream->read((char*) &ik_enable[i].enable, sizeof(uint8_t));
}
}
void Write(std::ostream *stream)
{
stream->write((char*)&frame, sizeof(int));
stream->write((char*)&display, sizeof(uint8_t));
int ik_count = static_cast<int>(ik_enable.size());
stream->write((char*)&ik_count, sizeof(int));
for (int i = 0; i < ik_count; i++)
{
const VmdIkEnable& ik_enable = this->ik_enable.at(i);
stream->write(ik_enable.ik_name.c_str(), 20);
stream->write((char*)&ik_enable.enable, sizeof(uint8_t));
}
}
};
/// VMDモーション
class VmdMotion
{
public:
/// モデル名
std::string model_name;
/// バージョン
int version;
/// ボーンフレーム
std::vector<VmdBoneFrame> bone_frames;
/// 表情フレーム
std::vector<VmdFaceFrame> face_frames;
/// カメラフレーム
std::vector<VmdCameraFrame> camera_frames;
/// ライトフレーム
std::vector<VmdLightFrame> light_frames;
/// IKフレーム
std::vector<VmdIkFrame> ik_frames;
static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename)
{
std::ifstream stream(filename, std::ios::binary);
auto result = LoadFromStream(&stream);
stream.close();
return result;
}
static std::unique_ptr<VmdMotion> LoadFromStream(std::ifstream *stream)
{
char buffer[30];
auto result = std::make_unique<VmdMotion>();
// magic and version
stream->read((char*) buffer, 30);
if (strncmp(buffer, "Vocaloid Motion Data", 20))
{
std::cerr << "invalid vmd file." << std::endl;
return nullptr;
}
result->version = std::atoi(buffer + 20);
// name
stream->read(buffer, 20);
result->model_name = std::string(buffer);
// bone frames
int bone_frame_num;
stream->read((char*) &bone_frame_num, sizeof(int));
result->bone_frames.resize(bone_frame_num);
for (int i = 0; i < bone_frame_num; i++)
{
result->bone_frames[i].Read(stream);
}
// face frames
int face_frame_num;
stream->read((char*) &face_frame_num, sizeof(int));
result->face_frames.resize(face_frame_num);
for (int i = 0; i < face_frame_num; i++)
{
result->face_frames[i].Read(stream);
}
// camera frames
int camera_frame_num;
stream->read((char*) &camera_frame_num, sizeof(int));
result->camera_frames.resize(camera_frame_num);
for (int i = 0; i < camera_frame_num; i++)
{
result->camera_frames[i].Read(stream);
}
// light frames
int light_frame_num;
stream->read((char*) &light_frame_num, sizeof(int));
result->light_frames.resize(light_frame_num);
for (int i = 0; i < light_frame_num; i++)
{
result->light_frames[i].Read(stream);
}
// unknown2
stream->read(buffer, 4);
// ik frames
if (stream->peek() != std::ios::traits_type::eof())
{
int ik_num;
stream->read((char*) &ik_num, sizeof(int));
result->ik_frames.resize(ik_num);
for (int i = 0; i < ik_num; i++)
{
result->ik_frames[i].Read(stream);
}
}
if (stream->peek() != std::ios::traits_type::eof())
{
std::cerr << "vmd stream has unknown data." << std::endl;
}
return result;
}
bool SaveToFile(const std::u16string& filename)
{
// TODO: How to adapt u16string to string?
/*
std::ofstream stream(filename.c_str(), std::ios::binary);
auto result = SaveToStream(&stream);
stream.close();
return result;
*/
return false;
}
bool SaveToStream(std::ofstream *stream)
{
std::string magic = "Vocaloid Motion Data 0002\0";
magic.resize(30);
// magic and version
stream->write(magic.c_str(), 30);
// name
stream->write(model_name.c_str(), 20);
// bone frames
const int bone_frame_num = static_cast<int>(bone_frames.size());
stream->write(reinterpret_cast<const char*>(&bone_frame_num), sizeof(int));
for (int i = 0; i < bone_frame_num; i++)
{
bone_frames[i].Write(stream);
}
// face frames
const int face_frame_num = static_cast<int>(face_frames.size());
stream->write(reinterpret_cast<const char*>(&face_frame_num), sizeof(int));
for (int i = 0; i < face_frame_num; i++)
{
face_frames[i].Write(stream);
}
// camera frames
const int camera_frame_num = static_cast<int>(camera_frames.size());
stream->write(reinterpret_cast<const char*>(&camera_frame_num), sizeof(int));
for (int i = 0; i < camera_frame_num; i++)
{
camera_frames[i].Write(stream);
}
// light frames
const int light_frame_num = static_cast<int>(light_frames.size());
stream->write(reinterpret_cast<const char*>(&light_frame_num), sizeof(int));
for (int i = 0; i < light_frame_num; i++)
{
light_frames[i].Write(stream);
}
// self shadow datas
const int self_shadow_num = 0;
stream->write(reinterpret_cast<const char*>(&self_shadow_num), sizeof(int));
// ik frames
const int ik_num = static_cast<int>(ik_frames.size());
stream->write(reinterpret_cast<const char*>(&ik_num), sizeof(int));
for (int i = 0; i < ik_num; i++)
{
ik_frames[i].Write(stream);
}
return true;
}
};
}