diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index f029088b1a..27a2929d1c 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -354,7 +354,8 @@ var elZoneAtmosphereScatteringWavelengthsZ = document.getElementById("property-zone-atmosphere-scattering-wavelengths-z"); var elZoneAtmosphereHasStars = document.getElementById("property-zone-atmosphere-has-stars"); - var elPolyVoxSelections = document.querySelectorAll(".poly-vox-section"); + var elPolyVoxSections = document.querySelectorAll(".poly-vox-section"); + allSections.push(elPolyVoxSections); var elVoxelVolumeSizeX = document.getElementById("property-voxel-volume-size-x"); var elVoxelVolumeSizeY = document.getElementById("property-voxel-volume-size-y"); var elVoxelVolumeSizeZ = document.getElementById("property-voxel-volume-size-z"); @@ -602,6 +603,10 @@ elParticleLocalGravity.value = properties.localGravity.toFixed(2); elParticleRadius.value = properties.particleRadius.toFixed(3); } else if (properties.type == "PolyVox") { + for (var i = 0; i < elPolyVoxSections.length; i++) { + elPolyVoxSections[i].style.display = 'block'; + } + elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2); elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2); elVoxelVolumeSizeZ.value = properties.voxelVolumeSize.z.toFixed(2); @@ -1014,9 +1019,9 @@
Voxel Volume Size
-
X
-
Y
-
Z
+
X
+
Y
+
Z
Surface Extractor
diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index bb5932d70c..71c3537a0c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -121,7 +121,7 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) _volData->setBorderValue(255); #ifdef WANT_DEBUG - qDebug() << " new size is" << _volData->getWidth() << _volData->getHeight() << _volData->getDepth(); + qDebug() << " new voxel-space size is" << _volData->getWidth() << _volData->getHeight() << _volData->getDepth(); #endif // I'm not sure this is needed... the docs say that each element is initialized with its default @@ -220,12 +220,15 @@ uint8_t RenderablePolyVoxEntityItem::getVoxel(int x, int y, int z) { return _volData->getVoxelAt(x, y, z); } -void RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) { +void RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t toValue) { + // set a voxel without recompressing the voxel data assert(_volData); if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) { return; } + updateOnCount(x, y, z, toValue); + if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) { _volData->setVoxelAt(x + 1, y + 1, z + 1, toValue); } else { @@ -234,6 +237,14 @@ void RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) } +void RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) { + if (_locked) { + return; + } + setVoxelInternal(x, y, z, toValue); + compressVolumeData(); +} + void RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toValue) { // keep _onCount up to date if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) { @@ -255,11 +266,15 @@ void RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toV } void RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { + if (_locked) { + return; + } + for (int z = 0; z < _voxelVolumeSize.z; z++) { for (int y = 0; y < _voxelVolumeSize.y; y++) { for (int x = 0; x < _voxelVolumeSize.x; x++) { updateOnCount(x, y, z, toValue); - setVoxel(x, y, z, toValue); + setVoxelInternal(x, y, z, toValue); } } } @@ -267,11 +282,19 @@ void RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { } void RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t toValue) { - updateOnCount(position.x, position.y, position.z, toValue); - setVoxel(position.x, position.y, position.z, toValue); + if (_locked) { + return; + } + + // same as setVoxel but takes a vector rather than 3 floats. + setVoxel((int)position.x, (int)position.y, (int)position.z, toValue); } void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { + if (_locked) { + return; + } + // This three-level for loop iterates over every voxel in the volume for (int z = 0; z < _voxelVolumeSize.z; z++) { for (int y = 0; y < _voxelVolumeSize.y; y++) { @@ -283,7 +306,7 @@ void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi // If the current voxel is less than 'radius' units from the center then we make it solid. if (fDistToCenter <= radius) { updateOnCount(x, y, z, toValue); - setVoxel(x, y, z, toValue); + setVoxelInternal(x, y, z, toValue); } } } @@ -380,10 +403,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { getModel(); } - Transform transform; - transform.setTranslation(getPosition() - getRegistrationPoint() * getDimensions()); - transform.setRotation(getRotation()); - transform.setScale(getDimensions() / _voxelVolumeSize); + Transform transform(voxelToWorldMatrix()); auto mesh = _modelGeometry.getMesh(); Q_ASSERT(args->_batch); @@ -514,6 +534,11 @@ void RenderablePolyVoxEntityItem::compressVolumeData() { QByteArray newVoxelData; QDataStream writer(&newVoxelData, QIODevice::WriteOnly | QIODevice::Truncate); + + #ifdef WANT_DEBUG + qDebug() << "compressing voxel data of size:" << voxelXSize << voxelYSize << voxelZSize; + #endif + writer << voxelXSize << voxelYSize << voxelZSize; QByteArray compressedData = qCompress(uncompressedData, 9); @@ -573,7 +598,7 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { for (int x = 0; x < voxelXSize; x++) { int uncompressedIndex = (z * voxelYSize * voxelXSize) + (y * voxelZSize) + x; updateOnCount(x, y, z, uncompressedData[uncompressedIndex]); - setVoxel(x, y, z, uncompressedData[uncompressedIndex]); + setVoxelInternal(x, y, z, uncompressedData[uncompressedIndex]); } } } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 77aeb24f2a..814f3deb07 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -73,11 +73,12 @@ public: virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue); SIMPLE_RENDERABLE(); - + private: // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize. + void setVoxelInternal(int x, int y, int z, uint8_t toValue); void compressVolumeData(); void decompressVolumeData(); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f64dad0ef4..d2881e5f3a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -67,12 +67,12 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : _simulatorIDChangedTime(0), _marketplaceID(ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), _name(ENTITY_ITEM_DEFAULT_NAME), + _href(""), + _description(""), _dirtyFlags(0), _element(nullptr), _physicsInfo(nullptr), - _simulated(false), - _href(""), - _description("") + _simulated(false) { quint64 now = usecTimestampNow(); _lastSimulated = now; diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 95ab7d1035..84fbf11311 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -23,7 +23,7 @@ const glm::vec3 PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE = glm::vec3(32, 32, 32); const float PolyVoxEntityItem::MAX_VOXEL_DIMENSION = 32.0f; -const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(qCompress(QByteArray(0), 9)); // XXX +const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(PolyVoxEntityItem::makeEmptyVoxelData()); const PolyVoxEntityItem::PolyVoxSurfaceStyle PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE = PolyVoxEntityItem::SURFACE_MARCHING_CUBES; @@ -31,6 +31,25 @@ EntityItemPointer PolyVoxEntityItem::factory(const EntityItemID& entityID, const return EntityItemPointer(new PolyVoxEntityItem(entityID, properties)); } + + + +QByteArray PolyVoxEntityItem::makeEmptyVoxelData(quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize) { + int rawSize = voxelXSize * voxelYSize * voxelZSize; + + QByteArray uncompressedData = QByteArray(rawSize, '\0'); + QByteArray newVoxelData; + QDataStream writer(&newVoxelData, QIODevice::WriteOnly | QIODevice::Truncate); + writer << voxelXSize << voxelYSize << voxelZSize; + + QByteArray compressedData = qCompress(uncompressedData, 9); + writer << compressedData; + + return newVoxelData; +} + + + PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : EntityItem(entityItemID), _voxelVolumeSize(PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE), diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index bf8214675b..e5d511c087 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -12,14 +12,14 @@ #ifndef hifi_PolyVoxEntityItem_h #define hifi_PolyVoxEntityItem_h -#include "EntityItem.h" +#include "EntityItem.h" class PolyVoxEntityItem : public EntityItem { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); PolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - + ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity @@ -29,22 +29,22 @@ class PolyVoxEntityItem : public EntityItem { // TODO: eventually only include properties changed since the params.lastViewFrustumSent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; - virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, - int& propertyCount, + int& propertyCount, OctreeElement::AppendState& appendState) const; - virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); - + // never have a ray intersection pick a PolyVoxEntityItem. virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return false; } virtual void debugDump() const; @@ -58,12 +58,12 @@ class PolyVoxEntityItem : public EntityItem { enum PolyVoxSurfaceStyle { SURFACE_MARCHING_CUBES, SURFACE_CUBIC, - SURFACE_EDGED_CUBIC + SURFACE_EDGED_CUBIC }; virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) { _voxelSurfaceStyle = voxelSurfaceStyle; } virtual void setVoxelSurfaceStyle(uint16_t voxelSurfaceStyle) { - setVoxelSurfaceStyle((PolyVoxSurfaceStyle) voxelSurfaceStyle); + setVoxelSurfaceStyle((PolyVoxSurfaceStyle) voxelSurfaceStyle); } virtual PolyVoxSurfaceStyle getVoxelSurfaceStyle() const { return _voxelSurfaceStyle; } @@ -82,10 +82,11 @@ class PolyVoxEntityItem : public EntityItem { virtual void setAll(uint8_t toValue) {} virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue) {} - + virtual uint8_t getVoxel(int x, int y, int z) { return 0; } virtual void setVoxel(int x, int y, int z, uint8_t toValue) {} + static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16); protected: glm::vec3 _voxelVolumeSize; // this is always 3 bytes