From 19c8e526e1fb630095f6ff4d0763b20ebacef784 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Mar 2015 08:47:06 -0700 Subject: [PATCH 1/5] add guards to _jointStates array size --- interface/src/avatar/FaceModel.cpp | 2 +- libraries/render-utils/src/Model.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index c80772ef49..6dd97f067a 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -87,7 +87,7 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta void FaceModel::updateJointState(int index) { JointState& state = _jointStates[index]; const FBXJoint& joint = state.getFBXJoint(); - if (joint.parentIndex != -1) { + if (joint.parentIndex != -1 && joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) { const JointState& parentState = _jointStates.at(joint.parentIndex); const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (index == geometry.neckJointIndex) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0e0f081ec8..f7a4257de7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1306,8 +1306,10 @@ void Model::updateJointState(int index) { glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; state.computeTransform(parentTransform); } else { - const JointState& parentState = _jointStates.at(parentIndex); - state.computeTransform(parentState.getTransform(), parentState.getTransformChanged()); + if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) { + const JointState& parentState = _jointStates.at(parentIndex); + state.computeTransform(parentState.getTransform(), parentState.getTransformChanged()); + } } } From fe8ad9517f788bbadb9c13b95d4a9c4983ae2130 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Mar 2015 10:08:08 -0700 Subject: [PATCH 2/5] added debugging for model mesh boxes --- libraries/render-utils/src/Model.cpp | 59 +++++++++++++++++++++++++++- libraries/render-utils/src/Model.h | 3 ++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f7a4257de7..d91c972c45 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -842,10 +842,67 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { args->_translucentMeshPartsRendered = translucentMeshPartsRendered; args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; } - + + #ifdef WANT_DEBUG_MESHBOXES + renderDebugMeshBoxes(); + #endif + return true; } +void Model::renderDebugMeshBoxes() { + int colorNdx = 0; + foreach(AABox box, _calculatedMeshBoxes) { + if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) { + _debugMeshBoxesID = DependencyManager::get()->allocateID(); + } + QVector points; + + glm::vec3 brn = box.getCorner(); + glm::vec3 bln = brn + glm::vec3(box.getDimensions().x, 0, 0); + glm::vec3 brf = brn + glm::vec3(0, 0, box.getDimensions().z); + glm::vec3 blf = brn + glm::vec3(box.getDimensions().x, 0, box.getDimensions().z); + + glm::vec3 trn = brn + glm::vec3(0, box.getDimensions().y, 0); + glm::vec3 tln = bln + glm::vec3(0, box.getDimensions().y, 0); + glm::vec3 trf = brf + glm::vec3(0, box.getDimensions().y, 0); + glm::vec3 tlf = blf + glm::vec3(0, box.getDimensions().y, 0); + + points << brn << bln; + points << brf << blf; + points << brn << brf; + points << bln << blf; + + points << trn << tln; + points << trf << tlf; + points << trn << trf; + points << tln << tlf; + + points << brn << trn; + points << brf << trf; + points << bln << tln; + points << blf << tlf; + + glm::vec4 color[] = { + { 1.0f, 0.0f, 0.0f, 1.0f }, // red + { 0.0f, 1.0f, 0.0f, 1.0f }, // green + { 0.0f, 0.0f, 1.0f, 1.0f }, // blue + { 1.0f, 0.0f, 1.0f, 1.0f }, // purple + { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow + { 0.0f, 1.0f, 1.0f, 1.0f }, // cyan + { 1.0f, 1.0f, 1.0f, 1.0f }, // white + { 0.0f, 0.5f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 0.5f, 1.0f }, + { 0.5f, 0.0f, 0.5f, 1.0f }, + { 0.5f, 0.5f, 0.0f, 1.0f }, + { 0.0f, 0.5f, 0.5f, 1.0f } }; + + DependencyManager::get()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]); + DependencyManager::get()->renderVertices(gpu::LINES, _debugMeshBoxesID); + colorNdx++; + } +} + Extents Model::getBindExtents() const { if (!isActive()) { return Extents(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 5114ef1c9f..e7cb0aa8e5 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -444,6 +444,9 @@ private: QVector _meshesOpaqueLightmapTangentsSpecular; QVector _meshesOpaqueLightmapSpecular; + // debug rendering support + void renderDebugMeshBoxes(); + int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; // Scene rendering support static QVector _modelsInScene; From b705d7633685c7f4ff81af45ffed3364632cb13b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Mar 2015 10:43:21 -0700 Subject: [PATCH 3/5] total hack to ignore frustum culling in case of avatar mesh parts with no transform --- libraries/render-utils/src/Model.cpp | 49 ++++++++++++++++++---------- libraries/render-utils/src/Model.h | 7 ++-- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d91c972c45..0b7fd3dcbf 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -727,19 +727,19 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); int opaqueMeshPartsRendered = 0; - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args, true); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args, true); // render translucent meshes afterwards //DependencyManager::get()->setPrimaryDrawBuffers(false, true, true); @@ -2358,7 +2358,8 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + bool forceRenderSomeMeshes) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; @@ -2378,8 +2379,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl Locations* locations; SkinLocations* skinLocations; - pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); - meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, + args, locations, skinLocations); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, + args, locations, skinLocations, forceRenderSomeMeshes); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2387,7 +2390,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - Locations* locations, SkinLocations* skinLocations) { + Locations* locations, SkinLocations* skinLocations, bool forceRenderSomeMeshes) { PROFILE_RANGE(__FUNCTION__); auto textureCache = DependencyManager::get(); @@ -2423,11 +2426,21 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod // if we got here, then check to see if this mesh is in view if (args) { bool shouldRender = true; + bool forceRender = false; args->_meshesConsidered++; if (args->_viewFrustum) { - shouldRender = args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; - if (shouldRender) { + + // NOTE: This is a hack to address the fact that for avatar meshes, the _calculatedMeshBoxes can be wrong + // for some meshes. Those meshes where the mesh's modelTransform is the identity matrix, and will have + // incorrectly calculated mesh boxes. In this case, we will ignore the box and assume it's visible. + if (forceRenderSomeMeshes && (geometry.meshes.at(i).modelTransform == glm::mat4())) { + forceRender = true; + } + + shouldRender = forceRender || args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; + + if (shouldRender && !forceRender) { float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter()); shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), distance); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index e7cb0aa8e5..05db20b056 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -459,12 +459,15 @@ private: void renderSetup(RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL, + bool forceRenderSomeMeshes = false); + void setupBatchTransform(gpu::Batch& batch); QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, Locations* locations, SkinLocations* skinLocations); + RenderArgs* args, Locations* locations, SkinLocations* skinLocations, + bool forceRenderSomeMeshes = false); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, From 3e8508f1493c654fde86d917facf68af35a70da3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Mar 2015 11:13:35 -0700 Subject: [PATCH 4/5] CR feedback --- libraries/render-utils/src/Model.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0b7fd3dcbf..d640876086 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1363,6 +1363,7 @@ void Model::updateJointState(int index) { glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; state.computeTransform(parentTransform); } else { + // guard against out-of-bounds access to _jointStates if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) { const JointState& parentState = _jointStates.at(parentIndex); state.computeTransform(parentState.getTransform(), parentState.getTransformChanged()); From 9fb53e3d72e8618401a80424f97e5756ecb6500f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Mar 2015 11:13:42 -0700 Subject: [PATCH 5/5] CR feedback --- interface/src/avatar/FaceModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 6dd97f067a..722f998f86 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -87,6 +87,7 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta void FaceModel::updateJointState(int index) { JointState& state = _jointStates[index]; const FBXJoint& joint = state.getFBXJoint(); + // guard against out-of-bounds access to _jointStates if (joint.parentIndex != -1 && joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) { const JointState& parentState = _jointStates.at(joint.parentIndex); const FBXGeometry& geometry = _geometry->getFBXGeometry();