mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:24:07 +02:00
make RenderablePolyVoxEntityItem::setSphere affect any voxel the sphere touches rather than just the ones whose center the sphere touches
This commit is contained in:
parent
048da6e6cb
commit
df875ab504
3 changed files with 58 additions and 8 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue