From 42614d88e9eab1ba0a63e9cb1ee1d2952e701232 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Thu, 6 Feb 2020 15:59:55 -0800 Subject: [PATCH 1/9] update drawables to reference shader manager update resource manager to use new ShaderManager flat shading override for scenes --- src/esp/assets/GltfMeshData.cpp | 3 +- src/esp/assets/ResourceManager.cpp | 279 ++++++++++++++++------------ src/esp/assets/ResourceManager.h | 161 +++++++++------- src/esp/gfx/CMakeLists.txt | 4 + src/esp/gfx/Drawable.cpp | 6 +- src/esp/gfx/Drawable.h | 4 +- src/esp/gfx/GenericDrawable.cpp | 109 ++++++++--- src/esp/gfx/GenericDrawable.h | 29 ++- src/esp/gfx/LightSetup.cpp | 42 +++++ src/esp/gfx/LightSetup.h | 54 ++++++ src/esp/gfx/MaterialData.h | 30 +++ src/esp/gfx/PTexMeshDrawable.cpp | 24 ++- src/esp/gfx/PTexMeshDrawable.h | 7 +- src/esp/gfx/PrimitiveIDDrawable.cpp | 24 ++- src/esp/gfx/PrimitiveIDDrawable.h | 7 +- src/esp/gfx/ShaderManager.h | 21 +++ src/esp/sim/Simulator.cpp | 4 + src/utils/viewer/viewer.cpp | 3 + 18 files changed, 569 insertions(+), 242 deletions(-) create mode 100644 src/esp/gfx/LightSetup.cpp create mode 100644 src/esp/gfx/LightSetup.h create mode 100644 src/esp/gfx/MaterialData.h create mode 100644 src/esp/gfx/ShaderManager.h diff --git a/src/esp/assets/GltfMeshData.cpp b/src/esp/assets/GltfMeshData.cpp index b8309acb95..e4966f0cb1 100644 --- a/src/esp/assets/GltfMeshData.cpp +++ b/src/esp/assets/GltfMeshData.cpp @@ -19,7 +19,8 @@ void GltfMeshData::uploadBuffersToGPU(bool forceReload) { renderingBuffer_.reset(); renderingBuffer_ = std::make_unique(); // position, normals, uv, colors are bound to corresponding attributes - renderingBuffer_->mesh = Magnum::MeshTools::compile(*meshData_); + renderingBuffer_->mesh = Magnum::MeshTools::compile( + *meshData_, Magnum::MeshTools::CompileFlag::GenerateSmoothNormals); buffersOnGPU_ = true; } diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index e130a51b00..a713f5eafd 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -66,6 +66,16 @@ namespace Mn = Magnum; namespace esp { namespace assets { +// static constexpr arrays require redundant definitions until C++17 +constexpr char ResourceManager::NO_LIGHT_KEY[]; +constexpr char ResourceManager::DEFAULT_LIGHTING_KEY[]; +constexpr char ResourceManager::DEFAULT_MATERIAL_KEY[]; + +ResourceManager::ResourceManager() { + initDefaultLightSetups(); + initDefaultMaterials(); +} + bool ResourceManager::loadScene(const AssetInfo& info, scene::SceneNode* parent, /* = nullptr */ DrawableGroup* drawables /* = nullptr */) { @@ -91,10 +101,11 @@ bool ResourceManager::loadScene(const AssetInfo& info, } else if (info.type == AssetType::SUNCG_SCENE) { meshSuccess = loadSUNCGHouseFile(info, parent, drawables); } else if (info.type == AssetType::MP3D_MESH) { - meshSuccess = loadGeneralMeshData(info, parent, drawables); + // for now, force scenes to be flat shaded + meshSuccess = loadGeneralMeshData(info, parent, drawables, true); } else { // Unknown type, just load general mesh data - meshSuccess = loadGeneralMeshData(info, parent, drawables); + meshSuccess = loadGeneralMeshData(info, parent, drawables, true); } // add a scene attributes for this filename or modify the existing one if (meshSuccess) { @@ -427,7 +438,9 @@ int ResourceManager::loadObject(const std::string& objPhysConfigFilename, physicsObjectAttributes.getMagnumVec3("scale"); scalingNode.setScaling(objectScaling); - addComponent(meshMetaData, scalingNode, drawables, meshMetaData.root); + // TODO: make lighting selection configurable + addComponent(meshMetaData, scalingNode, DEFAULT_LIGHTING_KEY, drawables, + meshMetaData.root); // compute the full BB hierarchy for the new tree. parent->computeCumulativeBB(); } @@ -851,50 +864,6 @@ void ResourceManager::translateMesh(BaseMesh* meshDataGL, meshDataGL->BB = meshDataGL->BB.translated(translation); } -Magnum::GL::AbstractShaderProgram* ResourceManager::getShaderProgram( - ShaderType type) { - if (shaderPrograms_.count(type) == 0) { - switch (type) { - case INSTANCE_MESH_SHADER: { - shaderPrograms_[INSTANCE_MESH_SHADER] = - std::make_shared(); - } break; - -#ifdef ESP_BUILD_PTEX_SUPPORT - case PTEX_MESH_SHADER: { - shaderPrograms_[PTEX_MESH_SHADER] = - std::make_shared(); - } break; -#endif - - case COLORED_SHADER: { - shaderPrograms_[COLORED_SHADER] = - std::make_shared( - Magnum::Shaders::Flat3D::Flag::ObjectId); - } break; - - case VERTEX_COLORED_SHADER: { - shaderPrograms_[VERTEX_COLORED_SHADER] = - std::make_shared( - Magnum::Shaders::Flat3D::Flag::ObjectId | - Magnum::Shaders::Flat3D::Flag::VertexColor); - } break; - - case TEXTURED_SHADER: { - shaderPrograms_[TEXTURED_SHADER] = - std::make_shared( - Magnum::Shaders::Flat3D::Flag::ObjectId | - Magnum::Shaders::Flat3D::Flag::Textured); - } break; - - default: - return nullptr; - break; - } - } - return shaderPrograms_[type].get(); -} - bool ResourceManager::loadPTexMeshData(const AssetInfo& info, scene::SceneNode* parent, DrawableGroup* drawables) { @@ -924,9 +893,6 @@ bool ResourceManager::loadPTexMeshData(const AssetInfo& info, // create the scene graph by request if (parent) { - auto* ptexShader = - dynamic_cast(getShaderProgram(PTEX_MESH_SHADER)); - auto indexPair = resourceDict_.at(filename).meshIndex; int start = indexPair.first; int end = indexPair.second; @@ -941,9 +907,8 @@ bool ResourceManager::loadPTexMeshData(const AssetInfo& info, const quatf transform = info.frame.rotationFrameToWorld(); node.setRotation(Magnum::Quaternion(transform)); - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - new gfx::PTexMeshDrawable{node, *ptexShader, *pTexMeshData, jSubmesh, - drawables}; + node.addFeature(*pTexMeshData, jSubmesh, + shaderManager_, drawables); if (computeAbsoluteAABBs_) { staticDrawableInfo_.emplace_back( @@ -996,8 +961,8 @@ bool ResourceManager::loadInstanceMeshData(const AssetInfo& info, auto* instanceMeshData = dynamic_cast(meshes_[iMesh].get()); scene::SceneNode& node = parent->createChild(); - createDrawable(INSTANCE_MESH_SHADER, *instanceMeshData->getMagnumGLMesh(), - node, drawables); + node.addFeature( + *instanceMeshData->getMagnumGLMesh(), shaderManager_, drawables); } } @@ -1007,7 +972,8 @@ bool ResourceManager::loadInstanceMeshData(const AssetInfo& info, bool ResourceManager::loadGeneralMeshData( const AssetInfo& info, scene::SceneNode* parent /* = nullptr */, - DrawableGroup* drawables /* = nullptr */) { + DrawableGroup* drawables /* = nullptr */, + bool forceFlatShading /* = false */) { const std::string& filename = info.filepath; const bool fileIsLoaded = resourceDict_.count(filename) > 0; const bool drawData = parent != nullptr && drawables != nullptr; @@ -1112,7 +1078,7 @@ bool ResourceManager::loadGeneralMeshData( } // if this is a new file, load it and add it to the dictionary loadTextures(*importer, &metaData); - loadMaterials(*importer, &metaData); + loadMaterials(*importer, &metaData, forceFlatShading); loadMeshes(*importer, &metaData); resourceDict_.emplace(filename, metaData); @@ -1170,21 +1136,23 @@ bool ResourceManager::loadGeneralMeshData( } } // forceReload - addComponent(metaData, newNode, drawables, metaData.root); + // TODO: make this configurable + Mn::ResourceKey lightSetup{forceFlatShading ? NO_LIGHT_KEY + : DEFAULT_LIGHTING_KEY}; + addComponent(metaData, newNode, lightSetup, drawables, metaData.root); return true; } } void ResourceManager::loadMaterials(Importer& importer, - MeshMetaData* metaData) { - int materialStart = materials_.size(); + MeshMetaData* metaData, + bool forceFlatShading) { + int materialStart = nextMaterialID_; int materialEnd = materialStart + importer.materialCount() - 1; metaData->setMaterialIndices(materialStart, materialEnd); for (int iMaterial = 0; iMaterial < importer.materialCount(); ++iMaterial) { - // default null material - materials_.emplace_back(nullptr); - auto& currentMaterial = materials_.back(); + int currentMaterialID = nextMaterialID_++; // TODO: // it seems we have a way to just load the material once in this case, @@ -1197,12 +1165,86 @@ void ResourceManager::loadMaterials(Importer& importer, continue; } - // using make_unique will not work here - std::unique_ptr phongMaterialData( - static_cast(materialData.release())); + const auto& phongMaterialData = + static_cast(*materialData); + std::unique_ptr finalMaterial; + if (forceFlatShading) { + finalMaterial = getFlatShadedMaterialData(phongMaterialData, + metaData->textureIndex.first); + } else { + finalMaterial = getPhongShadedMaterialData(phongMaterialData, + metaData->textureIndex.first); + } + // for now, just use unique ID for material key. This may change if we + // expose materials to user for post-load modification + shaderManager_.set(std::to_string(currentMaterialID), + finalMaterial.release()); + } +} - currentMaterial = std::move(phongMaterialData); +gfx::PhongMaterialData::uptr ResourceManager::getFlatShadedMaterialData( + const Mn::Trade::PhongMaterialData& material, + int textureBaseIndex) { + // NOLINTNEXTLINE(google-build-using-namespace) + using namespace Mn::Math::Literals; + + auto finalMaterial = gfx::PhongMaterialData::create_unique(); + finalMaterial->ambientColor = 0xffffffff_rgbaf; + finalMaterial->diffuseColor = 0x00000000_rgbaf; + finalMaterial->specularColor = 0x00000000_rgbaf; + + if (material.flags() & Mn::Trade::PhongMaterialData::Flag::AmbientTexture) { + finalMaterial->ambientTexture = + textures_[textureBaseIndex + material.ambientTexture()].get(); + } else if (material.flags() & + Mn::Trade::PhongMaterialData::Flag::DiffuseTexture) { + // if we want to force flat shading, but we don't have ambient texture, + // check for diffuse texture and use that instead + finalMaterial->ambientTexture = + textures_[textureBaseIndex + material.diffuseTexture()].get(); + } else { + finalMaterial->ambientColor = material.ambientColor(); } + return finalMaterial; +} + +gfx::PhongMaterialData::uptr ResourceManager::getPhongShadedMaterialData( + const Mn::Trade::PhongMaterialData& material, + int textureBaseIndex) { + // NOLINTNEXTLINE(google-build-using-namespace) + using namespace Mn::Math::Literals; + + auto finalMaterial = gfx::PhongMaterialData::create_unique(); + // TODO: figure out why materials are being loaded with shininess == 1 + finalMaterial->shininess = std::max(material.shininess(), 80.f); + + // ambient material properties + if (material.flags() & Mn::Trade::PhongMaterialData::Flag::AmbientTexture) { + finalMaterial->ambientTexture = + textures_[textureBaseIndex + material.ambientTexture()].get(); + finalMaterial->ambientColor = 0xffffffff_rgbaf; + } else { + finalMaterial->ambientColor = material.ambientColor(); + } + + // diffuse material properties + if (material.flags() & Mn::Trade::PhongMaterialData::Flag::DiffuseTexture) { + finalMaterial->diffuseTexture = + textures_[textureBaseIndex + material.diffuseTexture()].get(); + finalMaterial->diffuseColor = 0xffffffff_rgbaf; + } else { + finalMaterial->diffuseColor = material.diffuseColor(); + } + + // specular material properties + if (material.flags() & Mn::Trade::PhongMaterialData::Flag::SpecularTexture) { + finalMaterial->specularTexture = + textures_[textureBaseIndex + material.specularTexture()].get(); + finalMaterial->specularColor = 0xffffffff_rgbaf; + } else { + finalMaterial->specularColor = material.specularColor(); + } + return finalMaterial; } void ResourceManager::loadMeshes(Importer& importer, MeshMetaData* metaData) { @@ -1325,6 +1367,7 @@ void ResourceManager::loadTextures(Importer& importer, MeshMetaData* metaData) { //! instantiated any time after initial loading void ResourceManager::addComponent(const MeshMetaData& metaData, scene::SceneNode& parent, + const Mn::ResourceKey& lightSetup, DrawableGroup* drawables, const MeshTransformNode& meshTransformNode) { // Add the object to the scene and set its transformation @@ -1337,8 +1380,9 @@ void ResourceManager::addComponent(const MeshMetaData& metaData, // Add a drawable if the object has a mesh and the mesh is loaded if (meshIDLocal != ID_UNDEFINED) { const int materialIDLocal = meshTransformNode.materialIDLocal; - addMeshToDrawables(metaData, node, drawables, meshTransformNode.componentID, - meshIDLocal, materialIDLocal); + addMeshToDrawables(metaData, node, lightSetup, drawables, + meshTransformNode.componentID, meshIDLocal, + materialIDLocal); // compute the bounding box for the mesh we are adding const int meshID = metaData.meshIndex.first + meshIDLocal; @@ -1348,12 +1392,13 @@ void ResourceManager::addComponent(const MeshMetaData& metaData, // Recursively add children for (auto& child : meshTransformNode.children) { - addComponent(metaData, node, drawables, child); + addComponent(metaData, node, lightSetup, drawables, child); } } void ResourceManager::addMeshToDrawables(const MeshMetaData& metaData, scene::SceneNode& node, + const Mn::ResourceKey& lightSetup, DrawableGroup* drawables, int objectID, int meshIDLocal, @@ -1362,39 +1407,17 @@ void ResourceManager::addMeshToDrawables(const MeshMetaData& metaData, const uint32_t meshID = meshStart + meshIDLocal; Magnum::GL::Mesh& mesh = *meshes_[meshID]->getMagnumGLMesh(); - const int materialStart = metaData.materialIndex.first; - const int materialID = materialStart + materialIDLocal; - - Magnum::GL::Texture2D* texture = nullptr; - // Material not set / not available / not loaded, use a default material + Mn::ResourceKey materialKey; if (materialIDLocal == ID_UNDEFINED || - metaData.materialIndex.second == ID_UNDEFINED || - !materials_[materialID]) { - createDrawable(COLORED_SHADER, mesh, node, drawables, texture, objectID); + metaData.materialIndex.second == ID_UNDEFINED) { + materialKey = DEFAULT_MATERIAL_KEY; } else { - if (materials_[materialID]->flags() & - Magnum::Trade::PhongMaterialData::Flag::DiffuseTexture) { - // Textured material. If the texture failed to load, again just use - // a default colored material. - const int textureStart = metaData.textureIndex.first; - const int textureIndex = materials_[materialID]->diffuseTexture(); - texture = textures_[textureStart + textureIndex].get(); - if (texture) { - createDrawable(TEXTURED_SHADER, mesh, node, drawables, texture, - objectID); - } else { - // Color-only material - createDrawable(COLORED_SHADER, mesh, node, drawables, texture, objectID, - materials_[materialID]->diffuseColor()); - } - } else { - // TODO: some types (such as .ply with vertex color) get binned here - // incorrectly. - // Color-only material - createDrawable(COLORED_SHADER, mesh, node, drawables, texture, objectID, - materials_[materialID]->diffuseColor()); - } - } // else + materialKey = + std::to_string(metaData.materialIndex.first + materialIDLocal); + } + + createGenericDrawable(mesh, node, lightSetup, materialKey, drawables, + objectID); if (computeAbsoluteAABBs_) { staticDrawableInfo_.emplace_back(StaticDrawableInfo{node, meshID}); @@ -1405,31 +1428,30 @@ void ResourceManager::addPrimitiveToDrawables(int primitiveID, scene::SceneNode& node, DrawableGroup* drawables) { CHECK(primitiveID >= 0 && primitiveID < primitive_meshes_.size()); - createDrawable(ShaderType::COLORED_SHADER, primitive_meshes_[primitiveID], - node, drawables); + createGenericDrawable(primitive_meshes_[primitiveID], node, + DEFAULT_LIGHTING_KEY, DEFAULT_MATERIAL_KEY, drawables); +} + +void ResourceManager::setLightSetup(const Mn::ResourceKey& key, + gfx::LightSetup setup) { + shaderManager_.set(key, std::move(setup), Mn::ResourceDataState::Mutable, + Mn::ResourcePolicy::Manual); +} + +Mn::Resource ResourceManager::getLightSetup( + const Mn::ResourceKey& key) { + return shaderManager_.get(key); } -void ResourceManager::createDrawable( - const ShaderType shaderType, - Magnum::GL::Mesh& mesh, +void ResourceManager::createGenericDrawable( + Mn::GL::Mesh& mesh, scene::SceneNode& node, + const Mn::ResourceKey& lightSetup, + const Mn::ResourceKey& material, DrawableGroup* group /* = nullptr */, - Magnum::GL::Texture2D* texture /* = nullptr */, - int objectId /* = ID_UNDEFINED */, - const Magnum::Color4& color /* = Magnum::Color4{1} */) { - if (shaderType == PTEX_MESH_SHADER) { - LOG(FATAL) << "ResourceManager::createDrawable does not support " - "PTEX_MESH_SHADER"; - } else if (shaderType == INSTANCE_MESH_SHADER) { - auto* shader = - static_cast(getShaderProgram(shaderType)); - node.addFeature(*shader, mesh, group); - } else { // all other shaders use GenericShader - auto* shader = - static_cast(getShaderProgram(shaderType)); - node.addFeature(*shader, mesh, group, texture, - objectId, color); - } + int objectId /* = ID_UNDEFINED */) { + node.addFeature(mesh, shaderManager_, lightSetup, + material, group, objectId); } bool ResourceManager::loadSUNCGHouseFile(const AssetInfo& houseInfo, @@ -1469,7 +1491,7 @@ bool ResourceManager::loadSUNCGHouseFile(const AssetInfo& houseInfo, nodeIds.push_back(id); objectNode.setId(nodeIndex); if (info.type == AssetType::SUNCG_OBJECT) { - loadGeneralMeshData(info, &objectNode, drawables); + loadGeneralMeshData(info, &objectNode, drawables, true); } return objectNode; }; @@ -1520,6 +1542,17 @@ bool ResourceManager::loadSUNCGHouseFile(const AssetInfo& houseInfo, return true; } +void ResourceManager::initDefaultLightSetups() { + shaderManager_.set(NO_LIGHT_KEY, gfx::LightSetup{}); + shaderManager_.setFallback(gfx::LightSetup{}); +} + +void ResourceManager::initDefaultMaterials() { + shaderManager_.set(DEFAULT_MATERIAL_KEY, + new gfx::PhongMaterialData{}); + shaderManager_.setFallback(new gfx::PhongMaterialData{}); +} + //! recursively join all sub-components of a mesh into a single unified //! MeshData. void ResourceManager::joinHeirarchy( diff --git a/src/esp/assets/ResourceManager.h b/src/esp/assets/ResourceManager.h index 29ed4b4b34..878868214d 100644 --- a/src/esp/assets/ResourceManager.h +++ b/src/esp/assets/ResourceManager.h @@ -29,6 +29,8 @@ #include "MeshData.h" #include "MeshMetaData.h" #include "esp/gfx/DrawableGroup.h" +#include "esp/gfx/MaterialData.h" +#include "esp/gfx/ShaderManager.h" #include "esp/gfx/configure.h" #include "esp/physics/PhysicsManager.h" #include "esp/scene/SceneNode.h" @@ -63,7 +65,7 @@ namespace assets { class ResourceManager { public: /** @brief Constructor */ - explicit ResourceManager(){}; + explicit ResourceManager(); /** @brief Destructor */ ~ResourceManager() {} @@ -338,6 +340,32 @@ class ResourceManager { scene::SceneNode& node, DrawableGroup* drawables); + /** + * @brief Set a named @ref LightSetup + * + * If this name already exists, the @ref LightSetup is updated and all @ref + * Drawables using this setup are updated. + * + * @param key Key to identify this @ref LightSetup + * @param setup Light setup this key will now references + */ + void setLightSetup(const Magnum::ResourceKey& key, gfx::LightSetup setup); + + /** + * @brief Get a named @ref LightSetup + */ + Magnum::Resource getLightSetup( + const Magnum::ResourceKey& key); + + //! @brief The @ref ShaderManager key for @ref LightInfo which has no lights + static constexpr char NO_LIGHT_KEY[] = "no_lights"; + + //! @brief The @ref ShaderManager key for the default @ref LightInfo + static constexpr char DEFAULT_LIGHTING_KEY[] = "default_lighting"; + + //! @brief The @ref ShaderManager key for the default @ref MaterialInfo + static constexpr char DEFAULT_MATERIAL_KEY[] = "default_material"; + protected: //======== Scene Functions ======== @@ -354,9 +382,12 @@ class ResourceManager { * rendered. * @param meshTransformNode The @ref MeshTransformNode for component * identifying its mesh, material, transformation, and children. + * @param lightSetup The @ref LightSetup key that will be used + * for the added component. */ void addComponent(const MeshMetaData& metaData, scene::SceneNode& parent, + const Magnum::ResourceKey& lightSetup, DrawableGroup* drawables, const MeshTransformNode& meshTransformNode); @@ -416,8 +447,36 @@ class ResourceManager { * * @param importer The importer already loaded with information for the asset. * @param metaData The asset's @ref MeshMetaData object. + * @param forceFlatShading Only bind ambient textures and colors. + */ + void loadMaterials(Importer& importer, + MeshMetaData* metaData, + bool forceFlatShading = false); + + /** + * @brief Get a @ref PhongMaterialData for use with flat shading + * + * Textures must already be loaded for the asset this material belongs to + * + * @param material Material data with texture IDs + * @param textureBaseIndex Base index of the assets textures in textures_ + */ + gfx::PhongMaterialData::uptr getFlatShadedMaterialData( + const Magnum::Trade::PhongMaterialData& material, + int textureBaseIndex); + + /** + * @brief Get a @ref PhongMaterialData for use with phong shading + * + * Textures must already be loaded for the asset this material belongs to + * + * @param material Material data with texture IDs + * @param textureBaseIndex Base index of the assets textures in textures_ + */ - void loadMaterials(Importer& importer, MeshMetaData* metaData); + gfx::PhongMaterialData::uptr getPhongShadedMaterialData( + const Magnum::Trade::PhongMaterialData& material, + int textureBaseIndex); /** * @brief Load a PTex mesh into assets from a file and add it to the scene @@ -460,7 +519,8 @@ class ResourceManager { */ bool loadGeneralMeshData(const AssetInfo& info, scene::SceneNode* parent = nullptr, - DrawableGroup* drawables = nullptr); + DrawableGroup* drawables = nullptr, + bool forceFlatShading = false); /** * @brief Load a SUNCG mesh into assets from a file. !Deprecated! TODO: @@ -476,6 +536,16 @@ class ResourceManager { scene::SceneNode* parent, DrawableGroup* drawables); + /** + * @brief initialize default lighting setups in the current ShaderManager + */ + void initDefaultLightSetups(); + + /** + * @brief initialize default material setups in the current ShaderManager + */ + void initDefaultMaterials(); + // ======== Geometry helper functions, data structures ======== /** @@ -554,9 +624,9 @@ class ResourceManager { std::vector> textures_; /** - * @brief The material data for loaded assets. + * @brief The next available unique ID for loaded materials */ - std::vector> materials_; + int nextMaterialID_ = 0; /** * @brief A pointer to render mesh data for the most recently loaded instance @@ -572,6 +642,12 @@ class ResourceManager { */ std::map resourceDict_; // meshes + /** + * @brief The @ref ShaderManager used to store shader information for + * drawables created by this ResourceManager + */ + gfx::ShaderManager shaderManager_; + // ======== Physical parameter data ======== /** @@ -629,6 +705,8 @@ class ResourceManager { * @param metaData Object meta data for the asset this mesh is linked to. * @param node The @ref scene::SceneNode which the new @ref gfx::Drawable will * be attached to. + * @param lightSetup The @ref LightSetup key that will be used + * for the added mesh. * @param drawables The @ref DrawableGroup with which the new @ref * gfx::Drawable will be rendered. * @param objectID The object type identifier or semantic group (e.g. @@ -640,66 +718,12 @@ class ResourceManager { */ void addMeshToDrawables(const MeshMetaData& metaData, scene::SceneNode& node, + const Magnum::ResourceKey& lightSetup, DrawableGroup* drawables, int objectID, int meshIDLocal, int materialIDLocal); - /** - * @brief Enumeration of supported shader program options. - */ - enum ShaderType { - /** - * Shader program for instance mesh data. See @ref gfx::PrimitiveIDShader, - * @ref GenericInstanceMeshData, @ref Mp3dInstanceMeshData, @ref - * AssetType::INSTANCE_MESH, @ref loadInstanceMeshData. - */ - INSTANCE_MESH_SHADER = 0, - - /** - * Shader program for PTex mesh data. See @ref gfx::PTexMeshShader, @ref - * gfx::PTexMeshDrawable, @ref loadPTexMeshData, @ref PTexMeshData. - */ - PTEX_MESH_SHADER = 1, - - /** - * Shader program for flat shading with uniform color. Used to render object - * identifier or semantic types (e.g. chair, table, etc...). Also the - * default shader for assets with unidentified rendering parameters. See - * @ref Magnum::Shaders::Flat3D. - */ - COLORED_SHADER = 2, - - /** - * Shader program for vertex color shading. Used to render meshes with - * per-vertex colors defined. - */ - VERTEX_COLORED_SHADER = 3, - - /** - * Shader program for meshes with textured defined. - */ - TEXTURED_SHADER = 4, - }; - - /** - * @brief Maps @ref ShaderType to specific instances of @ref - * Magnum::GL::AbstractShaderProgram. - * - * See @ref getShaderProgram. - */ - std::map> - shaderPrograms_; - - /** - * @brief Returns a pointer to the specified shader program. - * - * Creates a new shader program for @ref ShaderType if it does not exist. - * @param type The @ref ShaderType of the desired shader program. - * @return A pointer to the specified shader program. - */ - Magnum::GL::AbstractShaderProgram* getShaderProgram(ShaderType type); - /** * @brief Create a @ref gfx::Drawable for the specified mesh, node, * and @ref ShaderType. @@ -710,6 +734,10 @@ class ResourceManager { * @param mesh The render mesh. * @param node The @ref scene::SceneNode to which the drawable will be * attached. + * @param lightSetup The @ref LightSetup key that will be used + * for the drawable. + * @param material The @ref MaterialData key that will be used + * for the drawable. * @param meshID Optional, the index of this mesh component stored in meshes_ * @param group Optional @ref DrawableGroup with which the render the @ref * gfx::Drawable. @@ -719,13 +747,12 @@ class ResourceManager { * @param color Optional color parameter for the shader program. Defaults to * white. */ - void createDrawable(const ShaderType shaderType, - Magnum::GL::Mesh& mesh, - scene::SceneNode& node, - DrawableGroup* group = nullptr, - Magnum::GL::Texture2D* texture = nullptr, - int objectId = ID_UNDEFINED, - const Magnum::Color4& color = Magnum::Color4{1}); + void createGenericDrawable(Magnum::GL::Mesh& mesh, + scene::SceneNode& node, + const Magnum::ResourceKey& lightSetup, + const Magnum::ResourceKey& material, + DrawableGroup* group = nullptr, + int objectId = ID_UNDEFINED); /** * @brief Flag to denote the desire to compress textures. TODO: unused? diff --git a/src/esp/gfx/CMakeLists.txt b/src/esp/gfx/CMakeLists.txt index 321e1a574b..fdf99e41ac 100644 --- a/src/esp/gfx/CMakeLists.txt +++ b/src/esp/gfx/CMakeLists.txt @@ -7,6 +7,9 @@ set(gfx_SOURCES DrawableGroup.h GenericDrawable.cpp GenericDrawable.h + LightSetup.cpp + LightSetup.h + MaterialData.h magnum.h PrimitiveIDDrawable.cpp PrimitiveIDDrawable.h @@ -20,6 +23,7 @@ set(gfx_SOURCES WindowlessContext.h RenderTarget.cpp RenderTarget.h + ShaderManager.h ) # If ptex support is enabled add relevant source files diff --git a/src/esp/gfx/Drawable.cpp b/src/esp/gfx/Drawable.cpp index d7e4eaeb07..516b1bbac8 100644 --- a/src/esp/gfx/Drawable.cpp +++ b/src/esp/gfx/Drawable.cpp @@ -12,13 +12,9 @@ namespace esp { namespace gfx { Drawable::Drawable(scene::SceneNode& node, - Magnum::GL::AbstractShaderProgram& shader, Magnum::GL::Mesh& mesh, DrawableGroup* group /* = nullptr */) - : Magnum::SceneGraph::Drawable3D{node, group}, - node_(node), - shader_(shader), - mesh_(mesh) {} + : Magnum::SceneGraph::Drawable3D{node, group}, node_(node), mesh_(mesh) {} DrawableGroup* Drawable::drawables() { CORRADE_ASSERT( diff --git a/src/esp/gfx/Drawable.h b/src/esp/gfx/Drawable.h index 8f42b8ad8f..c338ac6288 100644 --- a/src/esp/gfx/Drawable.h +++ b/src/esp/gfx/Drawable.h @@ -30,7 +30,6 @@ class Drawable : public Magnum::SceneGraph::Drawable3D { * @param group Drawable group this drawable will be added to. */ Drawable(scene::SceneNode& node, - Magnum::GL::AbstractShaderProgram& shader, // TODO: remove this Magnum::GL::Mesh& mesh, DrawableGroup* group = nullptr); virtual ~Drawable() {} @@ -45,6 +44,8 @@ class Drawable : public Magnum::SceneGraph::Drawable3D { */ DrawableGroup* drawables(); + virtual void setLightSetup(const Magnum::ResourceKey& lightSetup){}; + protected: /** * @brief Draw the object using given camera @@ -59,7 +60,6 @@ class Drawable : public Magnum::SceneGraph::Drawable3D { Magnum::SceneGraph::Camera3D& camera) = 0; scene::SceneNode& node_; - Magnum::GL::AbstractShaderProgram& shader_; Magnum::GL::Mesh& mesh_; }; diff --git a/src/esp/gfx/GenericDrawable.cpp b/src/esp/gfx/GenericDrawable.cpp index 127ec97701..215e248411 100644 --- a/src/esp/gfx/GenericDrawable.cpp +++ b/src/esp/gfx/GenericDrawable.cpp @@ -4,43 +4,106 @@ #include "GenericDrawable.h" -#include +#include #include "esp/scene/SceneNode.h" namespace esp { namespace gfx { -GenericDrawable::GenericDrawable( - scene::SceneNode& node, - Magnum::Shaders::Flat3D& shader, - Magnum::GL::Mesh& mesh, - DrawableGroup* group /* = nullptr */, - Magnum::GL::Texture2D* texture /* = nullptr */, - int objectId /* = ID_UNDEFINED */, - const Magnum::Color4& color /* = Magnum::Color4{1} */) - : Drawable{node, shader, mesh, group}, - texture_(texture), - objectId_(objectId), - color_{color} {} +GenericDrawable::GenericDrawable(scene::SceneNode& node, + Magnum::GL::Mesh& mesh, + ShaderManager& shaderManager, + const Magnum::ResourceKey& lightSetup, + const Magnum::ResourceKey& materialData, + DrawableGroup* group /* = nullptr */, + int objectId /* = ID_UNDEFINED */) + : Drawable{node, mesh, group}, + shaderManager_{shaderManager}, + lightSetup_{shaderManager.get(lightSetup)}, + materialData_{ + shaderManager.get(materialData)}, + objectId_(objectId) { + // update the shader early here to to avoid doing it during the render loop + updateShader(); +} + +void GenericDrawable::setLightSetup(const Magnum::ResourceKey& resourceKey) { + lightSetup_ = shaderManager_.get(resourceKey); + + // update the shader early here to to avoid doing it during the render loop + updateShader(); +} void GenericDrawable::draw(const Magnum::Matrix4& transformationMatrix, Magnum::SceneGraph::Camera3D& camera) { - Magnum::Shaders::Flat3D& shader = - static_cast(shader_); - shader.setTransformationProjectionMatrix(camera.projectionMatrix() * - transformationMatrix); + updateShader(); + + (*shader_) + .setAmbientColor(materialData_->ambientColor) + .setDiffuseColor(materialData_->diffuseColor) + .setSpecularColor(materialData_->specularColor) + .setShininess(materialData_->shininess) + .setObjectId(node_.getId()) + .setTransformationMatrix(transformationMatrix) + .setProjectionMatrix(camera.projectionMatrix()) + .setNormalMatrix(transformationMatrix.rotationScaling()); + + if (materialData_->ambientTexture) + shader_->bindAmbientTexture(*(materialData_->ambientTexture)); + if (materialData_->diffuseTexture) + shader_->bindDiffuseTexture(*(materialData_->diffuseTexture)); + if (materialData_->specularTexture) + shader_->bindSpecularTexture(*(materialData_->specularTexture)); + + const Magnum::Matrix4 cameraMatrix = camera.cameraMatrix(); + for (Magnum::UnsignedInt i = 0; i < lightSetup_->size(); ++i) { + shader_->setLightPosition( + i, getLightPositionRelativeToCamera( + (*lightSetup_)[i], transformationMatrix, cameraMatrix)); - if ((shader.flags() & Magnum::Shaders::Flat3D::Flag::Textured) && texture_) { - shader.bindTexture(*texture_); + shader_->setLightColor(i, (*lightSetup_)[i].color); } - if (!(shader.flags() & Magnum::Shaders::Flat3D::Flag::VertexColor)) { - shader.setColor(color_); + mesh_.draw(*shader_); +} + +void GenericDrawable::updateShader() { + Magnum::UnsignedInt lightCount = lightSetup_->size(); + Magnum::Shaders::Phong::Flags flags = Magnum::Shaders::Phong::Flag::ObjectId; + + if (materialData_->ambientTexture) + flags |= Magnum::Shaders::Phong::Flag::AmbientTexture; + if (materialData_->diffuseTexture) + flags |= Magnum::Shaders::Phong::Flag::DiffuseTexture; + if (materialData_->specularTexture) + flags |= Magnum::Shaders::Phong::Flag::SpecularTexture; + + if (!shader_ || shader_->lightCount() != lightCount || + shader_->flags() != flags) { + // if the number of lights or flags have changed, we need to fetch a + // compatible shader + shader_ = + shaderManager_ + .get( + getShaderKey(lightCount, flags)); + + // if no shader with desired number of lights and flags exists, create one + if (!shader_) { + shaderManager_.set( + shader_.key(), new Magnum::Shaders::Phong{flags, lightCount}, + Magnum::ResourceDataState::Final, + Magnum::ResourcePolicy::ReferenceCounted); + } } +} - shader.setObjectId(node_.getId()); - mesh_.draw(shader_); +Magnum::ResourceKey GenericDrawable::getShaderKey( + Magnum::UnsignedInt lightCount, + Magnum::Shaders::Phong::Flags flags) const { + return Corrade::Utility::formatString( + SHADER_KEY_TEMPLATE, lightCount, + static_cast(flags)); } } // namespace gfx diff --git a/src/esp/gfx/GenericDrawable.h b/src/esp/gfx/GenericDrawable.h index ba0643d62b..046154cd54 100644 --- a/src/esp/gfx/GenericDrawable.h +++ b/src/esp/gfx/GenericDrawable.h @@ -4,9 +4,10 @@ #pragma once -#include +#include -#include "Drawable.h" +#include "esp/gfx/Drawable.h" +#include "esp/gfx/ShaderManager.h" namespace esp { namespace gfx { @@ -17,20 +18,36 @@ class GenericDrawable : public Drawable { //! Adds drawable to given group and uses provided texture, objectId, and //! color for textured, object id buffer and color shader output respectively explicit GenericDrawable(scene::SceneNode& node, - Magnum::Shaders::Flat3D& shader, Magnum::GL::Mesh& mesh, + ShaderManager& shaderManager, + const Magnum::ResourceKey& lightSetup, + const Magnum::ResourceKey& materialData, DrawableGroup* group = nullptr, - Magnum::GL::Texture2D* texture = nullptr, - int objectId = ID_UNDEFINED, - const Magnum::Color4& color = Magnum::Color4{1}); + int objectId = ID_UNDEFINED); + + void setLightSetup(const Magnum::ResourceKey& lightSetup) override; + + static constexpr const char* SHADER_KEY_TEMPLATE = "Phong-lights={}-flags={}"; protected: virtual void draw(const Magnum::Matrix4& transformationMatrix, Magnum::SceneGraph::Camera3D& camera) override; + void updateShader(); + + Magnum::ResourceKey getShaderKey(Magnum::UnsignedInt lightCount, + Magnum::Shaders::Phong::Flags flags) const; + Magnum::GL::Texture2D* texture_; int objectId_; Magnum::Color4 color_; + + // shader parameters + ShaderManager& shaderManager_; + Magnum::Resource + shader_; + Magnum::Resource materialData_; + Magnum::Resource lightSetup_; }; } // namespace gfx diff --git a/src/esp/gfx/LightSetup.cpp b/src/esp/gfx/LightSetup.cpp new file mode 100644 index 0000000000..b114b4c8f4 --- /dev/null +++ b/src/esp/gfx/LightSetup.cpp @@ -0,0 +1,42 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#include "LightSetup.h" + +namespace esp { +namespace gfx { + +Magnum::Vector3 getLightPositionRelativeToCamera( + const LightInfo& light, + const Magnum::Matrix4& transformationMatrix, + const Magnum::Matrix4& cameraMatrix) { + if (light.model == LightPositionModel::OBJECT) + return transformationMatrix.transformPoint(light.position); + + if (light.model == LightPositionModel::GLOBAL) + return cameraMatrix.transformPoint(light.position); + + // LightPositionModel::CAMERA + return light.position; +} + +LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph) { + const Magnum::Range3D& sceneBB = + sceneGraph.getRootNode().computeCumulativeBB(); + + // NOLINTNEXTLINE(google-build-using-namespace) + using namespace Magnum::Math::Literals; + + return LightSetup{{sceneBB.frontTopLeft(), 0xffffff_rgbf * 0.5f}, + {sceneBB.frontTopRight(), 0xffffff_rgbf * 0.5f}, + {sceneBB.frontBottomLeft(), 0xffffff_rgbf * 0.5f}, + {sceneBB.frontBottomRight(), 0xffffff_rgbf * 0.5f}, + {sceneBB.backTopLeft(), 0xffffff_rgbf * 0.5f}, + {sceneBB.backTopRight(), 0xffffff_rgbf * 0.5f}, + {sceneBB.backBottomLeft(), 0xffffff_rgbf * 0.5f}, + {sceneBB.backBottomRight(), 0xffffff_rgbf * 0.5f}}; +} + +} // namespace gfx +} // namespace esp diff --git a/src/esp/gfx/LightSetup.h b/src/esp/gfx/LightSetup.h new file mode 100644 index 0000000000..fd88603cc0 --- /dev/null +++ b/src/esp/gfx/LightSetup.h @@ -0,0 +1,54 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include +#include + +#include "esp/scene/SceneGraph.h" + +namespace esp { +namespace gfx { + +enum class LightPositionModel { + /** @brief Light position is relative to the camera */ + CAMERA = 0, + /** @brief Light position is relative to scene */ + GLOBAL = 1, + /** @brief Light position is relative to the object being rendered */ + OBJECT = 2, +}; + +/** @brief Contains a single light's information */ +struct LightInfo { + Magnum::Vector3 position; + Magnum::Color4 color; + LightPositionModel model = LightPositionModel::GLOBAL; +}; + +using LightSetup = std::vector; + +/** + * @brief Get position relative to a camera for a @ref LightInfo and a + * rendered object + * + * @param transformationMatrix Describes object position relative to camera + * @param cameraMatrix Describes world position relative to camera + * @return Magnum::Vector3 Light position relative to camera + */ +Magnum::Vector3 getLightPositionRelativeToCamera( + const LightInfo& light, + const Magnum::Matrix4& transformationMatrix, + const Magnum::Matrix4& cameraMatrix); + +/** + * @brief Get a @ref LightSetup with lights at the corners of a scene + */ +LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph); + +} // namespace gfx +} // namespace esp diff --git a/src/esp/gfx/MaterialData.h b/src/esp/gfx/MaterialData.h new file mode 100644 index 0000000000..4627c7e64f --- /dev/null +++ b/src/esp/gfx/MaterialData.h @@ -0,0 +1,30 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include + +#include "esp/core/esp.h" + +namespace esp { +namespace gfx { + +struct MaterialData {}; + +struct PhongMaterialData : public MaterialData { + Magnum::Float shininess = 80.f; + Magnum::Color4 ambientColor = Magnum::Color4{1}, + diffuseColor = Magnum::Color4{1}, + specularColor = Magnum::Color4{1}; + Magnum::GL::Texture2D *ambientTexture = nullptr, *diffuseTexture = nullptr, + *specularTexture = nullptr; + + ESP_SMART_POINTERS(PhongMaterialData) +}; + +} // namespace gfx +} // namespace esp diff --git a/src/esp/gfx/PTexMeshDrawable.cpp b/src/esp/gfx/PTexMeshDrawable.cpp index f78f05c094..f2589c9de8 100644 --- a/src/esp/gfx/PTexMeshDrawable.cpp +++ b/src/esp/gfx/PTexMeshDrawable.cpp @@ -5,17 +5,20 @@ #include "PTexMeshDrawable.h" #include "esp/assets/PTexMeshData.h" +#include "esp/gfx/PTexMeshShader.h" namespace esp { namespace gfx { +// static constexpr arrays require redundant definitions until C++17 +constexpr char PTexMeshDrawable::SHADER_KEY[]; + PTexMeshDrawable::PTexMeshDrawable(scene::SceneNode& node, - PTexMeshShader& shader, assets::PTexMeshData& ptexMeshData, int submeshID, + ShaderManager& shaderManager, DrawableGroup* group /* = nullptr */) - : Drawable{node, shader, ptexMeshData.getRenderingBuffer(submeshID)->mesh, - group}, + : Drawable{node, ptexMeshData.getRenderingBuffer(submeshID)->mesh, group}, atlasTexture_(ptexMeshData.getRenderingBuffer(submeshID)->atlasTexture), #ifndef CORRADE_TARGET_APPLE adjFacesBufferTexture_( @@ -25,12 +28,21 @@ PTexMeshDrawable::PTexMeshDrawable(scene::SceneNode& node, exposure_(ptexMeshData.exposure()), gamma_(ptexMeshData.gamma()), saturation_(ptexMeshData.saturation()) { + auto shaderResource = + shaderManager.get( + SHADER_KEY); + + if (!shaderResource) { + shaderManager.set(shaderResource.key(), + new PTexMeshShader{}); + } + shader_ = &(*shaderResource); } void PTexMeshDrawable::draw(const Magnum::Matrix4& transformationMatrix, Magnum::SceneGraph::Camera3D& camera) { - PTexMeshShader& ptexMeshShader = static_cast(shader_); - ptexMeshShader.setExposure(exposure_) + (*shader_) + .setExposure(exposure_) .setGamma(gamma_) .setSaturation(saturation_) .setAtlasTextureSize(atlasTexture_, tileSize_) @@ -39,7 +51,7 @@ void PTexMeshDrawable::draw(const Magnum::Matrix4& transformationMatrix, .bindAdjFacesBufferTexture(adjFacesBufferTexture_) #endif .setMVPMatrix(camera.projectionMatrix() * transformationMatrix); - mesh_.draw(ptexMeshShader); + mesh_.draw(*shader_); } } // namespace gfx diff --git a/src/esp/gfx/PTexMeshDrawable.h b/src/esp/gfx/PTexMeshDrawable.h index 46c9ff1aa2..ecab7518da 100644 --- a/src/esp/gfx/PTexMeshDrawable.h +++ b/src/esp/gfx/PTexMeshDrawable.h @@ -5,7 +5,7 @@ #pragma once #include "Drawable.h" -#include "PTexMeshShader.h" +#include "esp/gfx/ShaderManager.h" namespace esp { namespace assets { @@ -18,11 +18,13 @@ class PTexMeshShader; class PTexMeshDrawable : public Drawable { public: explicit PTexMeshDrawable(scene::SceneNode& node, - PTexMeshShader& shader, assets::PTexMeshData& ptexMeshData, int submeshID, + ShaderManager& shaderManager, DrawableGroup* group = nullptr); + static constexpr char SHADER_KEY[] = "PTexMeshShader"; + protected: virtual void draw(const Magnum::Matrix4& transformationMatrix, Magnum::SceneGraph::Camera3D& camera) override; @@ -35,6 +37,7 @@ class PTexMeshDrawable : public Drawable { float exposure_; float gamma_; float saturation_; + PTexMeshShader* shader_ = nullptr; }; } // namespace gfx diff --git a/src/esp/gfx/PrimitiveIDDrawable.cpp b/src/esp/gfx/PrimitiveIDDrawable.cpp index a5a6a24b8b..a80988549c 100644 --- a/src/esp/gfx/PrimitiveIDDrawable.cpp +++ b/src/esp/gfx/PrimitiveIDDrawable.cpp @@ -9,19 +9,31 @@ namespace esp { namespace gfx { +// static constexpr arrays require redundant definitions until C++17 +constexpr char PrimitiveIDDrawable::SHADER_KEY[]; + PrimitiveIDDrawable::PrimitiveIDDrawable(scene::SceneNode& node, - PrimitiveIDShader& shader, Magnum::GL::Mesh& mesh, + ShaderManager& shaderManager, DrawableGroup* group /* = nullptr */) - : Drawable{node, shader, mesh, group} {} + : Drawable{node, mesh, group} { + auto shaderResource = + shaderManager.get( + SHADER_KEY); + + if (!shaderResource) { + shaderManager.set( + shaderResource.key(), new PrimitiveIDShader{}); + } + shader_ = &(*shaderResource); +} void PrimitiveIDDrawable::draw(const Magnum::Matrix4& transformationMatrix, Magnum::SceneGraph::Camera3D& camera) { - PrimitiveIDShader& shader = static_cast(shader_); - shader.setTransformationProjectionMatrix(camera.projectionMatrix() * - transformationMatrix); + shader_->setTransformationProjectionMatrix(camera.projectionMatrix() * + transformationMatrix); - mesh_.draw(shader_); + mesh_.draw(*shader_); } } // namespace gfx diff --git a/src/esp/gfx/PrimitiveIDDrawable.h b/src/esp/gfx/PrimitiveIDDrawable.h index 1f12c9114a..3be1bb3a1c 100644 --- a/src/esp/gfx/PrimitiveIDDrawable.h +++ b/src/esp/gfx/PrimitiveIDDrawable.h @@ -5,6 +5,7 @@ #pragma once #include "Drawable.h" +#include "esp/gfx/ShaderManager.h" namespace esp { namespace gfx { @@ -18,13 +19,17 @@ class PrimitiveIDDrawable : public Drawable { //! objectId, and color for textured, object id buffer and color shader //! output respectively explicit PrimitiveIDDrawable(scene::SceneNode& node, - PrimitiveIDShader& shader, Magnum::GL::Mesh& mesh, + ShaderManager& shaderManager, DrawableGroup* group = nullptr); + static constexpr char SHADER_KEY[] = "PrimitiveIDShader"; + protected: virtual void draw(const Magnum::Matrix4& transformationMatrix, Magnum::SceneGraph::Camera3D& camera) override; + + PrimitiveIDShader* shader_ = nullptr; }; } // namespace gfx diff --git a/src/esp/gfx/ShaderManager.h b/src/esp/gfx/ShaderManager.h new file mode 100644 index 0000000000..9132131fef --- /dev/null +++ b/src/esp/gfx/ShaderManager.h @@ -0,0 +1,21 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include + +#include "esp/gfx/LightSetup.h" +#include "esp/gfx/MaterialData.h" + +namespace esp { +namespace gfx { + +using ShaderManager = Magnum::ResourceManager; + +} // namespace gfx +} // namespace esp diff --git a/src/esp/sim/Simulator.cpp b/src/esp/sim/Simulator.cpp index 48c41b0703..6d53d0c4d4 100644 --- a/src/esp/sim/Simulator.cpp +++ b/src/esp/sim/Simulator.cpp @@ -108,6 +108,10 @@ void Simulator::reconfigure(const SimulatorConfiguration& cfg) { throw std::invalid_argument("Cannot load: " + sceneFilename); } + gfx::LightSetup sceneCorners = gfx::getLightsAtSceneCorners(sceneGraph); + resourceManager_.setLightSetup( + assets::ResourceManager::DEFAULT_LIGHTING_KEY, std::move(sceneCorners)); + if (io::exists(houseFilename)) { LOG(INFO) << "Loading house from " << houseFilename; // if semantic mesh exists, load it as well diff --git a/src/utils/viewer/viewer.cpp b/src/utils/viewer/viewer.cpp index 993d144ae2..62cd458694 100644 --- a/src/utils/viewer/viewer.cpp +++ b/src/utils/viewer/viewer.cpp @@ -192,6 +192,9 @@ Viewer::Viewer(const Arguments& arguments) } } + resourceManager_.setLightSetup(assets::ResourceManager::DEFAULT_LIGHTING_KEY, + gfx::getLightsAtSceneCorners(*sceneGraph_)); + // Set up camera renderCamera_ = &sceneGraph_->getDefaultRenderCamera(); agentBodyNode_ = &rootNode_->createChild(); From e2be1adb5048561abe2926a95288360ce6f25024 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Tue, 11 Feb 2020 20:09:02 -0800 Subject: [PATCH 2/9] fix test failure by turning BUILD_DEPRECATED off --- setup.py | 1 + src/esp/assets/ResourceManager.cpp | 1 + src/esp/geo/geo.cpp | 3 +++ src/esp/gfx/LightSetup.cpp | 18 +++++++++--------- src/esp/gfx/LightSetup.h | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index 15c762dbed..b80ba38c93 100644 --- a/setup.py +++ b/setup.py @@ -217,6 +217,7 @@ def build_extension(self, ext): "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + extdir, "-DPYTHON_EXECUTABLE=" + sys.executable, "-DCMAKE_EXPORT_COMPILE_COMMANDS={}".format("OFF" if is_pip() else "ON"), + "-DBUILD_DEPRECATED=OFF" ] cmake_args += shlex.split(args.cmake_args) diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index a713f5eafd..50793df5ff 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/src/esp/geo/geo.cpp b/src/esp/geo/geo.cpp index efb0c058b1..6fc60a81af 100644 --- a/src/esp/geo/geo.cpp +++ b/src/esp/geo/geo.cpp @@ -2,6 +2,9 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. +#include +#include + #include "esp/geo/geo.h" #include diff --git a/src/esp/gfx/LightSetup.cpp b/src/esp/gfx/LightSetup.cpp index b114b4c8f4..882b728bd8 100644 --- a/src/esp/gfx/LightSetup.cpp +++ b/src/esp/gfx/LightSetup.cpp @@ -21,21 +21,21 @@ Magnum::Vector3 getLightPositionRelativeToCamera( return light.position; } -LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph) { +LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, Magnum::Float lightIntensity) { const Magnum::Range3D& sceneBB = sceneGraph.getRootNode().computeCumulativeBB(); // NOLINTNEXTLINE(google-build-using-namespace) using namespace Magnum::Math::Literals; - return LightSetup{{sceneBB.frontTopLeft(), 0xffffff_rgbf * 0.5f}, - {sceneBB.frontTopRight(), 0xffffff_rgbf * 0.5f}, - {sceneBB.frontBottomLeft(), 0xffffff_rgbf * 0.5f}, - {sceneBB.frontBottomRight(), 0xffffff_rgbf * 0.5f}, - {sceneBB.backTopLeft(), 0xffffff_rgbf * 0.5f}, - {sceneBB.backTopRight(), 0xffffff_rgbf * 0.5f}, - {sceneBB.backBottomLeft(), 0xffffff_rgbf * 0.5f}, - {sceneBB.backBottomRight(), 0xffffff_rgbf * 0.5f}}; + return LightSetup{{sceneBB.frontTopLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.frontTopRight(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.frontBottomLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.frontBottomRight(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backTopLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backTopRight(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backBottomLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backBottomRight(), 0xffffff_rgbf * lightIntensity}}; } } // namespace gfx diff --git a/src/esp/gfx/LightSetup.h b/src/esp/gfx/LightSetup.h index fd88603cc0..4d6a6fca18 100644 --- a/src/esp/gfx/LightSetup.h +++ b/src/esp/gfx/LightSetup.h @@ -48,7 +48,7 @@ Magnum::Vector3 getLightPositionRelativeToCamera( /** * @brief Get a @ref LightSetup with lights at the corners of a scene */ -LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph); +LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, Magnum::Float lightIntensity = 0.4f); } // namespace gfx } // namespace esp From de531503289aadaa9fbe37b900b26642c0d46551 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Tue, 11 Feb 2020 20:11:17 -0800 Subject: [PATCH 3/9] format error --- setup.py | 2 +- src/esp/gfx/LightSetup.cpp | 20 +++++++++++--------- src/esp/gfx/LightSetup.h | 3 ++- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/setup.py b/setup.py index b80ba38c93..21d34b6229 100644 --- a/setup.py +++ b/setup.py @@ -217,7 +217,7 @@ def build_extension(self, ext): "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + extdir, "-DPYTHON_EXECUTABLE=" + sys.executable, "-DCMAKE_EXPORT_COMPILE_COMMANDS={}".format("OFF" if is_pip() else "ON"), - "-DBUILD_DEPRECATED=OFF" + "-DBUILD_DEPRECATED=OFF", ] cmake_args += shlex.split(args.cmake_args) diff --git a/src/esp/gfx/LightSetup.cpp b/src/esp/gfx/LightSetup.cpp index 882b728bd8..467cf57b1d 100644 --- a/src/esp/gfx/LightSetup.cpp +++ b/src/esp/gfx/LightSetup.cpp @@ -21,21 +21,23 @@ Magnum::Vector3 getLightPositionRelativeToCamera( return light.position; } -LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, Magnum::Float lightIntensity) { +LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, + Magnum::Float lightIntensity) { const Magnum::Range3D& sceneBB = sceneGraph.getRootNode().computeCumulativeBB(); // NOLINTNEXTLINE(google-build-using-namespace) using namespace Magnum::Math::Literals; - return LightSetup{{sceneBB.frontTopLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.frontTopRight(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.frontBottomLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.frontBottomRight(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backTopLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backTopRight(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backBottomLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backBottomRight(), 0xffffff_rgbf * lightIntensity}}; + return LightSetup{ + {sceneBB.frontTopLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.frontTopRight(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.frontBottomLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.frontBottomRight(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backTopLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backTopRight(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backBottomLeft(), 0xffffff_rgbf * lightIntensity}, + {sceneBB.backBottomRight(), 0xffffff_rgbf * lightIntensity}}; } } // namespace gfx diff --git a/src/esp/gfx/LightSetup.h b/src/esp/gfx/LightSetup.h index 4d6a6fca18..c1b3bdc908 100644 --- a/src/esp/gfx/LightSetup.h +++ b/src/esp/gfx/LightSetup.h @@ -48,7 +48,8 @@ Magnum::Vector3 getLightPositionRelativeToCamera( /** * @brief Get a @ref LightSetup with lights at the corners of a scene */ -LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, Magnum::Float lightIntensity = 0.4f); +LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, + Magnum::Float lightIntensity = 0.4f); } // namespace gfx } // namespace esp From c9a8d5b38cfa562f1915f8d6d86187990f011f6c Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Tue, 11 Feb 2020 20:15:45 -0800 Subject: [PATCH 4/9] more lint errors --- src/esp/assets/ResourceManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index 50793df5ff..01970b1a7f 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -5,13 +5,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include #include From d4b5e720ccd5e15183406d97933be66e948399f3 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Wed, 12 Feb 2020 17:59:02 -0800 Subject: [PATCH 5/9] address comments --- setup.py | 1 - src/esp/assets/GltfMeshData.cpp | 8 +++++-- src/esp/assets/GltfMeshData.h | 5 +++- src/esp/assets/MeshMetaData.h | 15 +++++------- src/esp/assets/ResourceManager.cpp | 34 ++++++++++++++++---------- src/esp/assets/ResourceManager.h | 9 ++++--- src/esp/geo/geo.cpp | 3 --- src/esp/gfx/GenericDrawable.cpp | 25 +++++++++++++------- src/esp/gfx/LightSetup.cpp | 38 +++++++++++++----------------- src/esp/gfx/LightSetup.h | 7 +++--- src/esp/sim/Simulator.cpp | 6 ++--- src/utils/viewer/viewer.cpp | 3 ++- tests/test_sensors.py | 3 +++ 13 files changed, 86 insertions(+), 71 deletions(-) diff --git a/setup.py b/setup.py index 21d34b6229..15c762dbed 100644 --- a/setup.py +++ b/setup.py @@ -217,7 +217,6 @@ def build_extension(self, ext): "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + extdir, "-DPYTHON_EXECUTABLE=" + sys.executable, "-DCMAKE_EXPORT_COMPILE_COMMANDS={}".format("OFF" if is_pip() else "ON"), - "-DBUILD_DEPRECATED=OFF", ] cmake_args += shlex.split(args.cmake_args) diff --git a/src/esp/assets/GltfMeshData.cpp b/src/esp/assets/GltfMeshData.cpp index e4966f0cb1..ea7615ed25 100644 --- a/src/esp/assets/GltfMeshData.cpp +++ b/src/esp/assets/GltfMeshData.cpp @@ -18,9 +18,13 @@ void GltfMeshData::uploadBuffersToGPU(bool forceReload) { renderingBuffer_.reset(); renderingBuffer_ = std::make_unique(); + Magnum::MeshTools::CompileFlags compileFlags{}; + if (needsNormals_ && !meshData_->hasNormals()) { + compileFlags |= Magnum::MeshTools::CompileFlag::GenerateSmoothNormals; + } // position, normals, uv, colors are bound to corresponding attributes - renderingBuffer_->mesh = Magnum::MeshTools::compile( - *meshData_, Magnum::MeshTools::CompileFlag::GenerateSmoothNormals); + renderingBuffer_->mesh = Magnum::MeshTools::compile(*meshData_, compileFlags); + buffersOnGPU_ = true; } diff --git a/src/esp/assets/GltfMeshData.h b/src/esp/assets/GltfMeshData.h index aa88ab05f7..f2d15d0c99 100644 --- a/src/esp/assets/GltfMeshData.h +++ b/src/esp/assets/GltfMeshData.h @@ -38,7 +38,8 @@ class GltfMeshData : public BaseMesh { /** @brief Constructor. Sets @ref SupportedMeshType::GLTF_MESH to identify the * asset type.*/ - GltfMeshData() : BaseMesh(SupportedMeshType::GLTF_MESH){}; + GltfMeshData(bool needsNormals = true) + : BaseMesh(SupportedMeshType::GLTF_MESH), needsNormals_{needsNormals} {}; /** @brief Destructor */ virtual ~GltfMeshData(){}; @@ -82,6 +83,8 @@ class GltfMeshData : public BaseMesh { * does NOT have copy constructor. See @ref uploadBuffersToGPU. */ std::unique_ptr renderingBuffer_ = nullptr; + + bool needsNormals_ = true; }; } // namespace assets } // namespace esp diff --git a/src/esp/assets/MeshMetaData.h b/src/esp/assets/MeshMetaData.h index 5fca86df9e..f018be8ad6 100644 --- a/src/esp/assets/MeshMetaData.h +++ b/src/esp/assets/MeshMetaData.h @@ -84,6 +84,9 @@ struct MeshMetaData { * stores the relationship between components of the asset.*/ MeshTransformNode root; + /** @brief If this asset was loaded as a scene */ + bool isSceneAsset = false; + /** @brief Default constructor. */ MeshMetaData(){}; @@ -93,20 +96,14 @@ struct MeshMetaData { int textureStart = ID_UNDEFINED, int textureEnd = ID_UNDEFINED, int materialStart = ID_UNDEFINED, - int materialEnd = ID_UNDEFINED) { + int materialEnd = ID_UNDEFINED, + bool isScene = false) + : isSceneAsset{isScene} { meshIndex = std::make_pair(meshStart, meshEnd); textureIndex = std::make_pair(textureStart, textureEnd); materialIndex = std::make_pair(materialStart, materialEnd); } - /** @brief Copy constructor. */ - MeshMetaData(const MeshMetaData& val) { - meshIndex = val.meshIndex; - textureIndex = val.textureIndex; - materialIndex = val.materialIndex; - root = MeshTransformNode(val.root); - } - /** * @brief Sets the mesh indices for the asset See @ref * ResourceManager::meshes_. diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index 01970b1a7f..dca14c8c1d 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -102,7 +102,6 @@ bool ResourceManager::loadScene(const AssetInfo& info, } else if (info.type == AssetType::SUNCG_SCENE) { meshSuccess = loadSUNCGHouseFile(info, parent, drawables); } else if (info.type == AssetType::MP3D_MESH) { - // for now, force scenes to be flat shaded meshSuccess = loadGeneralMeshData(info, parent, drawables, true); } else { // Unknown type, just load general mesh data @@ -974,13 +973,14 @@ bool ResourceManager::loadGeneralMeshData( const AssetInfo& info, scene::SceneNode* parent /* = nullptr */, DrawableGroup* drawables /* = nullptr */, - bool forceFlatShading /* = false */) { + bool isScene /* = false */) { const std::string& filename = info.filepath; const bool fileIsLoaded = resourceDict_.count(filename) > 0; const bool drawData = parent != nullptr && drawables != nullptr; // Mesh & metaData container MeshMetaData metaData; + metaData.isSceneAsset = isScene; #ifndef MAGNUM_BUILD_STATIC Magnum::PluginManager::Manager manager; @@ -1079,7 +1079,7 @@ bool ResourceManager::loadGeneralMeshData( } // if this is a new file, load it and add it to the dictionary loadTextures(*importer, &metaData); - loadMaterials(*importer, &metaData, forceFlatShading); + loadMaterials(*importer, &metaData); loadMeshes(*importer, &metaData); resourceDict_.emplace(filename, metaData); @@ -1110,7 +1110,16 @@ bool ResourceManager::loadGeneralMeshData( resourceDict_[filename].root.transformFromLocalToParent = R * resourceDict_[filename].root.transformFromLocalToParent; } else { - metaData = resourceDict_[filename]; + const MeshMetaData& savedMetaData = resourceDict_[filename]; + if (savedMetaData.isSceneAsset != metaData.isSceneAsset) { + // TODO: Right now, we use flat shading for scenes, and phong shading + // for other objects. We need to add this information to our + // resourceDict key so that we can load the same asset with different + // shading + LOG(WARNING) << "Loading asset " << filename + << " as both an object and scene is not " + "yet supported, may be shaded wrong!"; + } } // Optional Instantiation @@ -1138,16 +1147,15 @@ bool ResourceManager::loadGeneralMeshData( } // forceReload // TODO: make this configurable - Mn::ResourceKey lightSetup{forceFlatShading ? NO_LIGHT_KEY - : DEFAULT_LIGHTING_KEY}; + Mn::ResourceKey lightSetup{metaData.isSceneAsset ? NO_LIGHT_KEY + : DEFAULT_LIGHTING_KEY}; addComponent(metaData, newNode, lightSetup, drawables, metaData.root); return true; } } void ResourceManager::loadMaterials(Importer& importer, - MeshMetaData* metaData, - bool forceFlatShading) { + MeshMetaData* metaData) { int materialStart = nextMaterialID_; int materialEnd = materialStart + importer.materialCount() - 1; metaData->setMaterialIndices(materialStart, materialEnd); @@ -1169,7 +1177,7 @@ void ResourceManager::loadMaterials(Importer& importer, const auto& phongMaterialData = static_cast(*materialData); std::unique_ptr finalMaterial; - if (forceFlatShading) { + if (metaData->isSceneAsset) { finalMaterial = getFlatShadedMaterialData(phongMaterialData, metaData->textureIndex.first); } else { @@ -1254,15 +1262,15 @@ void ResourceManager::loadMeshes(Importer& importer, MeshMetaData* metaData) { metaData->setMeshIndices(meshStart, meshEnd); for (int iMesh = 0; iMesh < importer.mesh3DCount(); ++iMesh) { - meshes_.emplace_back(std::make_unique()); - auto& currentMesh = meshes_.back(); - auto* gltfMeshData = static_cast(currentMesh.get()); + // don't need normals if we just flat shade the scene + auto gltfMeshData = std::make_unique(!metaData->isSceneAsset); gltfMeshData->setMeshData(importer, iMesh); // compute the mesh bounding box - gltfMeshData->BB = computeMeshBB(gltfMeshData); + gltfMeshData->BB = computeMeshBB(gltfMeshData.get()); gltfMeshData->uploadBuffersToGPU(false); + meshes_.emplace_back(std::move(gltfMeshData)); } } diff --git a/src/esp/assets/ResourceManager.h b/src/esp/assets/ResourceManager.h index 878868214d..dd75ac4970 100644 --- a/src/esp/assets/ResourceManager.h +++ b/src/esp/assets/ResourceManager.h @@ -447,11 +447,8 @@ class ResourceManager { * * @param importer The importer already loaded with information for the asset. * @param metaData The asset's @ref MeshMetaData object. - * @param forceFlatShading Only bind ambient textures and colors. */ - void loadMaterials(Importer& importer, - MeshMetaData* metaData, - bool forceFlatShading = false); + void loadMaterials(Importer& importer, MeshMetaData* metaData); /** * @brief Get a @ref PhongMaterialData for use with flat shading @@ -516,11 +513,13 @@ class ResourceManager { * a child. * @param drawables The @ref DrawableGroup with which the mesh will be * rendered. + * @param isScene Whether this asset is being loaded as a scene. If it is then + * it will be flat shaded for performance reasons */ bool loadGeneralMeshData(const AssetInfo& info, scene::SceneNode* parent = nullptr, DrawableGroup* drawables = nullptr, - bool forceFlatShading = false); + bool isScene = false); /** * @brief Load a SUNCG mesh into assets from a file. !Deprecated! TODO: diff --git a/src/esp/geo/geo.cpp b/src/esp/geo/geo.cpp index 6fc60a81af..efb0c058b1 100644 --- a/src/esp/geo/geo.cpp +++ b/src/esp/geo/geo.cpp @@ -2,9 +2,6 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. -#include -#include - #include "esp/geo/geo.h" #include diff --git a/src/esp/gfx/GenericDrawable.cpp b/src/esp/gfx/GenericDrawable.cpp index 215e248411..8372b21042 100644 --- a/src/esp/gfx/GenericDrawable.cpp +++ b/src/esp/gfx/GenericDrawable.cpp @@ -39,12 +39,28 @@ void GenericDrawable::draw(const Magnum::Matrix4& transformationMatrix, Magnum::SceneGraph::Camera3D& camera) { updateShader(); + const Magnum::Matrix4 cameraMatrix = camera.cameraMatrix(); + + std::vector lightPositions; + lightPositions.reserve(lightSetup_->size()); + std::vector lightColors; + lightColors.reserve(lightSetup_->size()); + + for (Magnum::UnsignedInt i = 0; i < lightSetup_->size(); ++i) { + lightPositions.emplace_back(getLightPositionRelativeToCamera( + (*lightSetup_)[i], transformationMatrix, cameraMatrix)); + + lightColors.emplace_back((*lightSetup_)[i].color); + } + (*shader_) .setAmbientColor(materialData_->ambientColor) .setDiffuseColor(materialData_->diffuseColor) .setSpecularColor(materialData_->specularColor) .setShininess(materialData_->shininess) .setObjectId(node_.getId()) + .setLightPositions(lightPositions) + .setLightColors(lightColors) .setTransformationMatrix(transformationMatrix) .setProjectionMatrix(camera.projectionMatrix()) .setNormalMatrix(transformationMatrix.rotationScaling()); @@ -56,15 +72,6 @@ void GenericDrawable::draw(const Magnum::Matrix4& transformationMatrix, if (materialData_->specularTexture) shader_->bindSpecularTexture(*(materialData_->specularTexture)); - const Magnum::Matrix4 cameraMatrix = camera.cameraMatrix(); - for (Magnum::UnsignedInt i = 0; i < lightSetup_->size(); ++i) { - shader_->setLightPosition( - i, getLightPositionRelativeToCamera( - (*lightSetup_)[i], transformationMatrix, cameraMatrix)); - - shader_->setLightColor(i, (*lightSetup_)[i].color); - } - mesh_.draw(*shader_); } diff --git a/src/esp/gfx/LightSetup.cpp b/src/esp/gfx/LightSetup.cpp index 467cf57b1d..282f78c938 100644 --- a/src/esp/gfx/LightSetup.cpp +++ b/src/esp/gfx/LightSetup.cpp @@ -11,33 +11,29 @@ Magnum::Vector3 getLightPositionRelativeToCamera( const LightInfo& light, const Magnum::Matrix4& transformationMatrix, const Magnum::Matrix4& cameraMatrix) { - if (light.model == LightPositionModel::OBJECT) - return transformationMatrix.transformPoint(light.position); - - if (light.model == LightPositionModel::GLOBAL) - return cameraMatrix.transformPoint(light.position); - - // LightPositionModel::CAMERA - return light.position; + switch (light.model) { + case LightPositionModel::OBJECT: + return transformationMatrix.transformPoint(light.position); + case LightPositionModel::GLOBAL: + return cameraMatrix.transformPoint(light.position); + case LightPositionModel::CAMERA: + return light.position; + } + + CORRADE_ASSERT_UNREACHABLE(); + return {}; } -LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, - Magnum::Float lightIntensity) { - const Magnum::Range3D& sceneBB = - sceneGraph.getRootNode().computeCumulativeBB(); - +LightSetup getLightsAtBoxCorners(const Magnum::Range3D& box, + const Magnum::Color4& lightColor) { // NOLINTNEXTLINE(google-build-using-namespace) using namespace Magnum::Math::Literals; return LightSetup{ - {sceneBB.frontTopLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.frontTopRight(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.frontBottomLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.frontBottomRight(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backTopLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backTopRight(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backBottomLeft(), 0xffffff_rgbf * lightIntensity}, - {sceneBB.backBottomRight(), 0xffffff_rgbf * lightIntensity}}; + {box.frontTopLeft(), lightColor}, {box.frontTopRight(), lightColor}, + {box.frontBottomLeft(), lightColor}, {box.frontBottomRight(), lightColor}, + {box.backTopLeft(), lightColor}, {box.backTopRight(), lightColor}, + {box.backBottomLeft(), lightColor}, {box.backBottomRight(), lightColor}}; } } // namespace gfx diff --git a/src/esp/gfx/LightSetup.h b/src/esp/gfx/LightSetup.h index c1b3bdc908..aeab725c9f 100644 --- a/src/esp/gfx/LightSetup.h +++ b/src/esp/gfx/LightSetup.h @@ -46,10 +46,11 @@ Magnum::Vector3 getLightPositionRelativeToCamera( const Magnum::Matrix4& cameraMatrix); /** - * @brief Get a @ref LightSetup with lights at the corners of a scene + * @brief Get a @ref LightSetup with lights at the corners of a box */ -LightSetup getLightsAtSceneCorners(scene::SceneGraph& sceneGraph, - Magnum::Float lightIntensity = 0.4f); +LightSetup getLightsAtBoxCorners( + const Magnum::Range3D& box, + const Magnum::Color4& lightColor = Magnum::Color4{0.4f}); } // namespace gfx } // namespace esp diff --git a/src/esp/sim/Simulator.cpp b/src/esp/sim/Simulator.cpp index 6d53d0c4d4..d25c5e863f 100644 --- a/src/esp/sim/Simulator.cpp +++ b/src/esp/sim/Simulator.cpp @@ -107,10 +107,10 @@ void Simulator::reconfigure(const SimulatorConfiguration& cfg) { // Pass the error to the python through pybind11 allowing graceful exit throw std::invalid_argument("Cannot load: " + sceneFilename); } - - gfx::LightSetup sceneCorners = gfx::getLightsAtSceneCorners(sceneGraph); + const Magnum::Range3D& sceneBB = rootNode.computeCumulativeBB(); resourceManager_.setLightSetup( - assets::ResourceManager::DEFAULT_LIGHTING_KEY, std::move(sceneCorners)); + assets::ResourceManager::DEFAULT_LIGHTING_KEY, + gfx::getLightsAtBoxCorners(sceneBB)); if (io::exists(houseFilename)) { LOG(INFO) << "Loading house from " << houseFilename; diff --git a/src/utils/viewer/viewer.cpp b/src/utils/viewer/viewer.cpp index 62cd458694..b55069b831 100644 --- a/src/utils/viewer/viewer.cpp +++ b/src/utils/viewer/viewer.cpp @@ -192,8 +192,9 @@ Viewer::Viewer(const Arguments& arguments) } } + const Magnum::Range3D& sceneBB = rootNode_->computeCumulativeBB(); resourceManager_.setLightSetup(assets::ResourceManager::DEFAULT_LIGHTING_KEY, - gfx::getLightsAtSceneCorners(*sceneGraph_)); + gfx::getLightsAtBoxCorners(sceneBB)); // Set up camera renderCamera_ = &sceneGraph_->getDefaultRenderCamera(); diff --git a/tests/test_sensors.py b/tests/test_sensors.py index 14647ee560..17461594d9 100644 --- a/tests/test_sensors.py +++ b/tests/test_sensors.py @@ -129,6 +129,9 @@ def test_sensors(scene, has_sem, sensor_type, gpu2gpu, sim, make_cfg_settings): # Tests to make sure that no sensors is supported and doesn't crash # Also tests to make sure we can have multiple instances # of the simulator with no sensors +@pytest.mark.skip( + reason="Multiple simulators not supported until ResourceManager singleton deprecation" +) def test_smoke_no_sensors(make_cfg_settings): sims = [] for scene in _test_scenes: From 1e1d660abf271f98dbd7e7c0791d63248b4abfb0 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Wed, 12 Feb 2020 19:52:01 -0800 Subject: [PATCH 6/9] fix test failure by closing sim --- src/esp/assets/ResourceManager.cpp | 9 ++++----- tests/test_simulator.py | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index dca14c8c1d..5fe3eec7e9 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -1110,15 +1110,14 @@ bool ResourceManager::loadGeneralMeshData( resourceDict_[filename].root.transformFromLocalToParent = R * resourceDict_[filename].root.transformFromLocalToParent; } else { - const MeshMetaData& savedMetaData = resourceDict_[filename]; - if (savedMetaData.isSceneAsset != metaData.isSceneAsset) { + if (resourceDict_[filename].isSceneAsset != isScene) { // TODO: Right now, we use flat shading for scenes, and phong shading // for other objects. We need to add this information to our // resourceDict key so that we can load the same asset with different // shading - LOG(WARNING) << "Loading asset " << filename - << " as both an object and scene is not " - "yet supported, may be shaded wrong!"; + LOG(ERROR) << "Loading asset " << filename + << " as both an object and scene is not " + "yet supported, will be shaded wrong!"; } } diff --git a/tests/test_simulator.py b/tests/test_simulator.py index ca6bf2d22c..f0b6cb6288 100644 --- a/tests/test_simulator.py +++ b/tests/test_simulator.py @@ -29,6 +29,8 @@ def test_no_navmesh_smoke(): # Can't collide with no navmesh assert not obs["collided"] + sim.close() + def test_empty_scene(sim): cfg_settings = examples.settings.default_sim_settings.copy() From a094aacb1ec3bba19e809c5020a68ca922afca04 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Wed, 12 Feb 2020 20:25:27 -0800 Subject: [PATCH 7/9] try another test fix --- tests/test_simulator.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_simulator.py b/tests/test_simulator.py index f0b6cb6288..c9355bf674 100644 --- a/tests/test_simulator.py +++ b/tests/test_simulator.py @@ -8,7 +8,7 @@ import habitat_sim -def test_no_navmesh_smoke(): +def test_no_navmesh_smoke(sim): sim_cfg = habitat_sim.SimulatorConfiguration() agent_config = habitat_sim.AgentConfiguration() # No sensors as we are only testing to see if things work @@ -19,7 +19,7 @@ def test_no_navmesh_smoke(): # Make it try to load a navmesh that doesn't exists sim_cfg.scene.filepaths["navmesh"] = "/tmp/dne.navmesh" - sim = habitat_sim.Simulator(habitat_sim.Configuration(sim_cfg, [agent_config])) + sim.reconfigure(habitat_sim.Configuration(sim_cfg, [agent_config])) sim.initialize_agent(0) @@ -29,8 +29,6 @@ def test_no_navmesh_smoke(): # Can't collide with no navmesh assert not obs["collided"] - sim.close() - def test_empty_scene(sim): cfg_settings = examples.settings.default_sim_settings.copy() From dcb61c28da10f578dc8946f5a601e2cba8f8e801 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Thu, 13 Feb 2020 16:51:31 -0800 Subject: [PATCH 8/9] change default specularity to no highlights --- src/esp/assets/ResourceManager.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index 5fe3eec7e9..f70a639faf 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -1223,8 +1223,7 @@ gfx::PhongMaterialData::uptr ResourceManager::getPhongShadedMaterialData( using namespace Mn::Math::Literals; auto finalMaterial = gfx::PhongMaterialData::create_unique(); - // TODO: figure out why materials are being loaded with shininess == 1 - finalMaterial->shininess = std::max(material.shininess(), 80.f); + finalMaterial->shininess = material.shininess(); // ambient material properties if (material.flags() & Mn::Trade::PhongMaterialData::Flag::AmbientTexture) { @@ -1250,7 +1249,11 @@ gfx::PhongMaterialData::uptr ResourceManager::getPhongShadedMaterialData( textures_[textureBaseIndex + material.specularTexture()].get(); finalMaterial->specularColor = 0xffffffff_rgbaf; } else { - finalMaterial->specularColor = material.specularColor(); + // remove specular highlights if shininess value doesn't make sense + // TODO: figure out why materials are being loaded with shininess == 1 + finalMaterial->specularColor = finalMaterial->shininess == 1 + ? 0x000000_rgbf + : material.specularColor(); } return finalMaterial; } From 7b2e66806b95ff4229f6b6ee5e9ed2d69d654163 Mon Sep 17 00:00:00 2001 From: matthewjmay Date: Tue, 18 Feb 2020 10:34:42 -0800 Subject: [PATCH 9/9] don't skip multiple sim test --- tests/test_sensors.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_sensors.py b/tests/test_sensors.py index 48ab55ba49..1f8bd5f951 100644 --- a/tests/test_sensors.py +++ b/tests/test_sensors.py @@ -131,9 +131,6 @@ def test_sensors(scene, has_sem, sensor_type, gpu2gpu, sim, make_cfg_settings): # Tests to make sure that no sensors is supported and doesn't crash # Also tests to make sure we can have multiple instances # of the simulator with no sensors -@pytest.mark.skip( - reason="Multiple simulators not supported until ResourceManager singleton deprecation" -) def test_smoke_no_sensors(make_cfg_settings): sims = [] for scene in _test_scenes: