diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0d9a403923..9a2d9e3dc5 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1140,147 +1140,6 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { return AABox(); } -void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shapeID, const MeshPartPayload* payload) { -// PROFILE_RANGE(__FUNCTION__); - PerformanceTimer perfTimer("Model::renderPart"); - if (!_readyWhenAdded) { - return; // bail asap - } - - auto textureCache = DependencyManager::get(); - - gpu::Batch& batch = *(args->_batch); - auto mode = args->_renderMode; - - auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME - - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const std::vector>& networkMeshes = _geometry->getMeshes(); - - auto networkMaterial = _geometry->getShapeMaterial(shapeID); - if (!networkMaterial) { - return; - }; - auto material = networkMaterial->_material; - if (!material) { - return; - } - - // TODO: Not yet - // auto drawMesh = _geometry->getShapeMesh(shapeID); - // auto drawPart = _geometry->getShapePart(shapeID); - - // guard against partially loaded meshes - if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)_meshStates.size() ) { - return; - } - - updateClusterMatrices(); - - const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get()); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); - const MeshState& state = _meshStates.at(meshIndex); - - // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown - // to false to rebuild out mesh groups. - if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) { - _meshGroupsKnown = false; // regenerate these lists next time around. - _readyWhenAdded = false; // in case any of our users are using scenes - invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid - return; // FIXME! - } - - - int vertexCount = mesh.vertices.size(); - if (vertexCount == 0) { - // sanity check - return; // FIXME! - } - - auto drawMaterialKey = material->getKey(); - bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); - - bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); - bool hasSpecular = drawMaterialKey.isGlossMap(); // !drawMaterial->specularTextureName.isEmpty(); //mesh.hasSpecularTexture(); - bool hasLightmap = drawMaterialKey.isLightmapMap(); // !drawMaterial->emissiveTextureName.isEmpty(); //mesh.hasEmissiveTexture(); - bool isSkinned = state.clusterMatrices.size() > 1; - bool wireframe = isWireframe(); - - // render the part bounding box - #ifdef DEBUG_BOUNDING_PARTS - { - AABox partBounds = getPartBounds(meshIndex, partIndex); - bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE; - - glm::vec4 cubeColor; - if (isSkinned) { - cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f); - } else if (inView) { - cubeColor = glm::vec4(1.0f, 0.0f, 1.0f, 1.0f); - } else { - cubeColor = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f); - } - - Transform transform; - transform.setTranslation(partBounds.calcCenter()); - transform.setScale(partBounds.getDimensions()); - batch.setModelTransform(transform); - DependencyManager::get()->renderWireCube(batch, 1.0f, cubeColor); - } - #endif //def DEBUG_BOUNDING_PARTS - - if (wireframe) { - translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; - } - - ModelRender::Locations* locations = nullptr; - ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, - args, locations); - - - payload->bindTransform(batch, locations); - - payload->bindMesh(batch); - - // guard against partially loaded meshes - if (partIndex >= mesh.parts.size()) { - return; - } - - - #ifdef WANT_DEBUG - if (material == nullptr) { - qCDebug(renderutils) << "WARNING: material == nullptr!!!"; - } - #endif - - { - // apply material properties - payload->bindMaterial(batch, locations); - - - // TODO: We should be able to do that just in the renderTransparentJob - if (translucentMesh && locations->lightBufferUnit >= 0) { - PerformanceTimer perfTimer("DLE->setupTransparent()"); - - DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); - } - if (args) { - args->_details._materialSwitches++; - } - } - - { - PerformanceTimer perfTimer("batch.drawIndexed()"); - payload->drawCall(batch); - } - - if (args) { - const int INDICES_PER_TRIANGLE = 3; - args->_details._trianglesRendered += payload->_drawPart._numIndices / INDICES_PER_TRIANGLE; - } -} - void Model::segregateMeshGroups() { const FBXGeometry& geometry = _geometry->getFBXGeometry(); const std::vector>& networkMeshes = _geometry->getMeshes(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 108480e4ef..8937ecb94c 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -89,7 +89,6 @@ public: bool isVisible() const { return _isVisible; } AABox getPartBounds(int meshIndex, int partIndex); - void renderPart(RenderArgs* args, int meshIndex, int partIndex, int shapeID, const MeshPartPayload* payload); bool maybeStartBlender(); diff --git a/libraries/render-utils/src/ModelRenderItem.cpp b/libraries/render-utils/src/ModelRenderItem.cpp index e2118a8f0b..4ddb7fac66 100644 --- a/libraries/render-utils/src/ModelRenderItem.cpp +++ b/libraries/render-utils/src/ModelRenderItem.cpp @@ -11,6 +11,8 @@ #include "ModelRenderItem.h" +#include + #include "DeferredLightingEffect.h" #include "Model.h" @@ -268,7 +270,7 @@ void ModelRender::pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, b bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, Locations*& locations) { - // PerformanceTimer perfTimer("Model::pickPrograms"); + PerformanceTimer perfTimer("ModelRender::pickPrograms"); getRenderPipelineLib(); RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); @@ -383,10 +385,6 @@ render::Item::Bound MeshPartPayload::getBound() const { return _bound; } -void MeshPartPayload::render(RenderArgs* args) const { - return model->renderPart(args, meshIndex, partIndex, _shapeID, this); -} - void MeshPartPayload::drawCall(gpu::Batch& batch) const { batch.drawIndexed(gpu::TRIANGLES, _drawPart._numIndices, _drawPart._startIndex); } @@ -515,3 +513,126 @@ void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locati batch.setModelTransform(transform); } + +void MeshPartPayload::render(RenderArgs* args) const { + PerformanceTimer perfTimer("MeshPartPayload::render"); + if (!model->_readyWhenAdded) { + return; // bail asap + } + + gpu::Batch& batch = *(args->_batch); + auto mode = args->_renderMode; + + auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME + + const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); + const std::vector>& networkMeshes = model->_geometry->getMeshes(); + + // guard against partially loaded meshes + if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)model->_meshStates.size() ) { + return; + } + + // Back to model to update the cluster matrices right now + model->updateClusterMatrices(); + + const FBXMesh& mesh = geometry.meshes.at(meshIndex); + + // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown + // to false to rebuild out mesh groups. + if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) { + model->_meshGroupsKnown = false; // regenerate these lists next time around. + model->_readyWhenAdded = false; // in case any of our users are using scenes + model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid + return; // FIXME! + } + + + int vertexCount = mesh.vertices.size(); + if (vertexCount == 0) { + // sanity check + return; // FIXME! + } + + + // guard against partially loaded meshes + if (partIndex >= mesh.parts.size()) { + return; + } + + model::MaterialKey drawMaterialKey; + if (_drawMaterial) { + drawMaterialKey = _drawMaterial->getKey(); + } + bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); + + bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); + bool hasSpecular = drawMaterialKey.isGlossMap(); + bool hasLightmap = drawMaterialKey.isLightmapMap(); + bool isSkinned = _isSkinned; + bool wireframe = model->isWireframe(); + + // render the part bounding box +#ifdef DEBUG_BOUNDING_PARTS + { + AABox partBounds = getPartBounds(meshIndex, partIndex); + bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE; + + glm::vec4 cubeColor; + if (isSkinned) { + cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f); + } else if (inView) { + cubeColor = glm::vec4(1.0f, 0.0f, 1.0f, 1.0f); + } else { + cubeColor = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f); + } + + Transform transform; + transform.setTranslation(partBounds.calcCenter()); + transform.setScale(partBounds.getDimensions()); + batch.setModelTransform(transform); + DependencyManager::get()->renderWireCube(batch, 1.0f, cubeColor); + } +#endif //def DEBUG_BOUNDING_PARTS + + if (wireframe) { + translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + } + + ModelRender::Locations* locations = nullptr; + ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + args, locations); + + + // Bind the model transform and the skinCLusterMatrices if needed + bindTransform(batch, locations); + + //Bind the index buffer and vertex buffer and Blend shapes if needed + bindMesh(batch); + + // apply material properties + bindMaterial(batch, locations); + + + // TODO: We should be able to do that just in the renderTransparentJob + if (translucentMesh && locations->lightBufferUnit >= 0) { + PerformanceTimer perfTimer("DLE->setupTransparent()"); + + DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); + } + if (args) { + args->_details._materialSwitches++; + } + + // Draw! + { + PerformanceTimer perfTimer("batch.drawIndexed()"); + drawCall(batch); + } + + if (args) { + const int INDICES_PER_TRIANGLE = 3; + args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; + } +} +