From df875ab5042725f0f60cfb5cd0baa48d7e4bedfd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 22 Mar 2017 16:21:45 -0700 Subject: [PATCH] make RenderablePolyVoxEntityItem::setSphere affect any voxel the sphere touches rather than just the ones whose center the sphere touches --- .../src/RenderablePolyVoxEntityItem.cpp | 39 +++++++++++++++---- libraries/shared/src/AABox.cpp | 26 +++++++++++++ libraries/shared/src/AABox.h | 1 + 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index efe284651a..cd62d72c70 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -414,19 +414,41 @@ bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float r glm::ivec3 lowI = glm::clamp(low, glm::vec3(0.0f), _voxelVolumeSize); glm::ivec3 highI = glm::clamp(high, glm::vec3(0.0f), _voxelVolumeSize); + // This three-level for loop iterates over every voxel in the volume that might be in the sphere + // withWriteLock([&] { + // for (int z = lowI.z; z < highI.z; z++) { + // for (int y = lowI.y; y < highI.y; y++) { + // for (int x = lowI.x; x < highI.x; x++) { + // // Store our current position as a vector... + // glm::vec4 pos(x + 0.5f, y + 0.5f, z + 0.5f, 1.0); // consider voxels cenetered on their coordinates + // // convert to world coordinates + // glm::vec3 worldPos = glm::vec3(vtwMatrix * pos); + // // compute how far the current position is from the center of the volume + // float fDistToCenter = glm::distance(worldPos, centerWorldCoords); + // // If the current voxel is less than 'radius' units from the center then we set its value + // if (fDistToCenter <= radiusWorldCoords) { + // result |= setVoxelInternal(x, y, z, toValue); + // } + // } + // } + // } + // }); + + + glm::vec3 radials(radiusWorldCoords / voxelSize.x, + radiusWorldCoords / voxelSize.y, + radiusWorldCoords / voxelSize.z); + float minRadial = glm::min(radials.x, radials.y); + minRadial = glm::min(minRadial, radials.z); + // This three-level for loop iterates over every voxel in the volume that might be in the sphere withWriteLock([&] { for (int z = lowI.z; z < highI.z; z++) { for (int y = lowI.y; y < highI.y; y++) { for (int x = lowI.x; x < highI.x; x++) { - // Store our current position as a vector... - glm::vec4 pos(x + 0.5f, y + 0.5f, z + 0.5f, 1.0); // consider voxels cenetered on their coordinates - // convert to world coordinates - glm::vec3 worldPos = glm::vec3(vtwMatrix * pos); - // compute how far the current position is from the center of the volume - float fDistToCenter = glm::distance(worldPos, centerWorldCoords); - // If the current voxel is less than 'radius' units from the center then we set its value - if (fDistToCenter <= radiusWorldCoords) { + AABox voxelBox(glm::vec3(x - 0.5f, y - 0.5f, z - 0.5f), glm::vec3(1.0f, 1.0f, 1.0f)); + // if (voxelBox.touchesSphere(centerInVoxelCoords, minRadial)) { + if (voxelBox.touchesAAEllipsoid(centerInVoxelCoords, radials)) { result |= setVoxelInternal(x, y, z, toValue); } } @@ -434,6 +456,7 @@ bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float r } }); + if (result) { compressVolumeDataAndSendEditPacket(); } diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index 89d5ce709d..fa993856dd 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -436,6 +436,32 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& return getClosestPointOnFace(glm::vec3(origin), face); } +bool AABox::touchesAAEllipsoid(const glm::vec3& center, glm::vec3 radials) const { + if (_corner.x - radials.x > center.x || + _corner.y - radials.y > center.y || + _corner.z - radials.z > center.z || + _corner.x + _scale.x + radials.x < center.x || + _corner.y + _scale.y + radials.y < center.y || + _corner.z + _scale.z + radials.z < center.z) { + return false; + } + + for (int i = 0; i < FACE_COUNT; i++) { + glm::vec3 closest = getClosestPointOnFace(center, (BoxFace)i) - center; + float x = closest.x; + float y = closest.y; + float z = closest.z; + float a = radials.x; + float b = radials.y; + float c = radials.z; + if (x*x/(a*a) + y*y/(b*b) + z*z/(c*c) < 1.0f) { + return true; + } + } + return false; +} + + glm::vec4 AABox::getPlane(BoxFace face) const { switch (face) { case MIN_X_FACE: return glm::vec4(-1.0f, 0.0f, 0.0f, _corner.x); diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index ccc7b6e302..022f1a6ff1 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -70,6 +70,7 @@ public: bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal) const; bool touchesSphere(const glm::vec3& center, float radius) const; // fast but may generate false positives + bool touchesAAEllipsoid(const glm::vec3& center, glm::vec3 radials) const; bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const; bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;