diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 14cb2e5c55..0d9423218e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -573,6 +573,61 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g return intersectedSomething; } +bool Model::convexHullContains(glm::vec3 point) { + // if we aren't active, we can't compute that yet... + if (!isActive()) { + return false; + } + + // extents is the entity relative, scaled, centered extents of the entity + glm::vec3 position = _translation; + glm::mat4 rotation = glm::mat4_cast(_rotation); + glm::mat4 translation = glm::translate(position); + glm::mat4 modelToWorldMatrix = translation * rotation; + glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); + + Extents modelExtents = getMeshExtents(); // NOTE: unrotated + + glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; + glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference + AABox modelFrameBox(corner, dimensions); + + glm::vec3 modelFramePoint = glm::vec3(worldToModelMatrix * glm::vec4(point, 1.0f)); + + // we can use the AABox's ray intersection by mapping our origin and direction into the model frame + // and testing intersection there. + if (modelFrameBox.contains(modelFramePoint)){ + if (!_calculatedMeshTrianglesValid) { + recalculateMeshBoxes(true); + } + + // If we are inside the models box, then consider the submeshes... + int subMeshIndex = 0; + foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { + if (subMeshBox.contains(point)) { + bool insideMesh = true; + // To be inside the sub mesh, we need to be behind every triangles' planes + const QVector& meshTriangles = _calculatedMeshTriangles[subMeshIndex]; + foreach (const Triangle& triangle, meshTriangles) { + if (!isPointBehindTrianglesPlane(point, triangle.v0, triangle.v1, triangle.v2)) { + // it's not behind at least one so we bail + insideMesh = false; + break; + } + + } + if (insideMesh) { + // It's inside this mesh, return true. + return true; + } + } + subMeshIndex++; + } + } + // It wasn't in any mesh, return false. + return false; +} + // TODO: we seem to call this too often when things haven't actually changed... look into optimizing this void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1559e73e61..10f294dc7c 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -213,6 +213,7 @@ public: bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo, bool pickAgainstTriangles = false); + bool convexHullContains(glm::vec3 point); protected: QSharedPointer _geometry;