From b129c2a93342c0c86363ad1c6959406affe81c54 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 09:36:54 -0700 Subject: [PATCH] in edged mode, make sure border voxels are zeroed out. expose some more voxel matrix math to javascript --- .../src/RenderablePolyVoxEntityItem.cpp | 84 +++++++++++++++---- .../src/RenderablePolyVoxEntityItem.h | 7 +- .../entities/src/EntityScriptingInterface.cpp | 40 +++++++++ .../entities/src/EntityScriptingInterface.h | 2 + libraries/entities/src/PolyVoxEntityItem.h | 2 + 5 files changed, 117 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 9f97585fab..108660f386 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #if defined(__GNUC__) && !defined(__clang__) @@ -67,7 +68,7 @@ RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() { } bool inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, - int x, int y, int z) { + int x, int y, int z) { // x, y, z are in user voxel-coords, not adjusted-for-edge voxel-coords. switch (surfaceStyle) { case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: @@ -206,6 +207,11 @@ glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { return scaled; } +glm::mat4 RenderablePolyVoxEntityItem::localToVoxelMatrix() const { + glm::mat4 localToModelMatrix = glm::inverse(voxelToLocalMatrix()); + return localToModelMatrix; +} + glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const { glm::mat4 rotation = glm::mat4_cast(getRotation()); glm::mat4 translation = glm::translate(getPosition()); @@ -252,13 +258,32 @@ bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t return result; } +void RenderablePolyVoxEntityItem::clearEdges() { + // if we are in an edged mode, make sure the outside surfaces are zeroed out. + if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { + for (int z = 0; z < _volData->getDepth(); z++) { + for (int y = 0; y < _volData->getHeight(); y++) { + for (int x = 0; x < _volData->getWidth(); x++) { + if (x == 0 || y == 0 || z == 0 || + x == _volData->getWidth() - 1 || + y == _volData->getHeight() - 1 || + z == _volData->getDepth() - 1) { + _volData->setVoxelAt(x, y, z, 0); + } + } + } + } + } +} bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) { if (_locked) { return false; } bool result = setVoxelInternal(x, y, z, toValue); - compressVolumeData(); + if (result) { + compressVolumeData(); + } return result; } @@ -298,7 +323,9 @@ bool RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { } } } - compressVolumeData(); + if (result) { + compressVolumeData(); + } return result; } @@ -308,7 +335,7 @@ bool RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t t } // same as setVoxel but takes a vector rather than 3 floats. - return setVoxel((int)position.x, (int)position.y, (int)position.z, toValue); + return setVoxel(roundf(position.x), roundf(position.y), roundf(position.z), toValue); } bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { @@ -332,7 +359,9 @@ bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi } } } - compressVolumeData(); + if (result) { + compressVolumeData(); + } return result; } @@ -354,9 +383,10 @@ public: } bool operator()(PolyVox::SimpleVolume::Sampler& sampler) { - int x = sampler.getPosition().getX(); - int y = sampler.getPosition().getY(); - int z = sampler.getPosition().getZ(); + PolyVox::Vector3DInt32 positionIndex = sampler.getPosition(); + int x = positionIndex.getX(); + int y = positionIndex.getY(); + int z = positionIndex.getZ(); if (!inBounds(_vol, x, y, z)) { return true; @@ -365,8 +395,9 @@ public: if (sampler.getVoxel() == 0) { return true; // keep raycasting } - PolyVox::Vector3DInt32 positionIndex = sampler.getPosition(); - _result = glm::vec4(positionIndex.getX(), positionIndex.getY(), positionIndex.getZ(), 1.0f); + // qDebug() << "RaycastFunctor hit" << x << y << z; + // add {0.5, 0.5, 0.5} to result so it's centered on the voxel + _result = glm::vec4((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f, 1.0f); return false; } glm::vec4 _result; @@ -386,7 +417,6 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o return true; } - // the PolyVox ray intersection code requires a near and far point. glm::mat4 wtvMatrix = worldToVoxelMatrix(); glm::vec3 normDirection = glm::normalize(direction); @@ -411,23 +441,29 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o } glm::vec4 result = callback._result; + switch (_voxelSurfaceStyle) { case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: - result -= glm::vec4(1, 1, 1, 0); // compensate for the extra voxel border + result -= glm::vec4(1.0f, 1.0f, 1.0f, 0.0f); // compensate for the extra voxel border break; case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: case PolyVoxEntityItem::SURFACE_CUBIC: break; } - result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); + // result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * result; - distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); + // TODO: use this to find the actual point of intersection rather than using the center of the voxel + // GeometryUtil.h + // bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, + // const glm::vec3& position, const glm::vec2& dimensions, float& distance);; - face = BoxFace::MIN_X_FACE; // XXX + face = BoxFace::MIN_X_FACE; + + distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); return true; } @@ -436,6 +472,8 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o // compress the data in _volData and save the results. The compressed form is used during // saves to disk and for transmission over the wire void RenderablePolyVoxEntityItem::compressVolumeData() { + auto startTime = usecTimestampNow(); + quint16 voxelXSize = _voxelVolumeSize.x; quint16 voxelYSize = _voxelVolumeSize.y; quint16 voxelZSize = _voxelVolumeSize.z; @@ -486,6 +524,8 @@ void RenderablePolyVoxEntityItem::compressVolumeData() { _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; _needsModelReload = true; + + qDebug() << "RenderablePolyVoxEntityItem::compressVolumeData" << (usecTimestampNow() - startTime) << getName(); } @@ -525,6 +565,7 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { } } } + clearEdges(); #ifdef WANT_DEBUG qDebug() << "--------------- voxel decompress ---------------"; @@ -628,7 +669,6 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { offH += 1.0f; } - glm::vec3 p000 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offL, 1.0f)); glm::vec3 p001 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offH, 1.0f)); glm::vec3 p010 = glm::vec3(vtoM * glm::vec4(x + offL, y + offH, z + offL, 1.0f)); @@ -691,6 +731,8 @@ void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { } void RenderablePolyVoxEntityItem::getModel() { + auto startTime = usecTimestampNow(); + // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; @@ -745,6 +787,8 @@ void RenderablePolyVoxEntityItem::getModel() { #endif _needsModelReload = false; + + qDebug() << "RenderablePolyVoxEntityItem::getModel" << (usecTimestampNow() - startTime) << getName(); } void RenderablePolyVoxEntityItem::render(RenderArgs* args) { @@ -871,3 +915,11 @@ glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3 voxelC glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f)); } + +glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { + return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 1.0f)); +} + +glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3 localCoords) { + return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 1.0f)); +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 17c8934577..ffc45beb22 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -71,8 +71,9 @@ public: virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize); glm::vec3 getSurfacePositionAdjustment() const; glm::mat4 voxelToWorldMatrix() const; - glm::mat4 voxelToLocalMatrix() const; glm::mat4 worldToVoxelMatrix() const; + glm::mat4 voxelToLocalMatrix() const; + glm::mat4 localToVoxelMatrix() const; virtual ShapeType getShapeType() const; virtual bool isReadyToComputeShape(); @@ -80,6 +81,8 @@ public: virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords); virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords); + virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords); + virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords); // coords are in voxel-volume space virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue); @@ -110,7 +113,7 @@ private: bool setVoxelInternal(int x, int y, int z, uint8_t toValue); void compressVolumeData(); void decompressVolumeData(); - + void clearEdges(); PolyVox::SimpleVolume* _volData = nullptr; model::Geometry _modelGeometry; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c3e71cef82..41ca6a91ac 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -697,3 +697,43 @@ glm::vec3 EntityScriptingInterface::worldCoordsToVoxelCoords(const QUuid& entity auto polyVoxEntity = std::dynamic_pointer_cast(entity); return polyVoxEntity->worldCoordsToVoxelCoords(worldCoords); } + +glm::vec3 EntityScriptingInterface::voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords) { + if (!_entityTree) { + return glm::vec3(0.0f); + } + + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::voxelCoordsToLocalCoords no entity with ID" << entityID; + return glm::vec3(0.0f); + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::PolyVox) { + return glm::vec3(0.0f); + } + + auto polyVoxEntity = std::dynamic_pointer_cast(entity); + return polyVoxEntity->voxelCoordsToLocalCoords(voxelCoords); +} + +glm::vec3 EntityScriptingInterface::localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords) { + if (!_entityTree) { + return glm::vec3(0.0f); + } + + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::localCoordsToVoxelCoords no entity with ID" << entityID; + return glm::vec3(0.0f); + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::PolyVox) { + return glm::vec3(0.0f); + } + + auto polyVoxEntity = std::dynamic_pointer_cast(entity); + return polyVoxEntity->localCoordsToVoxelCoords(localCoords); +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index e5bff8e80a..a51ebfb61c 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -136,6 +136,8 @@ public slots: Q_INVOKABLE glm::vec3 voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords); Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords); + Q_INVOKABLE glm::vec3 voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords); + Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords); signals: void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 563624a1c7..2ba57f85de 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -79,6 +79,8 @@ class PolyVoxEntityItem : public EntityItem { virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(0.0f); } + virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } + virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords) { return glm::vec3(0.0f); } // coords are in world-space virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; }