From 8be1aff1bacc96c6cca0adb9fdda4f0b323a2dab Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Mon, 6 May 2013 12:58:57 -0700 Subject: [PATCH] Implemented KRContext::getResources FBX Importing toolchain now detects need for vertex tangent vectors based on presence of Normal maps, and only imports them when needed. If tangent vectors are needed, but not present in the FBX file, they are calculated during the import process. Importing tangents increases the size of the vertex data and reduces the ability to share vertexes for multiple faces when using indexed triangle rendering; therefore, they are imported sparingly. --- KREngine/kraken/KRAudioManager.cpp | 5 +++ KREngine/kraken/KRAudioManager.h | 2 ++ KREngine/kraken/KRContext.cpp | 39 ++++++++++++++++++++ KREngine/kraken/KRContext.h | 2 ++ KREngine/kraken/KRMaterial.cpp | 5 +++ KREngine/kraken/KRMaterial.h | 2 ++ KREngine/kraken/KRMaterialManager.cpp | 21 +++++++++-- KREngine/kraken/KRMaterialManager.h | 6 +++- KREngine/kraken/KRResource+fbx.cpp | 51 +++++++++++++++++---------- KREngine/kraken/KRUnknownManager.cpp | 5 +++ KREngine/kraken/KRUnknownManager.h | 2 ++ 11 files changed, 118 insertions(+), 22 deletions(-) diff --git a/KREngine/kraken/KRAudioManager.cpp b/KREngine/kraken/KRAudioManager.cpp index 6dfd7de..b87ebc2 100644 --- a/KREngine/kraken/KRAudioManager.cpp +++ b/KREngine/kraken/KRAudioManager.cpp @@ -104,6 +104,11 @@ void KRAudioManager::initAudio() } } +unordered_map &KRAudioManager::getSounds() +{ + return m_sounds; +} + bool KRAudioManager::getEnableAudio() { return m_enable_audio; diff --git a/KREngine/kraken/KRAudioManager.h b/KREngine/kraken/KRAudioManager.h index 1e7aebc..157c73a 100644 --- a/KREngine/kraken/KRAudioManager.h +++ b/KREngine/kraken/KRAudioManager.h @@ -80,6 +80,8 @@ public: KRAudioManager(KRContext &context); virtual ~KRAudioManager(); + unordered_map &getSounds(); + void add(KRAudioSample *Sound); KRAudioSample *load(const std::string &name, const std::string &extension, KRDataBlock *data); diff --git a/KREngine/kraken/KRContext.cpp b/KREngine/kraken/KRContext.cpp index 570e70f..ae815e1 100644 --- a/KREngine/kraken/KRContext.cpp +++ b/KREngine/kraken/KRContext.cpp @@ -131,6 +131,45 @@ KRUnknownManager *KRContext::getUnknownManager() { return m_pUnknownManager; } +std::vector KRContext::getResources() +{ + + std::vector resources; + + for(unordered_map::iterator itr = m_pSceneManager->getScenes().begin(); itr != m_pSceneManager->getScenes().end(); itr++) { + resources.push_back((*itr).second); + } + for(unordered_map::iterator itr = m_pTextureManager->getTextures().begin(); itr != m_pTextureManager->getTextures().end(); itr++) { + resources.push_back((*itr).second); + } + for(unordered_map::iterator itr = m_pMaterialManager->getMaterials().begin(); itr != m_pMaterialManager->getMaterials().end(); itr++) { + resources.push_back((*itr).second); + } + for(unordered_multimap::iterator itr = m_pModelManager->getModels().begin(); itr != m_pModelManager->getModels().end(); itr++) { + resources.push_back((*itr).second); + } + for(unordered_map::iterator itr = m_pAnimationManager->getAnimations().begin(); itr != m_pAnimationManager->getAnimations().end(); itr++) { + resources.push_back((*itr).second); + } + for(unordered_map::iterator itr = m_pAnimationCurveManager->getAnimationCurves().begin(); itr != m_pAnimationCurveManager->getAnimationCurves().end(); itr++) { + resources.push_back((*itr).second); + } + for(unordered_map::iterator itr = m_pSoundManager->getSounds().begin(); itr != m_pSoundManager->getSounds().end(); itr++) { + resources.push_back((*itr).second); + } + + unordered_map > unknowns = m_pUnknownManager->getUnknowns(); + for(unordered_map >::iterator itr = unknowns.begin(); itr != unknowns.end(); itr++) { + for(unordered_map::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr++) { + resources.push_back((*itr2).second); + } + } + + // FINDME, TODO - Not yet exporting shaders, as they are currently only being used as standard Kraken assets. In the future people may want their custom shaders to be exported. + + return resources; +} + void KRContext::loadResource(const std::string &file_name, KRDataBlock *data) { std::string name = KRResource::GetFileBase(file_name); std::string extension = KRResource::GetFileExtension(file_name); diff --git a/KREngine/kraken/KRContext.h b/KREngine/kraken/KRContext.h index aba1c64..47a0b34 100644 --- a/KREngine/kraken/KRContext.h +++ b/KREngine/kraken/KRContext.h @@ -72,6 +72,8 @@ public: long getAbsoluteTimeMilliseconds(); + std::vector getResources(); + private: KRBundleManager *m_pBundleManager; KRSceneManager *m_pSceneManager; diff --git a/KREngine/kraken/KRMaterial.cpp b/KREngine/kraken/KRMaterial.cpp index 46f90dc..855a698 100644 --- a/KREngine/kraken/KRMaterial.cpp +++ b/KREngine/kraken/KRMaterial.cpp @@ -75,6 +75,11 @@ std::string KRMaterial::getExtension() { return "mtl"; } +bool KRMaterial::needsVertexTangents() +{ + return m_normalMap.size() > 0; +} + bool KRMaterial::save(KRDataBlock &data) { std::stringstream stream; stream.precision(std::numeric_limits::digits10); diff --git a/KREngine/kraken/KRMaterial.h b/KREngine/kraken/KRMaterial.h index 8ff4259..a87e957 100644 --- a/KREngine/kraken/KRMaterial.h +++ b/KREngine/kraken/KRMaterial.h @@ -85,6 +85,8 @@ public: bool bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, KRCamera *pCamera, std::vector &point_lights, std::vector &directional_lights, std::vector&spot_lights, const std::vector &bones, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass); + bool needsVertexTangents(); + private: std::string m_name; diff --git a/KREngine/kraken/KRMaterialManager.cpp b/KREngine/kraken/KRMaterialManager.cpp index 6b1a9f8..5f9d568 100644 --- a/KREngine/kraken/KRMaterialManager.cpp +++ b/KREngine/kraken/KRMaterialManager.cpp @@ -44,6 +44,11 @@ KRMaterialManager::~KRMaterialManager() { } +unordered_map &KRMaterialManager::getMaterials() +{ + return m_materials; +} + void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) { if(blend_enable) { GLDEBUG(glEnable(GL_BLEND)); @@ -67,21 +72,31 @@ void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum bl } -KRMaterial *KRMaterialManager::getMaterial(const char *szName) { - std::string lowerName = szName; +KRMaterial *KRMaterialManager::getMaterial(const std::string &name) { + std::string lowerName = name; std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); unordered_map::iterator itr = m_materials.find(lowerName); if(itr == m_materials.end()) { - fprintf(stderr, "Material not found: %s\n", szName); + fprintf(stderr, "Material not found: %s\n", name.c_str()); // Not found return NULL; } else { return (*itr).second; } } + +void KRMaterialManager::add(KRMaterial *new_material) { + // FINDME, TODO - Potential memory leak if multiple materials with the same name are added + std::string lowerName = new_material->getName(); + std::transform(lowerName.begin(), lowerName.end(), + lowerName.begin(), ::tolower); + + m_materials[lowerName] = new_material; +} + bool KRMaterialManager::load(const char *szName, KRDataBlock *data) { KRMaterial *pMaterial = NULL; char szSymbol[16][256]; diff --git a/KREngine/kraken/KRMaterialManager.h b/KREngine/kraken/KRMaterialManager.h index 7e044c1..d2e85b1 100644 --- a/KREngine/kraken/KRMaterialManager.h +++ b/KREngine/kraken/KRMaterialManager.h @@ -50,10 +50,14 @@ public: virtual ~KRMaterialManager(); bool load(const char *szName, KRDataBlock *data); - KRMaterial *getMaterial(const char *szName); + void add(KRMaterial *new_material); + KRMaterial *getMaterial(const std::string &name); void configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable); + + unordered_map &getMaterials(); + private: unordered_map m_materials; KRTextureManager *m_pTextureManager; diff --git a/KREngine/kraken/KRResource+fbx.cpp b/KREngine/kraken/KRResource+fbx.cpp index cc19d67..aa45d63 100644 --- a/KREngine/kraken/KRResource+fbx.cpp +++ b/KREngine/kraken/KRResource+fbx.cpp @@ -122,6 +122,15 @@ std::vector KRResource::LoadFbx(KRContext &context, const std::str } } + // ----====---- Import Materials ----====---- + int material_count = pFbxScene->GetSrcObjectCount(); + printf("\nLoading materials...\n"); + for(int i=0; i < material_count; i++) { + FbxSurfaceMaterial *material = pFbxScene->GetSrcObject(i); + printf(" Material %i of %i: %s\n", i+1, material_count, material->GetName()); + LoadMaterial(context, resources, material); + } + // ----====---- Import Meshes ----====---- int mesh_count = pFbxScene->GetSrcObjectCount(); printf("\nLoading meshes...\n"); @@ -132,15 +141,6 @@ std::vector KRResource::LoadFbx(KRContext &context, const std::str LoadMesh(context, resources, pGeometryConverter, mesh); } - // ----====---- Import Materials ----====---- - int material_count = pFbxScene->GetSrcObjectCount(); - printf("\nLoading materials...\n"); - for(int i=0; i < material_count; i++) { - FbxSurfaceMaterial *material = pFbxScene->GetSrcObject(i); - printf(" Material %i of %i: %s\n", i+1, material_count, material->GetName()); - LoadMaterial(context, resources, material); - } - // ----====---- Import Textures ----====---- int texture_count = pFbxScene->GetSrcObjectCount(); @@ -162,13 +162,8 @@ std::vector KRResource::LoadFbx(KRContext &context, const std::str } } - for(unordered_map::iterator texture_itr = context.getTextureManager()->getTextures().begin(); texture_itr != context.getTextureManager()->getTextures().end(); texture_itr++) { - resources.push_back((*texture_itr).second); - } - - for(unordered_map::iterator mesh_itr = context.getModelManager()->getModels().begin(); mesh_itr != context.getModelManager()->getModels().end(); mesh_itr++) { - resources.push_back((*mesh_itr).second); - } + std::vector resources2 = context.getResources(); + resources.insert(resources.begin(), resources2.begin(), resources2.end()); DestroySdkObjects(lSdkManager); @@ -1044,6 +1039,7 @@ void LoadMaterial(KRContext &context, std::vector &resources, FbxS } } + /* bool bFound = false; for(vector::iterator resource_itr = resources.begin(); resource_itr != resources.end(); resource_itr++) { KRResource *pResource = (*resource_itr); @@ -1056,7 +1052,16 @@ void LoadMaterial(KRContext &context, std::vector &resources, FbxS } else { resources.push_back(new_material); } - + */ + + + // Only save unique materials + KRMaterial *found_material = context.getMaterialManager()->getMaterial(new_material->getName()); + if(found_material == NULL) { + context.getMaterialManager()->add(new_material); + } else { + delete new_material; + } } void LoadMesh(KRContext &context, std::vector &resources, FbxGeometryConverter *pGeometryConverter, KFbxMesh* pSourceMesh) { @@ -1162,8 +1167,18 @@ void LoadMesh(KRContext &context, std::vector &resources, FbxGeome int dest_vertex_id = 0; + bool need_tangents = false; + for(int iMaterial=0; iMaterial < material_count; iMaterial++) { KFbxSurfaceMaterial *pMaterial = pSourceMesh->GetNode()->GetMaterial(iMaterial); + + KRMaterial *material = context.getMaterialManager()->getMaterial(pMaterial->GetName()); + if(material) { + if(material->needsVertexTangents()) { + need_tangents = true; + } + } + int source_vertex_id = 0; int mat_vertex_count = 0; int mat_vertex_start = dest_vertex_id; @@ -1294,7 +1309,7 @@ void LoadMesh(KRContext &context, std::vector &resources, FbxGeome KRMesh *new_mesh = new KRMesh(context, pSourceMesh->GetNode()->GetName()); std::vector<__uint16_t> vertex_indexes; std::vector > vertex_index_bases; - new_mesh->LoadData(vertex_indexes, vertex_index_bases, vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights,KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES, true, false); // FINDME, HACK! "false" set for importing tangents so that we can merge more vertices in the index buffer. This should be configurable by the end-user so if normal maps are required and no tangents are included in the model, they can be calculated + new_mesh->LoadData(vertex_indexes, vertex_index_bases, vertices, uva, uvb, normals, tangents, submesh_starts, submesh_lengths, material_names, bone_names, bone_indexes, bone_weights,KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES, true, need_tangents); context.getModelManager()->addModel(new_mesh); } diff --git a/KREngine/kraken/KRUnknownManager.cpp b/KREngine/kraken/KRUnknownManager.cpp index 2f174a4..cdfc78b 100644 --- a/KREngine/kraken/KRUnknownManager.cpp +++ b/KREngine/kraken/KRUnknownManager.cpp @@ -46,6 +46,11 @@ KRUnknownManager::~KRUnknownManager() } } +unordered_map > &KRUnknownManager::getUnknowns() +{ + return m_unknowns; +} + void KRUnknownManager::add(KRUnknown *unknown) { std::string lower_name = unknown->getName(); diff --git a/KREngine/kraken/KRUnknownManager.h b/KREngine/kraken/KRUnknownManager.h index 05599c6..c2440a5 100644 --- a/KREngine/kraken/KRUnknownManager.h +++ b/KREngine/kraken/KRUnknownManager.h @@ -51,6 +51,8 @@ public: const unordered_map &get(const std::string &extension); + unordered_map > &getUnknowns(); + private: unordered_map > m_unknowns; };