mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
voxel-paint paints with capsules rather than spheres
This commit is contained in:
parent
542cb7ab85
commit
88c850afa2
7 changed files with 111 additions and 0 deletions
|
@ -437,6 +437,59 @@ bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float r
|
|||
return result;
|
||||
}
|
||||
|
||||
bool RenderablePolyVoxEntityItem::setCapsule(glm::vec3 startWorldCoords, glm::vec3 endWorldCoords,
|
||||
float radiusWorldCoords, uint8_t toValue) {
|
||||
bool result = false;
|
||||
if (_locked) {
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::mat4 vtwMatrix = voxelToWorldMatrix();
|
||||
glm::mat4 wtvMatrix = glm::inverse(vtwMatrix);
|
||||
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
glm::vec3 voxelSize = dimensions / _voxelVolumeSize;
|
||||
float smallestDimensionSize = voxelSize.x;
|
||||
smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.y);
|
||||
smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.z);
|
||||
|
||||
glm::vec3 maxRadiusInVoxelCoords = glm::vec3(radiusWorldCoords / smallestDimensionSize);
|
||||
|
||||
glm::vec3 startInVoxelCoords = wtvMatrix * glm::vec4(startWorldCoords, 1.0f);
|
||||
glm::vec3 endInVoxelCoords = wtvMatrix * glm::vec4(endWorldCoords, 1.0f);
|
||||
|
||||
glm::vec3 low = glm::min(glm::floor(startInVoxelCoords - maxRadiusInVoxelCoords),
|
||||
glm::floor(endInVoxelCoords - maxRadiusInVoxelCoords));
|
||||
glm::vec3 high = glm::max(glm::ceil(startInVoxelCoords + maxRadiusInVoxelCoords),
|
||||
glm::ceil(endInVoxelCoords + maxRadiusInVoxelCoords));
|
||||
|
||||
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 capsule
|
||||
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);
|
||||
if (pointInCapsule(worldPos, startWorldCoords, endWorldCoords, radiusWorldCoords)) {
|
||||
result |= setVoxelInternal(x, y, z, toValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (result) {
|
||||
compressVolumeDataAndSendEditPacket();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
class RaycastFunctor
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -94,6 +94,8 @@ public:
|
|||
|
||||
// coords are in world-space
|
||||
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) override;
|
||||
virtual bool setCapsule(glm::vec3 startWorldCoords, glm::vec3 endWorldCoords,
|
||||
float radiusWorldCoords, uint8_t toValue) override;
|
||||
virtual bool setAll(uint8_t toValue) override;
|
||||
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override;
|
||||
|
||||
|
|
|
@ -891,6 +891,16 @@ bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& c
|
|||
});
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::setVoxelCapsule(QUuid entityID,
|
||||
const glm::vec3& start, const glm::vec3& end,
|
||||
float radius, int value) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
return setVoxels(entityID, [start, end, radius, value](PolyVoxEntityItem& polyVoxEntity) {
|
||||
return polyVoxEntity.setCapsule(start, end, radius, value);
|
||||
});
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::setVoxel(QUuid entityID, const glm::vec3& position, int value) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
|
@ -1524,3 +1534,11 @@ QObject* EntityScriptingInterface::getWebViewRoot(const QUuid& entityID) {
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO move this someplace that makes more sense...
|
||||
bool EntityScriptingInterface::AABoxIntersectsCapsule(const glm::vec3& low, const glm::vec3& dimensions,
|
||||
const glm::vec3& start, const glm::vec3& end, float radius) {
|
||||
glm::vec3 penetration;
|
||||
AABox aaBox(low, dimensions);
|
||||
return aaBox.findCapsulePenetration(start, end, radius, penetration);
|
||||
}
|
||||
|
|
|
@ -223,6 +223,8 @@ public slots:
|
|||
Q_INVOKABLE bool getDrawZoneBoundaries() const;
|
||||
|
||||
Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value);
|
||||
Q_INVOKABLE bool setVoxelCapsule(QUuid entityID, const glm::vec3& start, const glm::vec3& end, float radius, int value);
|
||||
|
||||
Q_INVOKABLE bool setVoxel(QUuid entityID, const glm::vec3& position, int value);
|
||||
Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value);
|
||||
Q_INVOKABLE bool setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition,
|
||||
|
@ -287,6 +289,10 @@ public slots:
|
|||
|
||||
Q_INVOKABLE QObject* getWebViewRoot(const QUuid& entityID);
|
||||
|
||||
Q_INVOKABLE bool AABoxIntersectsCapsule(const glm::vec3& low, const glm::vec3& dimensions,
|
||||
const glm::vec3& start, const glm::vec3& end, float radius);
|
||||
|
||||
|
||||
signals:
|
||||
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||
|
||||
|
|
|
@ -86,6 +86,8 @@ class PolyVoxEntityItem : public EntityItem {
|
|||
|
||||
// coords are in world-space
|
||||
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; }
|
||||
virtual bool setCapsule(glm::vec3 startWorldCoords, glm::vec3 endWorldCoords,
|
||||
float radiusWorldCoords, uint8_t toValue) { return false; }
|
||||
virtual bool setAll(uint8_t toValue) { return false; }
|
||||
virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int value) { return false; }
|
||||
|
||||
|
|
|
@ -205,6 +205,33 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi
|
|||
return true;
|
||||
}
|
||||
|
||||
bool pointInSphere(const glm::vec3& origin, const glm::vec3& center, float radius) {
|
||||
glm::vec3 relativeOrigin = origin - center;
|
||||
float c = glm::dot(relativeOrigin, relativeOrigin) - radius * radius;
|
||||
return c <= 0.0f;
|
||||
}
|
||||
|
||||
|
||||
bool pointInCapsule(const glm::vec3& origin, const glm::vec3& start, const glm::vec3& end, float radius) {
|
||||
glm::vec3 relativeOrigin = origin - start;
|
||||
glm::vec3 relativeEnd = end - start;
|
||||
float capsuleLength = glm::length(relativeEnd);
|
||||
relativeEnd /= capsuleLength;
|
||||
float originProjection = glm::dot(relativeEnd, relativeOrigin);
|
||||
glm::vec3 constant = relativeOrigin - relativeEnd * originProjection;
|
||||
float c = glm::dot(constant, constant) - radius * radius;
|
||||
if (c < 0.0f) { // starts inside cylinder
|
||||
if (originProjection < 0.0f) { // below start
|
||||
return pointInSphere(origin, start, radius);
|
||||
} else if (originProjection > capsuleLength) { // above end
|
||||
return pointInSphere(origin, end, radius);
|
||||
} else { // between start and end
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& start, const glm::vec3& end, float radius, float& distance) {
|
||||
if (start == end) {
|
||||
|
|
|
@ -73,6 +73,9 @@ glm::vec3 addPenetrations(const glm::vec3& currentPenetration, const glm::vec3&
|
|||
bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& center, float radius, float& distance);
|
||||
|
||||
bool pointInSphere(const glm::vec3& origin, const glm::vec3& center, float radius);
|
||||
bool pointInCapsule(const glm::vec3& origin, const glm::vec3& start, const glm::vec3& end, float radius);
|
||||
|
||||
bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const glm::vec3& start, const glm::vec3& end, float radius, float& distance);
|
||||
|
||||
|
|
Loading…
Reference in a new issue