diff --git a/code/AssetLib/FEZ/FezLoader.cpp b/code/AssetLib/FEZ/FezLoader.cpp index 9dc92c396..f72428daa 100644 --- a/code/AssetLib/FEZ/FezLoader.cpp +++ b/code/AssetLib/FEZ/FezLoader.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace Assimp { @@ -32,6 +33,7 @@ static const ai_real gc_orient[] = { AI_MATH_PI, -AI_MATH_HALF_PI, 0,AI_MATH_HALF_PI, }; + FezLoader::FezLoader() = default; FezLoader::~FezLoader() = default; @@ -173,6 +175,88 @@ void FezLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSyst aoRoot->addChildren(1, &aoNode); } + // Create child for background planes + auto bgpRoot = new aiNode("Background Planes"); + pScene->mRootNode->addChildren(1, &bgpRoot); + + // For some reason, it needs a positioning adjustment... + aiMatrix4x4::Translation(aiVector3D(-0.5,-0.5, -0.5), bgpRoot->mTransformation); + + auto xmlBGPRoot = levelRoot.child("BackgroundPlanes"); + for (auto t : xmlBGPRoot.children()) { + auto nodeName = std::string(t.name()); + if (nodeName != "Entry") { + ASSIMP_LOG_WARN("BackgroundPlanes child found that isn't Entry"); + continue; + } + + auto instance = t.child("BackgroundPlane"); + auto animated = instance.attribute("animated").as_bool(false); + if (animated) { + ASSIMP_LOG_WARN("Animated BackgroundPlane found, skipping"); + continue; + } + + auto bgpTexName = std::string(instance.attribute("textureName").as_string()); + + bool found = true; + auto bgpMesh = GetBackgroundPlaneFromName(bgpTexName, pIOHandler, found); + auto mesh = mMeshes[bgpMesh]; + auto mat = mMaterials[mesh->mMaterialIndex]; + + if (!found) { + + auto doubleSided = (int)instance.attribute("doubleSided").as_bool(false); + mat->AddProperty(&doubleSided, 1, AI_MATKEY_TWOSIDED); + + auto opacity = instance.attribute("opacity").as_float(1.0); + mat->AddProperty(&opacity, 1, AI_MATKEY_OPACITY); + + auto xTexRepeat = (int)(!instance.attribute("xTextureRepeat").as_bool(false)); + mat->AddProperty(&xTexRepeat, 1, AI_MATKEY_MAPPINGMODE_U(aiTextureType_BASE_COLOR, 0)); + + + auto yTexRepeat = (int)(!instance.attribute("yTextureRepeat").as_bool(false)); + mat->AddProperty(&yTexRepeat, 1, AI_MATKEY_MAPPINGMODE_V(aiTextureType_BASE_COLOR, 0)); + + // redundant probably? idk + // auto clampTex = instance.attribute("clampTexture").as_bool(false); + } + + // Create node, link found mesh + auto bgpNode = new aiNode(); + bgpNode->mNumMeshes = 1; + bgpNode->mMeshes = new unsigned int[1]; + bgpNode->mMeshes[0] = bgpMesh; + + bgpNode->mName = aiString("BGP_" + bgpTexName); + auto pos = GetFezVec3(instance.child("Position")); + auto rotate = GetFezQuat(instance.child("Rotation")); + auto scale = GetFezVec3(instance.child("Scale")); + + // Get scale again from texture { + aiString texRef; + mat->Get(AI_MATKEY_TEXTURE(aiTextureType_BASE_COLOR, 0), texRef); + + unsigned int texId = atoi(texRef.C_Str()+1); + aiTexture* bgpTex = mTextures[texId]; + + int width; + int height; + int comp; + stbi_info_from_memory(reinterpret_cast(bgpTex->pcData), (int)bgpTex->mWidth, &width, &height, &comp); + auto imageScaleVec = aiVector3D(scale.x * (width / 16.0f), scale.y * (height / 16.0f), scale.z * 1); + + // Create transformation matrix + aiMatrix4x4 scaling = aiMatrix4x4::Scaling(imageScaleVec, scaling); + auto rmMatrix = aiMatrix4x4 (aiVector3D (1,1,1), rotate, pos); + + + bgpNode->mTransformation = rmMatrix * scaling; + + bgpRoot->addChildren(1, &bgpNode); + } + // Fill in meshes from vector pScene->mNumMeshes = mMeshes.size(); pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; @@ -211,7 +295,6 @@ aiMesh *FezLoader::CreateMesh(const Assimp::XmlNode &xmlSIIP) { aiVector3D texCoord; }; std::vector vertex; - // TODO: check handedness/orientation for (auto v : xmlVerts.children()) { auto pos = GetFezVec3(v.child("Position")); auto normal = v.child("Normal").text().as_int(); @@ -256,7 +339,7 @@ aiMesh *FezLoader::CreateMesh(const Assimp::XmlNode &xmlSIIP) { return mesh; } -unsigned int FezLoader::GetTrileMeshFromId(const int trileId) { +unsigned int FezLoader::GetTrileMeshFromId(const int trileId, bool &valid) { if (auto search = mTrileMap.find(trileId); search != mTrileMap.end()) { return search->second; } @@ -267,6 +350,10 @@ unsigned int FezLoader::GetTrileMeshFromId(const int trileId) { // Create mesh auto mesh = CreateMesh(xmlSIIP); + if (mesh->mNumVertices == 0) { + valid = false; + return 0; + } mesh->mName = "Trile#" + std::to_string(trileId); // Only one material for all triles. @@ -276,9 +363,48 @@ unsigned int FezLoader::GetTrileMeshFromId(const int trileId) { mTrileMap[trileId] = mMeshes.size(); mMeshes.push_back(mesh); + valid = true; return mTrileMap[trileId]; } +unsigned int FezLoader::GetBackgroundPlaneFromName(const std::string &name, IOSystem *pIOHandler, bool &found) { + if (auto search = mBGPMap.find(name); search != mBGPMap.end()) { + found = true; + return search->second; + } + + found = false; + + auto BGPTexPath = mFezAssetDir / "background planes" / (ai_tolower(name) + ".png"); + + // Create material, mesh, and texture + auto myTex = CreateTex(BGPTexPath, pIOHandler); + auto myMesh = NewBGPlaneMesh(); + 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 + myMesh->mMaterialIndex = mMaterials.size(); + mMaterials.push_back(myMat); + + // Put mesh into vector + auto i = mMeshes.size(); + mBGPMap[name] = i; + mMeshes.push_back(myMesh); + + // Set parameters for material + int flags = aiTextureFlags_UseAlpha; + myMat->AddProperty(&flags, 1, AI_MATKEY_TEXFLAGS(aiTextureType_BASE_COLOR, 0)); + flags = aiBlendMode_Default; + myMat->AddProperty(&flags, 1, AI_MATKEY_BLEND_FUNC); + + return i; +} + unsigned int FezLoader::GetArtObjectFromName(const std::string &name, IOSystem *pIOHandler) { if (auto search = mAOMap.find(name); search != mAOMap.end()) { return search->second; @@ -299,8 +425,9 @@ unsigned int FezLoader::GetArtObjectFromName(const std::string &name, IOSystem * XmlNode aoXmlRoot = p.getRootNode().child("ArtObject"); - if (std::string(aoXmlRoot.name()) != name) { - ASSIMP_LOG_WARN("Art Object name mismatch! ", name, " != ", aoXmlRoot.name()); + std::string myaoname = aoXmlRoot.attribute("name").as_string(); + if (myaoname != name) { + ASSIMP_LOG_WARN("Art Object name mismatch! ", name, " != ", myaoname); } // Create mesh @@ -363,7 +490,13 @@ void FezLoader::AddTrileInstances(const XmlNode &tis, aiNode *trileRoot) { continue; } - auto meshID = GetTrileMeshFromId(trileID); + bool valid = true; + auto meshID = GetTrileMeshFromId(trileID, valid); + + if (!valid) { + ASSIMP_LOG_WARN("Trile instance found that's empty!"); + continue; + } // Create node, link found mesh auto trileNode = new aiNode(); @@ -420,6 +553,40 @@ aiQuaternion FezLoader::GetFezQuat(const XmlNode &t, bool direct) { } } +static aiFace bgPlaneFaces[4] = { + +}; +aiMesh *FezLoader::NewBGPlaneMesh() { + auto myMesh = new aiMesh(); + // Create plane + + // Two tris + myMesh->mNumFaces = 2; + myMesh->mFaces = new aiFace[2]; + myMesh->mFaces[0].mNumIndices = 3; + myMesh->mFaces[1].mNumIndices = 3; + myMesh->mFaces[0].mIndices = new unsigned int[3] {0, 2, 1}; + myMesh->mFaces[1].mIndices = new unsigned int[3] {2, 0, 3}; + + // Four verts + myMesh->mNumVertices = 4; + myMesh->mVertices = new aiVector3D[4] { + {-0.5, 0.5, 0}, + { 0.5, 0.5, 0}, + {0.5, -0.5, 0}, + {-0.5, -0.5, 0}, + }; + + // Texture coords + myMesh->mTextureCoords[0] = new aiVector3D[4] { + {0, 1, 0}, + {1, 1, 0}, + {1, 0, 0}, + {0, 0, 0}, + }; + return myMesh; +} + } #endif diff --git a/code/AssetLib/FEZ/FezLoader.h b/code/AssetLib/FEZ/FezLoader.h index ddc47de11..28fe46577 100644 --- a/code/AssetLib/FEZ/FezLoader.h +++ b/code/AssetLib/FEZ/FezLoader.h @@ -22,7 +22,7 @@ protected: void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override; - unsigned int GetTrileMeshFromId(const int trileId); + unsigned int GetTrileMeshFromId(const int trileId, bool &valid); aiVector3D GetFezVec3(const XmlNode &t, bool direct = false); aiQuaternion GetFezQuat(const XmlNode &t, bool direct = false); @@ -31,6 +31,7 @@ protected: void AddTrileInstances(const XmlNode &tis, aiNode *trileRoot); aiMesh *CreateMesh(const XmlNode &xmlSIIP); + aiMesh *NewBGPlaneMesh(); aiTexture *CreateTex(const std::string &path, IOSystem *pIOHandler); private: @@ -42,10 +43,12 @@ private: std::map mTriles; std::map mTrileMap; std::map mAOMap; + std::map mBGPMap; std::vector mMeshes; std::vector mMaterials; std::vector mTextures; unsigned int GetArtObjectFromName(const std::string &name, IOSystem *pIOHandler); + unsigned int GetBackgroundPlaneFromName(const std::string &name, IOSystem *pIOHandler, bool &found); }; }