Import art objects in level
This commit is contained in:
parent
9a197dabe7
commit
0f4f852528
|
@ -72,6 +72,22 @@ void FezLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSyst
|
||||||
auto trileSetName = std::string(levelRoot.attribute("trileSetName").as_string());
|
auto trileSetName = std::string(levelRoot.attribute("trileSetName").as_string());
|
||||||
trileSetName = ai_tolower(trileSetName);
|
trileSetName = ai_tolower(trileSetName);
|
||||||
|
|
||||||
|
// Create material for triles
|
||||||
|
auto myMat = new aiMaterial();
|
||||||
|
aiString matName("TrileSet");
|
||||||
|
myMat->AddProperty(&matName, AI_MATKEY_NAME);
|
||||||
|
|
||||||
|
// Embed texture for triles
|
||||||
|
auto myTex = CreateTex(std::string(mFezAssetDir / "trile sets" / (trileSetName + ".png")), pIOHandler);
|
||||||
|
mTextures.push_back(myTex);
|
||||||
|
|
||||||
|
// Put tex ref into material
|
||||||
|
aiString tName("*0");
|
||||||
|
myMat->AddProperty(&tName, AI_MATKEY_TEXTURE(aiTextureType_BASE_COLOR, 0));
|
||||||
|
|
||||||
|
//store material in scene
|
||||||
|
mMaterials.push_back(myMat);
|
||||||
|
|
||||||
// Find and read trile set XML file
|
// Find and read trile set XML file
|
||||||
std::unique_ptr<IOStream> trileFile;
|
std::unique_ptr<IOStream> trileFile;
|
||||||
trileFile.reset(pIOHandler->Open(mFezAssetDir / "trile sets" / (trileSetName + ".xml")));
|
trileFile.reset(pIOHandler->Open(mFezAssetDir / "trile sets" / (trileSetName + ".xml")));
|
||||||
|
@ -109,107 +125,83 @@ void FezLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSyst
|
||||||
auto trileRoot = new aiNode("Triles");
|
auto trileRoot = new aiNode("Triles");
|
||||||
pScene->mRootNode->addChildren(1, &trileRoot);
|
pScene->mRootNode->addChildren(1, &trileRoot);
|
||||||
|
|
||||||
// Begin filling out trile emplacements
|
// Begin filling out trile nodes
|
||||||
auto xmlTrileT = levelRoot.child("Triles");
|
auto xmlTrileT = levelRoot.child("Triles");
|
||||||
for (auto t : xmlTrileT.children()) {
|
AddTrileInstances(xmlTrileT, trileRoot);
|
||||||
if (std::string(t.name()) != "Entry") {
|
|
||||||
ASSIMP_LOG_WARN("Unknown tag found in Level Triles XML.");
|
// Create child for art objects
|
||||||
|
auto aoRoot = new aiNode("Art Objects");
|
||||||
|
pScene->mRootNode->addChildren(1, &aoRoot);
|
||||||
|
|
||||||
|
// For some reason, it needs a positioning adjustment...
|
||||||
|
aiMatrix4x4::Translation(aiVector3D(-0.5,-0.5, -0.5), aoRoot->mTransformation);
|
||||||
|
|
||||||
|
// Begin filling out art objects
|
||||||
|
auto xmlAoRoot = levelRoot.child("ArtObjects");
|
||||||
|
for (auto t : xmlAoRoot.children()) {
|
||||||
|
XmlNode instance;
|
||||||
|
if (std::string(t.name()) == "Entry") {
|
||||||
|
instance = t.child("ArtObjectInstance");
|
||||||
|
} else if (std::string(t.name()) == "ArtObjectInstance") {
|
||||||
|
instance = t;
|
||||||
|
} else {
|
||||||
|
ASSIMP_LOG_WARN("AO instance not found in a node.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto instance = t.child("TrileInstance");
|
auto aoName = std::string(instance.attribute("name").as_string("INVALID"));
|
||||||
if (instance.empty()) {
|
if (aoName == "INVALID") {
|
||||||
ASSIMP_LOG_WARN("Trile instance not found in a node.");
|
ASSIMP_LOG_WARN("AO instance found without a valid name!");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto trileID = instance.attribute("trileId").as_int(-1);
|
auto meshID = GetArtObjectFromName(aoName, pIOHandler);
|
||||||
if (trileID == -1) {
|
|
||||||
ASSIMP_LOG_WARN("Trile instance found without a valid trileId!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto meshID = GetTrileMeshFromId(trileID);
|
|
||||||
|
|
||||||
// Create node, link found mesh
|
// Create node, link found mesh
|
||||||
auto trileNode = new aiNode();
|
auto aoNode = new aiNode();
|
||||||
trileNode->mNumMeshes = 1;
|
aoNode->mNumMeshes = 1;
|
||||||
trileNode->mMeshes = new unsigned int[1];
|
aoNode->mMeshes = new unsigned int[1];
|
||||||
trileNode->mMeshes[0] = meshID;
|
aoNode->mMeshes[0] = meshID;
|
||||||
|
|
||||||
|
aoNode->mName = aiString("AO_" + aoName);
|
||||||
auto pos = GetFezVec3(instance.child("Position"));
|
auto pos = GetFezVec3(instance.child("Position"));
|
||||||
auto orient = instance.attribute("orientation").as_int(0);
|
auto rotate = GetFezQuat(instance.child("Rotation"));
|
||||||
|
auto scale = GetFezVec3(instance.child("Scale"));
|
||||||
|
|
||||||
// Create transformation matrix
|
aoNode->mTransformation = aiMatrix4x4 (scale, rotate, pos);
|
||||||
aiMatrix4x4 transform = aiMatrix4x4::Translation(pos, transform);
|
|
||||||
aiMatrix4x4 rotate = aiMatrix4x4::RotationY(gc_orient[orient], rotate);
|
|
||||||
|
|
||||||
trileNode->mTransformation = transform * rotate;
|
aoRoot->addChildren(1, &aoNode);
|
||||||
|
|
||||||
trileRoot->addChildren(1, &trileNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Fill in meshes from vector
|
// Fill in meshes from vector
|
||||||
pScene->mNumMeshes = mTrileMeshes.size();
|
pScene->mNumMeshes = mMeshes.size();
|
||||||
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
||||||
for (int i = 0; i < mTrileMeshes.size(); i++) {
|
for (int i = 0; i < mMeshes.size(); i++) {
|
||||||
pScene->mMeshes[i] = mTrileMeshes[i];
|
pScene->mMeshes[i] = mMeshes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create material
|
// Fill in materials from vector
|
||||||
pScene->mNumMaterials = 1;
|
pScene->mNumMaterials = mMaterials.size();
|
||||||
pScene->mMaterials = new aiMaterial * [1];
|
pScene->mMaterials = new aiMaterial * [mMaterials.size()];
|
||||||
|
for (int i = 0; i < mMaterials.size(); i++) {
|
||||||
|
pScene->mMaterials[i] = mMaterials.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
auto myMat = new aiMaterial();
|
// Fill in textures from vector
|
||||||
aiString matName("TrileSet");
|
pScene->mNumTextures = mTextures.size();
|
||||||
myMat->AddProperty(&matName, AI_MATKEY_NAME);
|
pScene->mTextures = new aiTexture *[mTextures.size()];
|
||||||
aiString texturePath(std::string(mFezAssetDir / "trile sets" / (trileSetName + ".png")));
|
for (int i = 0; i < mTextures.size(); i++) {
|
||||||
|
pScene->mTextures[i] = mTextures.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create embedded texture ref
|
|
||||||
auto trileTex = new aiTexture();
|
|
||||||
trileTex->mFilename = texturePath;
|
|
||||||
|
|
||||||
// PNG file, compressed
|
|
||||||
strcpy(trileTex->achFormatHint, "png");
|
|
||||||
trileTex->mHeight = 0;
|
|
||||||
|
|
||||||
// Open texture file for reading
|
|
||||||
std::unique_ptr<IOStream> texFile;
|
|
||||||
texFile.reset(pIOHandler->Open(mFezAssetDir / "trile sets" / (trileSetName + ".png")));
|
|
||||||
|
|
||||||
// Create buffer, read data, store into texture instance
|
|
||||||
auto texDat = new unsigned char[texFile->FileSize()];
|
|
||||||
trileTex->mWidth = texFile->FileSize();
|
|
||||||
texFile->Read(texDat, 1, texFile->FileSize());
|
|
||||||
trileTex->pcData = (aiTexel*)texDat;
|
|
||||||
|
|
||||||
// Store embedded texture into scene
|
|
||||||
pScene->mNumTextures = 1;
|
|
||||||
pScene->mTextures = new aiTexture *[1];
|
|
||||||
pScene->mTextures[0] = trileTex;
|
|
||||||
|
|
||||||
// Put ref into material
|
|
||||||
aiString tName("*0");
|
|
||||||
myMat->AddProperty(&tName, AI_MATKEY_TEXTURE(aiTextureType_BASE_COLOR, 0));
|
|
||||||
|
|
||||||
//store material in scene
|
|
||||||
pScene->mMaterials[0] = myMat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int FezLoader::GetTrileMeshFromId(const int trileId) {
|
|
||||||
if (auto search = mTrileMap.find(trileId); search != mTrileMap.end()) {
|
|
||||||
return search->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to create an aiMesh instance and add it to the vector.
|
aiMesh *FezLoader::CreateMesh(const Assimp::XmlNode &xmlSIIP) {
|
||||||
auto trileXML = mTriles.at(trileId);
|
ASSIMP_LOG_VERBOSE_DEBUG("FEZ CreateMesh called");
|
||||||
|
|
||||||
auto mesh = new aiMesh();
|
auto mesh = new aiMesh();
|
||||||
|
|
||||||
auto xmlSIIP = trileXML.child("Geometry").child("ShaderInstancedIndexedPrimitives");
|
|
||||||
// TODO: check type="TriangleList"
|
|
||||||
|
|
||||||
auto xmlVerts = xmlSIIP.child("Vertices");
|
auto xmlVerts = xmlSIIP.child("Vertices");
|
||||||
auto xmlIdx = xmlSIIP.child("Indices");
|
auto xmlIdx = xmlSIIP.child("Indices");
|
||||||
|
|
||||||
|
@ -261,15 +253,81 @@ unsigned int FezLoader::GetTrileMeshFromId(const int trileId) {
|
||||||
mesh->mTextureCoords[0][i] = v.texCoord;
|
mesh->mTextureCoords[0][i] = v.texCoord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FezLoader::GetTrileMeshFromId(const int trileId) {
|
||||||
|
if (auto search = mTrileMap.find(trileId); search != mTrileMap.end()) {
|
||||||
|
return search->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to create an aiMesh instance and add it to the vector.
|
||||||
|
auto trileXML = mTriles.at(trileId);
|
||||||
|
auto xmlSIIP = trileXML.child("Geometry").child("ShaderInstancedIndexedPrimitives");
|
||||||
|
|
||||||
|
// Create mesh
|
||||||
|
auto mesh = CreateMesh(xmlSIIP);
|
||||||
|
mesh->mName = "Trile#" + std::to_string(trileId);
|
||||||
|
|
||||||
// Only one material for all triles.
|
// Only one material for all triles.
|
||||||
mesh->mMaterialIndex = 0;
|
mesh->mMaterialIndex = 0;
|
||||||
|
|
||||||
// Add entry to trile map and add mesh to vector
|
// Add entry to trile map and add mesh to vector
|
||||||
mTrileMap[trileId] = mTrileMeshes.size();
|
mTrileMap[trileId] = mMeshes.size();
|
||||||
mTrileMeshes.push_back(mesh);
|
mMeshes.push_back(mesh);
|
||||||
|
|
||||||
return mTrileMap[trileId];
|
return mTrileMap[trileId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int FezLoader::GetArtObjectFromName(const std::string &name, IOSystem *pIOHandler) {
|
||||||
|
if (auto search = mAOMap.find(name); search != mAOMap.end()) {
|
||||||
|
return search->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto AOXmlPath = mFezAssetDir / "art objects" / (ai_tolower(name) + ".xml");
|
||||||
|
|
||||||
|
if (!pIOHandler->Exists(AOXmlPath)) {
|
||||||
|
ASSIMP_LOG_ERROR("Art Object specified that doesn't exist: ", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<IOStream> aoXmlFile;
|
||||||
|
aoXmlFile.reset(pIOHandler->Open(AOXmlPath));
|
||||||
|
|
||||||
|
XmlParser p;
|
||||||
|
p.parse(aoXmlFile.get());
|
||||||
|
|
||||||
|
XmlNode aoXmlRoot = p.getRootNode().child("ArtObject");
|
||||||
|
|
||||||
|
if (std::string(aoXmlRoot.name()) != name) {
|
||||||
|
ASSIMP_LOG_WARN("Art Object name mismatch! ", name, " != ", aoXmlRoot.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create mesh
|
||||||
|
aiMesh* m = CreateMesh(aoXmlRoot.child("ShaderInstancedIndexedPrimitives"));
|
||||||
|
m->mName = "AO_" + name;
|
||||||
|
|
||||||
|
// Load texture
|
||||||
|
auto myTex = CreateTex(mFezAssetDir / "art objects" / (ai_tolower(name) + ".png"), pIOHandler);
|
||||||
|
|
||||||
|
// Create material
|
||||||
|
auto myMat = new aiMaterial();
|
||||||
|
|
||||||
|
// Put tex ref into material
|
||||||
|
aiString tName('*' + std::to_string(mMaterials.size()));
|
||||||
|
myMat->AddProperty(&tName, AI_MATKEY_TEXTURE(aiTextureType_BASE_COLOR, 0));
|
||||||
|
mTextures.push_back(myTex);
|
||||||
|
|
||||||
|
// Put material ref into mesh
|
||||||
|
m->mMaterialIndex = mMaterials.size();
|
||||||
|
mMaterials.push_back(myMat);
|
||||||
|
|
||||||
|
auto i = mMeshes.size();
|
||||||
|
mAOMap[name] = i;
|
||||||
|
mMeshes.push_back(m);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
aiVector3D FezLoader::GetFezVec3(const XmlNode &t, bool direct) {
|
aiVector3D FezLoader::GetFezVec3(const XmlNode &t, bool direct) {
|
||||||
if (direct) {
|
if (direct) {
|
||||||
return {t.attribute("x").as_float(), t.attribute("y").as_float(), t.attribute("z").as_float()};
|
return {t.attribute("x").as_float(), t.attribute("y").as_float(), t.attribute("z").as_float()};
|
||||||
|
@ -287,6 +345,80 @@ aiVector2D FezLoader::GetFezVec2(const XmlNode &t, bool direct) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
void FezLoader::AddTrileInstances(const XmlNode &tis, aiNode *trileRoot) {
|
||||||
|
for (auto t : tis.children()) {
|
||||||
|
XmlNode instance;
|
||||||
|
if (std::string(t.name()) == "Entry") {
|
||||||
|
instance = t.child("TrileInstance");
|
||||||
|
} else if (std::string(t.name()) == "TrileInstance") {
|
||||||
|
instance = t;
|
||||||
|
} else {
|
||||||
|
ASSIMP_LOG_WARN("Trile instance not found in a node.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto trileID = instance.attribute("trileId").as_int(-1);
|
||||||
|
if (trileID == -1) {
|
||||||
|
ASSIMP_LOG_WARN("Trile instance found without a valid trileId!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto meshID = GetTrileMeshFromId(trileID);
|
||||||
|
|
||||||
|
// Create node, link found mesh
|
||||||
|
auto trileNode = new aiNode();
|
||||||
|
trileNode->mNumMeshes = 1;
|
||||||
|
trileNode->mMeshes = new unsigned int[1];
|
||||||
|
trileNode->mMeshes[0] = meshID;
|
||||||
|
|
||||||
|
trileNode->mName = aiString("Trile_ID#" + std::to_string(trileID));
|
||||||
|
auto pos = GetFezVec3(instance.child("Position"));
|
||||||
|
auto orient = instance.attribute("orientation").as_int(0);
|
||||||
|
|
||||||
|
// Create transformation matrix
|
||||||
|
aiMatrix4x4 transform = aiMatrix4x4::Translation(pos, transform);
|
||||||
|
aiMatrix4x4 rotate = aiMatrix4x4::RotationY(gc_orient[orient], rotate);
|
||||||
|
|
||||||
|
trileNode->mTransformation = transform * rotate;
|
||||||
|
|
||||||
|
trileRoot->addChildren(1, &trileNode);
|
||||||
|
|
||||||
|
auto overlapped = instance.child("OverlappedTriles");
|
||||||
|
if (!overlapped.empty()) {
|
||||||
|
AddTrileInstances(overlapped, trileRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aiTexture *FezLoader::CreateTex(const std::string &path, IOSystem *pIOHandler) {
|
||||||
|
// Create embedded texture ref
|
||||||
|
auto myTex = new aiTexture();
|
||||||
|
myTex->mFilename = path;
|
||||||
|
|
||||||
|
// PNG file, compressed
|
||||||
|
strcpy(myTex->achFormatHint, "png");
|
||||||
|
myTex->mHeight = 0;
|
||||||
|
|
||||||
|
// Open texture file for reading
|
||||||
|
std::unique_ptr<IOStream> texFile;
|
||||||
|
texFile.reset(pIOHandler->Open(path));
|
||||||
|
|
||||||
|
// Create buffer, read data, store into texture instance
|
||||||
|
auto texDat = new unsigned char[texFile->FileSize()];
|
||||||
|
myTex->mWidth = texFile->FileSize();
|
||||||
|
texFile->Read(texDat, 1, texFile->FileSize());
|
||||||
|
myTex->pcData = (aiTexel*)texDat;
|
||||||
|
|
||||||
|
return myTex;
|
||||||
|
}
|
||||||
|
aiQuaternion FezLoader::GetFezQuat(const XmlNode &t, bool direct) {
|
||||||
|
if (direct) {
|
||||||
|
return {t.attribute("w").as_float(), t.attribute("x").as_float(), t.attribute("y").as_float(), t.attribute("z").as_float()};
|
||||||
|
} else {
|
||||||
|
auto c = t.child("Quaternion");
|
||||||
|
return {c.attribute("w").as_float(), c.attribute("x").as_float(), c.attribute("y").as_float(), c.attribute("z").as_float()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <assimp/BaseImporter.h>
|
#include <assimp/BaseImporter.h>
|
||||||
#include <assimp/XmlParser.h>
|
#include <assimp/XmlParser.h>
|
||||||
#include <assimp/mesh.h>
|
#include <assimp/mesh.h>
|
||||||
|
#include <assimp/material.h>
|
||||||
|
#include <assimp/texture.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
@ -23,8 +25,14 @@ protected:
|
||||||
unsigned int GetTrileMeshFromId(const int trileId);
|
unsigned int GetTrileMeshFromId(const int trileId);
|
||||||
|
|
||||||
aiVector3D GetFezVec3(const XmlNode &t, bool direct = false);
|
aiVector3D GetFezVec3(const XmlNode &t, bool direct = false);
|
||||||
|
aiQuaternion GetFezQuat(const XmlNode &t, bool direct = false);
|
||||||
aiVector2D GetFezVec2(const XmlNode &t, bool direct = false);
|
aiVector2D GetFezVec2(const XmlNode &t, bool direct = false);
|
||||||
|
|
||||||
|
void AddTrileInstances(const XmlNode &tis, aiNode *trileRoot);
|
||||||
|
|
||||||
|
aiMesh *CreateMesh(const XmlNode &xmlSIIP);
|
||||||
|
|
||||||
|
aiTexture *CreateTex(const std::string &path, IOSystem *pIOHandler);
|
||||||
private:
|
private:
|
||||||
std::filesystem::path mFezAssetDir;
|
std::filesystem::path mFezAssetDir;
|
||||||
std::string mFileName;
|
std::string mFileName;
|
||||||
|
@ -33,7 +41,11 @@ private:
|
||||||
|
|
||||||
std::map<int, XmlNode> mTriles;
|
std::map<int, XmlNode> mTriles;
|
||||||
std::map<int, unsigned int> mTrileMap;
|
std::map<int, unsigned int> mTrileMap;
|
||||||
std::vector<aiMesh*> mTrileMeshes;
|
std::map<std::string, unsigned int> mAOMap;
|
||||||
|
std::vector<aiMesh*> mMeshes;
|
||||||
|
std::vector<aiMaterial*> mMaterials;
|
||||||
|
std::vector<aiTexture*> mTextures;
|
||||||
|
unsigned int GetArtObjectFromName(const std::string &name, IOSystem *pIOHandler);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue