Files
WickedEngine/Editor/ModelImporter_WIO.cpp
T

1241 lines
33 KiB
C++

#include "stdafx.h"
#include "ModelImporter.h"
#include <fstream>
#include <algorithm>
using namespace std;
using namespace wiGraphicsTypes;
using namespace wiSceneComponents;
Mesh* LoadMeshFromBinaryFile(const std::string& newName, const std::string& fname, const std::map<std::string, Material*>& materialColl, const unordered_set<Armature*>& armatures)
{
Mesh* mesh = new Mesh(newName);
BYTE* buffer;
size_t fileSize;
if (wiHelper::readByteData(fname, &buffer, fileSize)) {
int offset = 0;
int VERSION;
memcpy(&VERSION, buffer, sizeof(int));
offset += sizeof(int);
if (VERSION >= 1001) {
int doubleside;
memcpy(&doubleside, buffer + offset, sizeof(int));
offset += sizeof(int);
if (doubleside) {
mesh->doubleSided = true;
}
}
int billboard;
memcpy(&billboard, buffer + offset, sizeof(int));
offset += sizeof(int);
if (billboard) {
char axis;
memcpy(&axis, buffer + offset, 1);
offset += 1;
if (toupper(axis) == 'Y')
mesh->billboardAxis = XMFLOAT3(0, 1, 0);
else if (toupper(axis) == 'X')
mesh->billboardAxis = XMFLOAT3(1, 0, 0);
else if (toupper(axis) == 'Z')
mesh->billboardAxis = XMFLOAT3(0, 0, 1);
else
mesh->billboardAxis = XMFLOAT3(0, 0, 0);
mesh->isBillboarded = true;
}
int parented; //parentnamelength
memcpy(&parented, buffer + offset, sizeof(int));
offset += sizeof(int);
if (parented) {
char* pName = new char[parented + 1]();
memcpy(pName, buffer + offset, parented);
offset += parented;
mesh->parent = pName;
delete[] pName;
stringstream identified_parent("");
identified_parent << mesh->parent;
for (Armature* a : armatures) {
if (!a->name.compare(identified_parent.str())) {
mesh->armatureName = identified_parent.str();
mesh->armature = a;
}
}
}
int materialCount;
memcpy(&materialCount, buffer + offset, sizeof(int));
offset += sizeof(int);
for (int i = 0; i<materialCount; ++i) {
int matNameLen;
memcpy(&matNameLen, buffer + offset, sizeof(int));
offset += sizeof(int);
char* matName = new char[matNameLen + 1]();
memcpy(matName, buffer + offset, matNameLen);
offset += matNameLen;
stringstream identified_matname("");
identified_matname << matName;
auto& iter = materialColl.find(identified_matname.str());
if (iter != materialColl.end()) {
mesh->subsets.push_back(MeshSubset());
mesh->subsets.back().material = iter->second;
//materials.push_back(iter->second);
}
mesh->materialNames.push_back(identified_matname.str());
delete[] matName;
}
int rendermesh, vertexCount;
memcpy(&rendermesh, buffer + offset, sizeof(int));
offset += sizeof(int);
memcpy(&vertexCount, buffer + offset, sizeof(int));
offset += sizeof(int);
mesh->vertices_FULL.resize(vertexCount);
for (int i = 0; i<vertexCount; ++i) {
float v[8];
memcpy(v, buffer + offset, sizeof(float) * 8);
offset += sizeof(float) * 8;
mesh->vertices_FULL[i].pos.x = v[0];
mesh->vertices_FULL[i].pos.y = v[1];
mesh->vertices_FULL[i].pos.z = v[2];
mesh->vertices_FULL[i].pos.w = 0;
if (!mesh->isBillboarded) {
mesh->vertices_FULL[i].nor.x = v[3];
mesh->vertices_FULL[i].nor.y = v[4];
mesh->vertices_FULL[i].nor.z = v[5];
}
else {
mesh->vertices_FULL[i].nor.x = mesh->billboardAxis.x;
mesh->vertices_FULL[i].nor.y = mesh->billboardAxis.y;
mesh->vertices_FULL[i].nor.z = mesh->billboardAxis.z;
}
mesh->vertices_FULL[i].tex.x = v[6];
mesh->vertices_FULL[i].tex.y = v[7];
int matIndex;
memcpy(&matIndex, buffer + offset, sizeof(int));
offset += sizeof(int);
mesh->vertices_FULL[i].tex.z = (float)matIndex;
int weightCount = 0;
memcpy(&weightCount, buffer + offset, sizeof(int));
offset += sizeof(int);
for (int j = 0; j<weightCount; ++j) {
int weightNameLen = 0;
memcpy(&weightNameLen, buffer + offset, sizeof(int));
offset += sizeof(int);
char* weightName = new char[weightNameLen + 1](); //bone name
memcpy(weightName, buffer + offset, weightNameLen);
offset += weightNameLen;
float weightValue = 0;
memcpy(&weightValue, buffer + offset, sizeof(float));
offset += sizeof(float);
#pragma region BONE INDEX SETUP
string nameB = weightName;
if (mesh->armature) {
bool gotBone = false;
int BONEINDEX = 0;
int b = 0;
while (!gotBone && b<(int)mesh->armature->boneCollection.size()) {
if (!mesh->armature->boneCollection[b]->name.compare(nameB)) {
gotBone = true;
BONEINDEX = b; //GOT INDEX OF BONE OF THE WEIGHT IN THE PARENT ARMATURE
}
b++;
}
if (gotBone) { //ONLY PROCEED IF CORRESPONDING BONE WAS FOUND
if (!mesh->vertices_FULL[i].wei.x) {
mesh->vertices_FULL[i].wei.x = weightValue;
mesh->vertices_FULL[i].ind.x = (float)BONEINDEX;
}
else if (!mesh->vertices_FULL[i].wei.y) {
mesh->vertices_FULL[i].wei.y = weightValue;
mesh->vertices_FULL[i].ind.y = (float)BONEINDEX;
}
else if (!mesh->vertices_FULL[i].wei.z) {
mesh->vertices_FULL[i].wei.z = weightValue;
mesh->vertices_FULL[i].ind.z = (float)BONEINDEX;
}
else if (!mesh->vertices_FULL[i].wei.w) {
mesh->vertices_FULL[i].wei.w = weightValue;
mesh->vertices_FULL[i].ind.w = (float)BONEINDEX;
}
}
}
//(+RIBBONTRAIL SETUP)(+VERTEXGROUP SETUP)
if (nameB.find("trailbase") != string::npos)
mesh->trailInfo.base = i;
else if (nameB.find("trailtip") != string::npos)
mesh->trailInfo.tip = i;
bool windAffection = false;
if (nameB.find("wind") != string::npos)
windAffection = true;
bool gotvg = false;
for (unsigned int v = 0; v<mesh->vertexGroups.size(); ++v)
if (!nameB.compare(mesh->vertexGroups[v].name)) {
gotvg = true;
mesh->vertexGroups[v].addVertex(VertexRef(i, weightValue));
if (windAffection)
mesh->vertices_FULL[i].pos.w = weightValue;
}
if (!gotvg) {
mesh->vertexGroups.push_back(VertexGroup(nameB));
mesh->vertexGroups.back().addVertex(VertexRef(i, weightValue));
if (windAffection)
mesh->vertices_FULL[i].pos.w = weightValue;
}
#pragma endregion
delete[] weightName;
}
}
if (rendermesh) {
int indexCount;
memcpy(&indexCount, buffer + offset, sizeof(int));
offset += sizeof(int);
unsigned int* indexArray = new unsigned int[indexCount];
memcpy(indexArray, buffer + offset, sizeof(unsigned int)*indexCount);
offset += sizeof(unsigned int)*indexCount;
mesh->indices.reserve(indexCount);
for (int i = 0; i<indexCount; ++i) {
mesh->indices.push_back(indexArray[i]);
}
delete[] indexArray;
int softBody;
memcpy(&softBody, buffer + offset, sizeof(int));
offset += sizeof(int);
if (softBody) {
int softCount[2]; //ind,vert
memcpy(softCount, buffer + offset, sizeof(int) * 2);
offset += sizeof(int) * 2;
unsigned int* softind = new unsigned int[softCount[0]];
memcpy(softind, buffer + offset, sizeof(unsigned int)*softCount[0]);
offset += sizeof(unsigned int)*softCount[0];
float* softvert = new float[softCount[1]];
memcpy(softvert, buffer + offset, sizeof(float)*softCount[1]);
offset += sizeof(float)*softCount[1];
mesh->physicsindices.reserve(softCount[0]);
mesh->physicsverts.reserve(softCount[1] / 3);
for (int i = 0; i<softCount[0]; ++i) {
mesh->physicsindices.push_back(softind[i]);
}
for (int i = 0; i<softCount[1]; i += 3) {
mesh->physicsverts.push_back(XMFLOAT3(softvert[i], softvert[i + 1], softvert[i + 2]));
}
delete[] softind;
delete[] softvert;
}
else {
}
}
else {
}
memcpy(mesh->aabb.corners, buffer + offset, sizeof(mesh->aabb.corners));
offset += sizeof(mesh->aabb.corners);
int isSoftbody;
memcpy(&isSoftbody, buffer + offset, sizeof(int));
offset += sizeof(int);
if (isSoftbody) {
float prop[2]; //mass,friction
memcpy(prop, buffer + offset, sizeof(float) * 2);
offset += sizeof(float) * 2;
mesh->softBody = true;
mesh->mass = prop[0];
mesh->friction = prop[1];
int vglenghts[3]; //goal,mass,soft
memcpy(vglenghts, buffer + offset, sizeof(int) * 3);
offset += sizeof(int) * 3;
char* vgg = new char[vglenghts[0] + 1]();
char* vgm = new char[vglenghts[1] + 1]();
char* vgs = new char[vglenghts[2] + 1]();
memcpy(vgg, buffer + offset, vglenghts[0]);
offset += vglenghts[0];
memcpy(vgm, buffer + offset, vglenghts[1]);
offset += vglenghts[1];
memcpy(vgs, buffer + offset, vglenghts[2]);
offset += vglenghts[2];
for (unsigned int v = 0; v<mesh->vertexGroups.size(); ++v) {
if (!strcmp(vgm, mesh->vertexGroups[v].name.c_str()))
mesh->massVG = v;
if (!strcmp(vgg, mesh->vertexGroups[v].name.c_str()))
mesh->goalVG = v;
if (!strcmp(vgs, mesh->vertexGroups[v].name.c_str()))
mesh->softVG = v;
}
delete[]vgg;
delete[]vgm;
delete[]vgs;
}
delete[] buffer;
mesh->renderable = rendermesh == 0 ? false : true;
}
return mesh;
}
void LoadWiArmatures(const std::string& directory, const std::string& name, unordered_set<Armature*>& armatures)
{
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file)
{
Armature* armature = nullptr;
while (!file.eof())
{
float trans[] = { 0,0,0,0 };
string line = "";
file >> line;
if (line[0] == '/' && line.substr(2, 8) == "ARMATURE")
{
armature = new Armature(line.substr(11, strlen(line.c_str()) - 11));
armatures.insert(armature);
}
else
{
switch (line[0])
{
case 'r':
file >> trans[0] >> trans[1] >> trans[2] >> trans[3];
armature->rotation_rest = XMFLOAT4(trans[0], trans[1], trans[2], trans[3]);
break;
case 's':
file >> trans[0] >> trans[1] >> trans[2];
armature->scale_rest = XMFLOAT3(trans[0], trans[1], trans[2]);
break;
case 't':
file >> trans[0] >> trans[1] >> trans[2];
armature->translation_rest = XMFLOAT3(trans[0], trans[1], trans[2]);
{
XMMATRIX world = XMMatrixScalingFromVector(XMLoadFloat3(&armature->scale))*XMMatrixRotationQuaternion(XMLoadFloat4(&armature->rotation))*XMMatrixTranslationFromVector(XMLoadFloat3(&armature->translation));
XMStoreFloat4x4(&armature->world_rest, world);
}
break;
case 'b':
{
string boneName;
file >> boneName;
armature->boneCollection.push_back(new Bone(boneName));
}
break;
case 'p':
file >> armature->boneCollection.back()->parentName;
break;
case 'l':
{
float x = 0, y = 0, z = 0, w = 0;
file >> x >> y >> z >> w;
XMVECTOR quaternion = XMVectorSet(x, y, z, w);
file >> x >> y >> z;
XMVECTOR translation = XMVectorSet(x, y, z, 0);
XMMATRIX frame;
frame = XMMatrixRotationQuaternion(quaternion) * XMMatrixTranslationFromVector(translation);
XMStoreFloat3(&armature->boneCollection.back()->translation_rest, translation);
XMStoreFloat4(&armature->boneCollection.back()->rotation_rest, quaternion);
XMStoreFloat4x4(&armature->boneCollection.back()->world_rest, frame);
//XMStoreFloat4x4(&armature->boneCollection.back()->restInv,XMMatrixInverse(0,frame));
}
break;
case 'c':
armature->boneCollection.back()->connected = true;
break;
case 'h':
file >> armature->boneCollection.back()->length;
break;
default: break;
}
}
}
}
file.close();
//CREATE FAMILY
for (Armature* armature : armatures)
{
armature->CreateFamily();
}
}
void LoadWiMaterialLibrary(const std::string& directory, const std::string& name, const std::string& texturesDir, std::map<std::string, Material*>& materials)
{
int materialI = (int)(materials.size() - 1);
Material* currentMat = NULL;
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file) {
while (!file.eof()) {
string line = "";
file >> line;
if (line[0] == '/' && !strcmp(line.substr(2, 8).c_str(), "MATERIAL")) {
if (currentMat)
{
currentMat->ConvertToPhysicallyBasedMaterial();
materials.insert(pair<string, Material*>(currentMat->name, currentMat));
}
currentMat = new Material(line.substr(11, strlen(line.c_str()) - 11));
materialI++;
}
else {
switch (line[0]) {
case 'd':
file >> currentMat->diffuseColor.x;
file >> currentMat->diffuseColor.y;
file >> currentMat->diffuseColor.z;
break;
case 'X':
currentMat->cast_shadow = false;
break;
case 'r':
{
string resourceName = "";
file >> resourceName;
stringstream ss("");
ss << directory << texturesDir << resourceName.c_str();
currentMat->surfaceMapName = ss.str();
currentMat->surfaceMap = (Texture2D*)wiResourceManager::GetGlobal()->add(ss.str());
}
break;
case 'n':
{
string resourceName = "";
file >> resourceName;
stringstream ss("");
ss << directory << texturesDir << resourceName.c_str();
currentMat->normalMapName = ss.str();
currentMat->normalMap = (Texture2D*)wiResourceManager::GetGlobal()->add(ss.str());
}
break;
case 't':
{
string resourceName = "";
file >> resourceName;
stringstream ss("");
ss << directory << texturesDir << resourceName.c_str();
currentMat->textureName = ss.str();
currentMat->texture = (Texture2D*)wiResourceManager::GetGlobal()->add(ss.str());
}
file >> currentMat->premultipliedTexture;
break;
case 'D':
{
string resourceName = "";
file >> resourceName;
stringstream ss("");
ss << directory << texturesDir << resourceName.c_str();
currentMat->displacementMapName = ss.str();
currentMat->displacementMap = (Texture2D*)wiResourceManager::GetGlobal()->add(ss.str());
}
break;
case 'S':
{
string resourceName = "";
file >> resourceName;
stringstream ss("");
ss << directory << texturesDir << resourceName.c_str();
currentMat->specularMapName = ss.str();
currentMat->specularMap = (Texture2D*)wiResourceManager::GetGlobal()->add(ss.str());
}
break;
case 'a':
file >> currentMat->alpha;
break;
case 'h':
currentMat->shadeless = true;
break;
case 'R':
file >> currentMat->refractionIndex;
break;
case 'e':
file >> currentMat->enviroReflection;
break;
case 's':
file >> currentMat->specular.x;
file >> currentMat->specular.y;
file >> currentMat->specular.z;
file >> currentMat->specular.w;
break;
case 'p':
file >> currentMat->specular_power;
break;
case 'k':
currentMat->isSky = true;
break;
case 'm':
file >> currentMat->movingTex.x;
file >> currentMat->movingTex.y;
file >> currentMat->movingTex.z;
currentMat->framesToWaitForTexCoordOffset = currentMat->movingTex.z;
break;
case 'w':
currentMat->water = true;
break;
case 'u':
currentMat->subsurfaceScattering = true;
break;
case 'b':
{
string blend;
file >> blend;
if (!blend.compare("ADD"))
currentMat->blendFlag = BLENDMODE_ADDITIVE;
}
break;
case 'i':
{
file >> currentMat->emissive;
}
break;
default:break;
}
}
}
}
file.close();
if (currentMat)
{
currentMat->ConvertToPhysicallyBasedMaterial();
materials.insert(pair<string, Material*>(currentMat->name, currentMat));
}
}
void LoadWiObjects(const std::string& directory, const std::string& name, unordered_set<Object*>& objects
, unordered_set<Armature*>& armatures
, std::map<std::string, Mesh*>& meshes, const std::map<std::string, Material*>& materials)
{
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file)
{
Object* object = nullptr;
while (!file.eof())
{
float trans[] = { 0,0,0,0 };
string line = "";
file >> line;
if (line[0] == '/' && !strcmp(line.substr(2, 6).c_str(), "OBJECT"))
{
object = new Object(line.substr(9, strlen(line.c_str()) - 9));
objects.insert(object);
}
else
{
switch (line[0])
{
case 'm':
{
string meshName = "";
file >> meshName;
object->meshName = meshName;
auto& iter = meshes.find(meshName);
if (line[1] == 'b')
{
//binary load mesh in place if not present
if (iter == meshes.end())
{
stringstream meshFileName("");
meshFileName << directory << meshName << ".wimesh";
Mesh* mesh = LoadMeshFromBinaryFile(meshName, meshFileName.str(), materials, armatures);
object->mesh = mesh;
meshes.insert(pair<string, Mesh*>(meshName, mesh));
}
else
{
object->mesh = iter->second;
}
}
else
{
if (iter != meshes.end())
{
object->mesh = iter->second;
}
}
}
break;
case 'p':
{
file >> object->parentName;
}
break;
case 'b':
{
file >> object->boneParent;
}
break;
case 'I':
{
XMFLOAT3 s, t;
XMFLOAT4 r;
file >> t.x >> t.y >> t.z >> r.x >> r.y >> r.z >> r.w >> s.x >> s.y >> s.z;
XMStoreFloat4x4(&object->parent_inv_rest
, XMMatrixScalingFromVector(XMLoadFloat3(&s)) *
XMMatrixRotationQuaternion(XMLoadFloat4(&r)) *
XMMatrixTranslationFromVector(XMLoadFloat3(&t))
);
}
break;
case 'r':
file >> trans[0] >> trans[1] >> trans[2] >> trans[3];
object->Rotate(XMFLOAT4(trans[0], trans[1], trans[2], trans[3]));
break;
case 's':
file >> trans[0] >> trans[1] >> trans[2];
object->Scale(XMFLOAT3(trans[0], trans[1], trans[2]));
break;
case 't':
file >> trans[0] >> trans[1] >> trans[2];
object->Translate(XMFLOAT3(trans[0], trans[1], trans[2]));
break;
case 'E':
{
string systemName, materialName;
bool visibleEmitter;
float size, randfac, norfac;
float count, life, randlife;
float scaleX, scaleY, rot;
file >> systemName >> visibleEmitter >> materialName >> size >> randfac >> norfac >> count >> life >> randlife;
file >> scaleX >> scaleY >> rot;
if (object->mesh)
{
object->eParticleSystems.push_back(
new wiEmittedParticle(systemName, materialName, object, size, randfac, norfac, count, life, randlife, scaleX, scaleY, rot)
);
}
}
break;
case 'H':
{
string name, mat, densityG, lenG;
float len;
int count;
file >> name >> mat >> len >> count >> densityG >> lenG;
object->hParticleSystems.push_back(new wiHairParticle(name, len, count, mat, object, densityG, lenG));
}
break;
case 'P':
object->rigidBody = true;
file >> object->collisionShape >> object->mass >>
object->friction >> object->restitution >> object->damping >> object->physicsType >>
object->kinematic;
break;
case 'T':
file >> object->transparency;
break;
default: break;
}
}
}
}
file.close();
}
void LoadWiMeshes(const std::string& directory, const std::string& name, std::map<std::string, Mesh*>& meshes,
const unordered_set<Armature*>& armatures, const std::map<std::string, Material*>& materials)
{
int meshI = (int)(meshes.size() - 1);
Mesh* currentMesh = NULL;
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file) {
while (!file.eof())
{
float trans[] = { 0,0,0,0 };
string line = "";
file >> line;
if (line[0] == '/' && !line.substr(2, 4).compare("MESH")) {
currentMesh = new Mesh(line.substr(7, strlen(line.c_str()) - 7));
meshes.insert(pair<string, Mesh*>(currentMesh->name, currentMesh));
meshI++;
}
else
{
switch (line[0])
{
case 'p':
{
file >> currentMesh->parent;
for (auto& a : armatures)
{
if (!a->name.compare(currentMesh->parent))
{
currentMesh->armature = a;
break;
}
}
}
break;
case 'v':
currentMesh->vertices_FULL.push_back(Mesh::Vertex_FULL());
file >> currentMesh->vertices_FULL.back().pos.x;
file >> currentMesh->vertices_FULL.back().pos.y;
file >> currentMesh->vertices_FULL.back().pos.z;
break;
case 'n':
if (currentMesh->isBillboarded) {
currentMesh->vertices_FULL.back().nor.x = currentMesh->billboardAxis.x;
currentMesh->vertices_FULL.back().nor.y = currentMesh->billboardAxis.y;
currentMesh->vertices_FULL.back().nor.z = currentMesh->billboardAxis.z;
}
else {
file >> currentMesh->vertices_FULL.back().nor.x;
file >> currentMesh->vertices_FULL.back().nor.y;
file >> currentMesh->vertices_FULL.back().nor.z;
}
break;
case 'u':
file >> currentMesh->vertices_FULL.back().tex.x;
file >> currentMesh->vertices_FULL.back().tex.y;
break;
case 'w':
{
string nameB;
float weight = 0;
int BONEINDEX = 0;
file >> nameB >> weight;
bool gotBone = false;
if (currentMesh->armature != nullptr) {
int j = 0;
for (auto& b : currentMesh->armature->boneCollection)
{
if (!b->name.compare(nameB))
{
BONEINDEX = j;
break;
}
j++;
}
}
if (gotBone)
{
//ONLY PROCEED IF CORRESPONDING BONE WAS FOUND
if (!currentMesh->vertices_FULL.back().wei.x) {
currentMesh->vertices_FULL.back().wei.x = weight;
currentMesh->vertices_FULL.back().ind.x = (float)BONEINDEX;
}
else if (!currentMesh->vertices_FULL.back().wei.y) {
currentMesh->vertices_FULL.back().wei.y = weight;
currentMesh->vertices_FULL.back().ind.y = (float)BONEINDEX;
}
else if (!currentMesh->vertices_FULL.back().wei.z) {
currentMesh->vertices_FULL.back().wei.z = weight;
currentMesh->vertices_FULL.back().ind.z = (float)BONEINDEX;
}
else if (!currentMesh->vertices_FULL.back().wei.w) {
currentMesh->vertices_FULL.back().wei.w = weight;
currentMesh->vertices_FULL.back().ind.w = (float)BONEINDEX;
}
}
//(+RIBBONTRAIL SETUP)(+VERTEXGROUP SETUP)
if (nameB.find("trailbase") != string::npos)
currentMesh->trailInfo.base = (int)(currentMesh->vertices_FULL.size() - 1);
else if (nameB.find("trailtip") != string::npos)
currentMesh->trailInfo.tip = (int)(currentMesh->vertices_FULL.size() - 1);
bool windAffection = false;
if (nameB.find("wind") != string::npos)
windAffection = true;
bool gotvg = false;
for (unsigned int v = 0; v<currentMesh->vertexGroups.size(); ++v)
if (!nameB.compare(currentMesh->vertexGroups[v].name)) {
gotvg = true;
currentMesh->vertexGroups[v].addVertex(VertexRef((int)(currentMesh->vertices_FULL.size() - 1), weight));
if (windAffection)
currentMesh->vertices_FULL.back().pos.w = weight;
}
if (!gotvg) {
currentMesh->vertexGroups.push_back(VertexGroup(nameB));
currentMesh->vertexGroups.back().addVertex(VertexRef((int)(currentMesh->vertices_FULL.size() - 1), weight));
if (windAffection)
currentMesh->vertices_FULL.back().pos.w = weight;
}
}
break;
case 'i':
{
int count;
file >> count;
for (int i = 0; i<count; i++) {
int index;
file >> index;
currentMesh->indices.push_back(index);
}
break;
}
case 'V':
{
XMFLOAT3 pos;
file >> pos.x >> pos.y >> pos.z;
currentMesh->physicsverts.push_back(pos);
}
break;
case 'I':
{
int count;
file >> count;
for (int i = 0; i<count; i++) {
int index;
file >> index;
currentMesh->physicsindices.push_back(index);
}
break;
}
case 'm':
{
string mName = "";
file >> mName;
currentMesh->materialNames.push_back(mName);
auto& iter = materials.find(mName);
if (iter != materials.end()) {
currentMesh->subsets.push_back(MeshSubset());
currentMesh->renderable = true;
currentMesh->subsets.back().material = (iter->second);
}
}
break;
case 'a':
file >> currentMesh->vertices_FULL.back().tex.z;
break;
case 'B':
for (int corner = 0; corner<8; ++corner) {
file >> currentMesh->aabb.corners[corner].x;
file >> currentMesh->aabb.corners[corner].y;
file >> currentMesh->aabb.corners[corner].z;
}
break;
case 'b':
{
currentMesh->isBillboarded = true;
string read = "";
file >> read;
transform(read.begin(), read.end(), read.begin(), toupper);
if (read.find(toupper('y')) != string::npos) currentMesh->billboardAxis = XMFLOAT3(0, 1, 0);
else if (read.find(toupper('x')) != string::npos) currentMesh->billboardAxis = XMFLOAT3(1, 0, 0);
else if (read.find(toupper('z')) != string::npos) currentMesh->billboardAxis = XMFLOAT3(0, 0, 1);
else currentMesh->billboardAxis = XMFLOAT3(0, 0, 0);
}
break;
case 'S':
{
currentMesh->softBody = true;
string mvgi = "", gvgi = "", svgi = "";
file >> currentMesh->mass >> currentMesh->friction >> gvgi >> mvgi >> svgi;
for (unsigned int v = 0; v<currentMesh->vertexGroups.size(); ++v) {
if (!strcmp(mvgi.c_str(), currentMesh->vertexGroups[v].name.c_str()))
currentMesh->massVG = v;
if (!strcmp(gvgi.c_str(), currentMesh->vertexGroups[v].name.c_str()))
currentMesh->goalVG = v;
if (!strcmp(svgi.c_str(), currentMesh->vertexGroups[v].name.c_str()))
currentMesh->softVG = v;
}
}
break;
default: break;
}
}
}
}
file.close();
if (currentMesh)
meshes.insert(pair<string, Mesh*>(currentMesh->name, currentMesh));
}
void LoadWiActions(const std::string& directory, const std::string& name, unordered_set<Armature*>& armatures)
{
Armature* armatureI = nullptr;
Bone* boneI = nullptr;
int firstFrame = INT_MAX;
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file) {
while (!file.eof()) {
string line = "";
file >> line;
if (line[0] == '/' && !strcmp(line.substr(2, 8).c_str(), "ARMATURE")) {
string armaturename = line.substr(11, strlen(line.c_str()) - 11);
for (auto& a : armatures)
{
if (!a->name.compare(armaturename)) {
armatureI = a;
break;
}
}
}
else {
switch (line[0]) {
case 'C':
armatureI->actions.push_back(Action());
file >> armatureI->actions.back().name;
break;
case 'A':
file >> armatureI->actions.back().frameCount;
break;
case 'b':
{
string boneName;
file >> boneName;
boneI = armatureI->GetBone(boneName);
if (boneI != nullptr)
{
boneI->actionFrames.resize(armatureI->actions.size());
}
}
break;
case 'r':
{
int f = 0;
float x = 0, y = 0, z = 0, w = 0;
file >> f >> x >> y >> z >> w;
if (boneI != nullptr)
{
boneI->actionFrames.back().keyframesRot.push_back(KeyFrame(f, x, y, z, w));
}
}
break;
case 't':
{
int f = 0;
float x = 0, y = 0, z = 0;
file >> f >> x >> y >> z;
if (boneI != nullptr)
{
boneI->actionFrames.back().keyframesPos.push_back(KeyFrame(f, x, y, z, 0));
}
}
break;
case 's':
{
int f = 0;
float x = 0, y = 0, z = 0;
file >> f >> x >> y >> z;
if (boneI != nullptr)
{
boneI->actionFrames.back().keyframesSca.push_back(KeyFrame(f, x, y, z, 0));
}
}
break;
default: break;
}
}
}
}
file.close();
}
void LoadWiLights(const std::string& directory, const std::string& name, unordered_set<Light*>& lights)
{
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file)
{
Light* light = nullptr;
while (!file.eof())
{
string line = "";
file >> line;
switch (line[0])
{
case 'P':
{
light = new Light();
lights.insert(light);
light->SetType(Light::POINT);
file >> light->name >> light->shadow;
}
break;
case 'D':
{
light = new Light();
lights.insert(light);
light->SetType(Light::DIRECTIONAL);
file >> light->name;
light->shadow = true;
}
break;
case 'S':
{
light = new Light();
lights.insert(light);
light->SetType(Light::SPOT);
file >> light->name;
file >> light->shadow >> light->enerDis.z;
}
break;
case 'p':
{
file >> light->parentName;
}
break;
case 'b':
{
file >> light->boneParent;
}
break;
case 'I':
{
XMFLOAT3 s, t;
XMFLOAT4 r;
file >> t.x >> t.y >> t.z >> r.x >> r.y >> r.z >> r.w >> s.x >> s.y >> s.z;
XMStoreFloat4x4(&light->parent_inv_rest
, XMMatrixScalingFromVector(XMLoadFloat3(&s)) *
XMMatrixRotationQuaternion(XMLoadFloat4(&r)) *
XMMatrixTranslationFromVector(XMLoadFloat3(&t))
);
}
break;
case 't':
{
float x, y, z;
file >> x >> y >> z;
light->Translate(XMFLOAT3(x, y, z));
break;
}
case 'r':
{
float x, y, z, w;
file >> x >> y >> z >> w;
light->Rotate(XMFLOAT4(x, y, z, w));
break;
}
case 'c':
{
float r, g, b;
file >> r >> g >> b;
light->color = XMFLOAT4(r, g, b, 0);
break;
}
case 'e':
file >> light->enerDis.x;
break;
case 'd':
file >> light->enerDis.y;
break;
case 'n':
light->noHalo = true;
break;
case 'l':
{
string t = "";
file >> t;
stringstream rim("");
rim << directory << "rims/" << t;
Texture2D* tex = nullptr;
if ((tex = (Texture2D*)wiResourceManager::GetGlobal()->add(rim.str())) != nullptr) {
light->lensFlareRimTextures.push_back(tex);
light->lensFlareNames.push_back(rim.str());
}
}
break;
default: break;
}
}
}
file.close();
}
void LoadWiCameras(const std::string&directory, const std::string& name, std::list<Camera*>& cameras
, const unordered_set<Armature*>& armatures)
{
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file)
{
string voidStr("");
file >> voidStr;
while (!file.eof()) {
string line = "";
file >> line;
switch (line[0]) {
case 'c':
{
XMFLOAT3 trans;
XMFLOAT4 rot;
string name(""), parentA(""), parentB("");
file >> name >> parentA >> parentB >> trans.x >> trans.y >> trans.z >> rot.x >> rot.y >> rot.z >> rot.w;
cameras.push_back(new Camera(
trans, rot
, name)
);
for (auto& a : armatures)
{
Bone* b = a->GetBone(parentB);
if (b != nullptr)
{
cameras.back()->attachTo(b);
}
}
}
break;
case 'I':
{
XMFLOAT3 s, t;
XMFLOAT4 r;
file >> t.x >> t.y >> t.z >> r.x >> r.y >> r.z >> r.w >> s.x >> s.y >> s.z;
XMStoreFloat4x4(&cameras.back()->parent_inv_rest
, XMMatrixScalingFromVector(XMLoadFloat3(&s)) *
XMMatrixRotationQuaternion(XMLoadFloat4(&r)) *
XMMatrixTranslationFromVector(XMLoadFloat3(&t))
);
}
break;
default:break;
}
}
}
file.close();
}
void LoadWiDecals(const std::string&directory, const std::string& name, const std::string& texturesDir, unordered_set<Decal*>& decals)
{
stringstream filename("");
filename << directory << name;
ifstream file(filename.str().c_str());
if (file)
{
Decal* decal = nullptr;
string voidStr = "";
file >> voidStr;
while (!file.eof())
{
string line = "";
file >> line;
switch (line[0])
{
case 'd':
{
string name;
XMFLOAT3 loc, scale;
XMFLOAT4 rot;
file >> name >> scale.x >> scale.y >> scale.z >> loc.x >> loc.y >> loc.z >> rot.x >> rot.y >> rot.z >> rot.w;
decal = new Decal(loc, scale, rot);
decal->name = name;
decals.insert(decal);
}
break;
case 't':
{
string tex = "";
file >> tex;
stringstream ss("");
ss << directory << texturesDir << tex;
decal->addTexture(ss.str());
}
break;
case 'n':
{
string tex = "";
file >> tex;
stringstream ss("");
ss << directory << texturesDir << tex;
decal->addNormal(ss.str());
}
break;
default:break;
};
}
}
file.close();
}
Model* ImportModel_WIO(const std::string& fileName)
{
string directory, name;
wiHelper::SplitPath(fileName, directory, name);
string extension = wiHelper::toUpper(wiHelper::GetExtensionFromFileName(name));
wiHelper::RemoveExtensionFromFileName(name);
Model* model = new Model;
model->name = name;
stringstream armatureFilePath(""), materialLibFilePath(""), meshesFilePath(""), objectsFilePath("")
, actionsFilePath(""), lightsFilePath(""), decalsFilePath(""), camerasFilePath("");
armatureFilePath << name << ".wia";
materialLibFilePath << name << ".wim";
meshesFilePath << name << ".wi";
objectsFilePath << name << ".wio";
actionsFilePath << name << ".wiact";
lightsFilePath << name << ".wil";
decalsFilePath << name << ".wid";
camerasFilePath << name << ".wic";
LoadWiArmatures(directory, armatureFilePath.str(), model->armatures);
LoadWiMaterialLibrary(directory, materialLibFilePath.str(), "textures/", model->materials);
LoadWiMeshes(directory, meshesFilePath.str(), model->meshes, model->armatures, model->materials);
LoadWiObjects(directory, objectsFilePath.str(), model->objects, model->armatures, model->meshes, model->materials);
LoadWiActions(directory, actionsFilePath.str(), model->armatures);
LoadWiLights(directory, lightsFilePath.str(), model->lights);
LoadWiDecals(directory, decalsFilePath.str(), "textures/", model->decals);
LoadWiCameras(directory, camerasFilePath.str(), model->cameras, model->armatures);
model->FinishLoading();
return model;
}