From c60a8e7dfcbe610d7d51790dd7d1642964c74885 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 12:52:55 -0700 Subject: [PATCH] minecraft style voxel editing largely works --- examples/voxels.js | 85 ++++--------------- .../src/RenderablePolyVoxEntityItem.cpp | 15 ++-- 2 files changed, 25 insertions(+), 75 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index b198ac3948..cc3453202a 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -5,80 +5,34 @@ function floorVector(v) { return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)}; } -function backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, low, high) { - // try to back up along pickRay an amount that changes only one coordinate. this does - // a binary search for a pickRay multiplier that only causes one of the 3 coordinates to change. - var originalVoxelCoords = floorVector(originalVoxelPosition) - if (high - low < 0.001) { - print("voxel backup-by-1 failed"); - // give up. - return originalVoxelPosition; - } - var middle = (low + high) / 2.0; - - var backupVector = Vec3.multiply(pickRayDirInVoxelSpace, -middle); - print("backupVector = " + "{" + backupVector.x + ", " + backupVector.y + ", " + backupVector.z + "}"); - var nPosition = Vec3.sum(originalVoxelPosition, backupVector); // possible neighbor coordinates - var nCoords = floorVector(nPosition); - - print("middle = " + middle + - " -- {" + originalVoxelCoords.x + ", " + originalVoxelCoords.y + ", " + originalVoxelCoords.z + "}" + - " -- {" + nCoords.x + ", " + nCoords.y + ", " + nCoords.z + "}"); - - - if (nCoords.x == originalVoxelCoords.x && - nCoords.y == originalVoxelCoords.y && - nCoords.z == originalVoxelCoords.z) { - // still in the original voxel. back up more... - return backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, middle, high); - } - - if (nCoords.x != originalVoxelCoords.x && - nCoords.y == originalVoxelCoords.y && - nCoords.z == originalVoxelCoords.z) { - return nCoords; - } - if (nCoords.x == originalVoxelCoords.x && - nCoords.y != originalVoxelCoords.y && - nCoords.z == originalVoxelCoords.z) { - return nCoords; - } - if (nCoords.x == originalVoxelCoords.x && - nCoords.y == originalVoxelCoords.y && - nCoords.z != originalVoxelCoords.z) { - return nCoords; - } - - // more than one coordinate changed, but no less... - return backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, low, middle); -} - - function attemptVoxelChange(pickRayDir, intersection) { - var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection); - var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir); - print("voxelPosition = " + voxelPosition.x + ", " + voxelPosition.y + ", " + voxelPosition.z); - print("pickRay = " + pickRayDir.x + ", " + pickRayDir.y + ", " + pickRayDir.z); - print("pickRayInVoxelSpace = " + - pickRayDirInVoxelSpace.x + ", " + pickRayDirInVoxelSpace.y + ", " + pickRayDirInVoxelSpace.z); + var properties = Entities.getEntityProperties(intersection.entityID); + if (properties.type != "PolyVox") { + return false; + } + + var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection); + voxelPosition = Vec3.subtract(voxelPosition, {x: 0.5, y: 0.5, z: 0.5}); + var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir); + pickRayDirInVoxelSpace = Vec3.normalize(pickRayDirInVoxelSpace); if (controlHeld) { // hold control to erase a voxel - return Entities.setVoxel(intersection.entityID, floorVector(voxelPosition), 0); + var toErasePosition = Vec3.sum(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); + return Entities.setVoxel(intersection.entityID, floorVector(toErasePosition), 0); } else if (shiftHeld) { // hold shift to set all voxels to 255 return Entities.setAllVoxels(intersection.entityID, 255); } else { // no modifier key to add a voxel - var backOneVoxel = backUpByOneVoxel(pickRayDirInVoxelSpace, voxelPosition, 0.0, 1.0); - return Entities.setVoxel(intersection.entityID, backOneVoxel, 255); + var toDrawPosition = Vec3.subtract(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); + return Entities.setVoxel(intersection.entityID, floorVector(toDrawPosition), 255); } // Entities.setVoxelSphere(id, intersection.intersection, radius, 0) } - function mousePressEvent(event) { if (!event.isLeftButton) { return; @@ -86,22 +40,13 @@ function mousePressEvent(event) { var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking - var properties; if (intersection.intersects) { - properties = Entities.getEntityProperties(intersection.entityID); - print("got accurate pick"); - if (properties.type == "PolyVox") { - if (attemptVoxelChange(pickRay.direction, intersection)) { - return; - } - } else { - print("not a polyvox: " + properties.type); + if (attemptVoxelChange(pickRay.direction, intersection)) { + return; } } - print("trying bounding-box pick"); - // if the PolyVox entity is empty, we can't pick against its "on" voxels. try picking against its // bounding box, instead. intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 4819d46e39..7044eb0b3c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -395,9 +395,6 @@ public: if (sampler.getVoxel() == 0) { return true; // keep raycasting } - // 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); _result = glm::vec4((float)x, (float)y, (float)z, 1.0f); return false; @@ -506,7 +503,9 @@ 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() { + #ifdef WANT_DEBUG auto startTime = usecTimestampNow(); + #endif quint16 voxelXSize = _voxelVolumeSize.x; quint16 voxelYSize = _voxelVolumeSize.y; @@ -559,7 +558,9 @@ void RenderablePolyVoxEntityItem::compressVolumeData() { _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; _needsModelReload = true; + #ifdef WANT_DEBUG qDebug() << "RenderablePolyVoxEntityItem::compressVolumeData" << (usecTimestampNow() - startTime) << getName(); + #endif } @@ -765,7 +766,9 @@ void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { } void RenderablePolyVoxEntityItem::getModel() { + #ifdef WANT_DEBUG auto startTime = usecTimestampNow(); + #endif // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; @@ -822,7 +825,9 @@ void RenderablePolyVoxEntityItem::getModel() { _needsModelReload = false; + #ifdef WANT_DEBUG qDebug() << "RenderablePolyVoxEntityItem::getModel" << (usecTimestampNow() - startTime) << getName(); + #endif } void RenderablePolyVoxEntityItem::render(RenderArgs* args) { @@ -951,9 +956,9 @@ glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldC } glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { - return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 1.0f)); + return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 0.0f)); } glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3 localCoords) { - return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 1.0f)); + return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 0.0f)); }