From 64d0ce47f3ee23b54fc056a0fed3cc0ac1de5b41 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 30 Aug 2015 09:59:33 -0700 Subject: [PATCH 01/23] attempting to stitch polyvox entites together --- .../display-plugins/OpenGLDisplayPlugin.cpp | 43 +++---- .../stereo/StereoDisplayPlugin.cpp | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 115 +++++++++++++++++- .../src/RenderablePolyVoxEntityItem.h | 8 ++ libraries/entities/src/EntityItemID.h | 18 --- .../entities/src/EntityItemProperties.cpp | 27 +++- libraries/entities/src/EntityItemProperties.h | 6 + .../entities/src/EntityItemPropertiesMacros.h | 8 ++ libraries/entities/src/EntityPropertyFlags.h | 12 +- .../entities/src/ParticleEffectEntityItem.cpp | 10 +- libraries/entities/src/PolyVoxEntityItem.cpp | 24 +++- libraries/entities/src/PolyVoxEntityItem.h | 15 +++ .../src/input-plugins/UserInputMapper.cpp | 4 +- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- .../src/AmbientOcclusionEffect.cpp | 2 +- libraries/shared/src/GLMHelpers.cpp | 18 +-- tests/entities/src/main.cpp | 4 +- tests/gpu-test/src/main.cpp | 4 +- 19 files changed, 249 insertions(+), 76 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index f99d1f2a3b..0ce63e87ac 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -80,32 +80,33 @@ void OpenGLDisplayPlugin::deactivate() { // Pass input events on to the application bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::MouseMove: - case QEvent::Wheel: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::Wheel: - case QEvent::TouchBegin: - case QEvent::TouchEnd: - case QEvent::TouchUpdate: + case QEvent::TouchBegin: + case QEvent::TouchEnd: + case QEvent::TouchUpdate: - case QEvent::FocusIn: - case QEvent::FocusOut: + case QEvent::FocusIn: + case QEvent::FocusOut: - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::ShortcutOverride: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::ShortcutOverride: - case QEvent::DragEnter: - case QEvent::Drop: + case QEvent::DragEnter: + case QEvent::Drop: - case QEvent::Resize: - if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { - return true; - } - default: - break; + case QEvent::Resize: + if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { + return true; + } + break; + default: + break; } return false; diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp index de34451c83..ae3c1f29e2 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp @@ -78,7 +78,7 @@ void StereoDisplayPlugin::activate() { } void StereoDisplayPlugin::updateScreen() { - for (int i = 0; i < (int) _screenActions.size(); ++i) { + for (uint32_t i = 0; i < _screenActions.size(); ++i) { if (_screenActions[i]->isChecked()) { CONTAINER->setFullscreen(qApp->screens().at(i)); break; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 46c4986fa8..5ad23c91be 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -408,14 +408,17 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { } void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) { + _xTexture.clear(); PolyVoxEntityItem::setXTextureURL(xTextureURL); } void RenderablePolyVoxEntityItem::setYTextureURL(QString yTextureURL) { + _yTexture.clear(); PolyVoxEntityItem::setYTextureURL(yTextureURL); } void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { + _zTexture.clear(); PolyVoxEntityItem::setZTextureURL(zTextureURL); } @@ -598,10 +601,27 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) _volData = new PolyVox::SimpleVolume(PolyVox::Region(lowCorner, highCorner)); } else { PolyVox::Vector3DInt32 lowCorner(0, 0, 0); - PolyVox::Vector3DInt32 highCorner(_voxelVolumeSize.x - 1, // -1 because these corners are inclusive - _voxelVolumeSize.y - 1, - _voxelVolumeSize.z - 1); + PolyVox::Vector3DInt32 highCorner(_voxelVolumeSize.x, // -1 because these corners are inclusive + _voxelVolumeSize.y, + _voxelVolumeSize.z); _volData = new PolyVox::SimpleVolume(PolyVox::Region(lowCorner, highCorner)); + + + // // XXX + // { + // for (int x = 0; x <= _voxelVolumeSize.x; x++) { + // for (int y = 0; y <= _voxelVolumeSize.y; y++) { + // for (int z = 0; z <= _voxelVolumeSize.z; z++) { + // if (x == _voxelVolumeSize.x || + // y == _voxelVolumeSize.y || + // z == _voxelVolumeSize.z) { + // setVoxelInternal(x, y, z, 255); + // } + // } + // } + // } + // } + } // having the "outside of voxel-space" value be 255 has helped me notice some problems. @@ -851,9 +871,98 @@ void RenderablePolyVoxEntityItem::getMesh() { } +void RenderablePolyVoxEntityItem::clearOutOfDateNeighbors() { + if (_xNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentXNeighbor = _xNeighbor.lock(); + if (currentXNeighbor && currentXNeighbor->getID() != _xNeighborID) { + _xNeighbor.reset(); + } + } + if (_yNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentYNeighbor = _yNeighbor.lock(); + if (currentYNeighbor && currentYNeighbor->getID() != _yNeighborID) { + _yNeighbor.reset(); + } + } + if (_zNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentZNeighbor = _zNeighbor.lock(); + if (currentZNeighbor && currentZNeighbor->getID() != _zNeighborID) { + _zNeighbor.reset(); + } + } +} + +void RenderablePolyVoxEntityItem::cacheNeighbors() { + if (_voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_CUBIC && + _voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { + return; + } + + clearOutOfDateNeighbors(); + EntityTreeElement* element = getElement(); + EntityTree* tree = element ? element->getTree() : nullptr; + if (!tree) { + return; + } + + if (_xNeighborID != UNKNOWN_ENTITY_ID && _xNeighbor.expired()) { + _xNeighbor = tree->findEntityByID(_xNeighborID); + } + if (_yNeighborID != UNKNOWN_ENTITY_ID && _yNeighbor.expired()) { + _yNeighbor = tree->findEntityByID(_yNeighborID); + } + if (_zNeighborID != UNKNOWN_ENTITY_ID && _zNeighbor.expired()) { + _zNeighbor = tree->findEntityByID(_zNeighborID); + } +} + +void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { + if (_voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_CUBIC && + _voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { + return; + } + + EntityItemPointer currentXNeighbor = _xNeighbor.lock(); + EntityItemPointer currentYNeighbor = _yNeighbor.lock(); + EntityItemPointer currentZNeighbor = _zNeighbor.lock(); + + if (currentXNeighbor) { + auto polyVoxXNeighbor = std::dynamic_pointer_cast(currentXNeighbor); + for (int y = 0; y < _voxelVolumeSize.y; y++) { + for (int z = 0; z < _voxelVolumeSize.z; y++) { + uint8_t neighborValue = polyVoxXNeighbor->getVoxel(0, y, z); + _volData->setVoxelAt(_voxelVolumeSize.x, y, z, neighborValue); + } + } + } + + if (currentYNeighbor) { + auto polyVoxYNeighbor = std::dynamic_pointer_cast(currentYNeighbor); + for (int x = 0; x < _voxelVolumeSize.x; x++) { + for (int z = 0; z < _voxelVolumeSize.z; z++) { + uint8_t neighborValue = polyVoxYNeighbor->getVoxel(x, 0, z); + _volData->setVoxelAt(x, _voxelVolumeSize.y, z, neighborValue); + } + } + } + + if (currentZNeighbor) { + auto polyVoxZNeighbor = std::dynamic_pointer_cast(currentZNeighbor); + for (int x = 0; x < _voxelVolumeSize.x; x++) { + for (int y = 0; y < _voxelVolumeSize.y; y++) { + uint8_t neighborValue = polyVoxZNeighbor->getVoxel(x, y, 0); + _volData->setVoxelAt(x, y, _voxelVolumeSize.z, neighborValue); + } + } + } +} + void RenderablePolyVoxEntityItem::getMeshAsync() { model::MeshPointer mesh(new model::Mesh()); + cacheNeighbors(); + copyUpperEdgesFromNeighbors(); + // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 110e8f8ab4..fa203f5e4d 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -147,6 +147,14 @@ private: void computeShapeInfoWorkerAsync(); QSemaphore _threadRunning{1}; + + // these are cached lookups of _xNeighborID, _yNeighborID, _zNeighborID + EntityItemWeakPointer _xNeighbor; + EntityItemWeakPointer _yNeighbor; + EntityItemWeakPointer _zNeighbor; + void clearOutOfDateNeighbors(); + void cacheNeighbors(); + void copyUpperEdgesFromNeighbors(); }; diff --git a/libraries/entities/src/EntityItemID.h b/libraries/entities/src/EntityItemID.h index 7f55005a17..765082ef0b 100644 --- a/libraries/entities/src/EntityItemID.h +++ b/libraries/entities/src/EntityItemID.h @@ -32,26 +32,8 @@ public: QScriptValue toScriptValue(QScriptEngine* engine) const; bool isInvalidID() const { return *this == UNKNOWN_ENTITY_ID; } - - // QUuid id; }; -// inline bool operator<(const EntityItemID& a, const EntityItemID& b) { -// return a.id < b.id; -// } - -// inline bool operator==(const EntityItemID& a, const EntityItemID& b) { -// return a.id == b.id; -// } - -// inline bool operator!=(const EntityItemID& a, const EntityItemID& b) { -// return !(a == b); -// } - -// inline uint qHash(const EntityItemID& a, uint seed) { -// return qHash(a.id, seed); -// } - inline QDebug operator<<(QDebug debug, const EntityItemID& id) { debug << "[entity-id:" << id.toString() << "]"; return debug; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index c6c02f248c..199defbcb1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -109,6 +109,10 @@ CONSTRUCT_PROPERTY(strokeWidths, QVector()), CONSTRUCT_PROPERTY(xTextureURL, ""), CONSTRUCT_PROPERTY(yTextureURL, ""), CONSTRUCT_PROPERTY(zTextureURL, ""), +CONSTRUCT_PROPERTY(xNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(yNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(zNeighborID, UNKNOWN_ENTITY_ID), + _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -377,6 +381,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_X_TEXTURE_URL, xTextureURL); CHECK_PROPERTY_CHANGE(PROP_Y_TEXTURE_URL, yTextureURL); CHECK_PROPERTY_CHANGE(PROP_Z_TEXTURE_URL, zTextureURL); + CHECK_PROPERTY_CHANGE(PROP_X_NEIGHBOR_ID, xNeighborID); + CHECK_PROPERTY_CHANGE(PROP_Y_NEIGHBOR_ID, yNeighborID); + CHECK_PROPERTY_CHANGE(PROP_Z_NEIGHBOR_ID, zNeighborID); changedProperties += _stage.getChangedProperties(); changedProperties += _atmosphere.getChangedProperties(); @@ -521,6 +528,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(yTextureURL); COPY_PROPERTY_TO_QSCRIPTVALUE(zTextureURL); + COPY_PROPERTY_TO_QSCRIPTVALUE(xNeighborID); + COPY_PROPERTY_TO_QSCRIPTVALUE(yNeighborID); + COPY_PROPERTY_TO_QSCRIPTVALUE(zNeighborID); + return properties; } @@ -620,6 +631,10 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(yTextureURL, QString, setYTextureURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(zTextureURL, QString, setZTextureURL); + COPY_PROPERTY_FROM_QSCRIPTVALUE(xNeighborID, EntityItemID, setXNeighborID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(yNeighborID, EntityItemID, setYNeighborID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(zNeighborID, EntityItemID, setZNeighborID); + _lastEdited = usecTimestampNow(); } @@ -852,6 +867,9 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent APPEND_ENTITY_PROPERTY(PROP_X_TEXTURE_URL, properties.getXTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Y_TEXTURE_URL, properties.getYTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Z_TEXTURE_URL, properties.getZTextureURL()); + APPEND_ENTITY_PROPERTY(PROP_X_NEIGHBOR_ID, properties.getXNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Y_NEIGHBOR_ID, properties.getYNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Z_NEIGHBOR_ID, properties.getZNeighborID()); } if (properties.getType() == EntityTypes::Line) { @@ -1115,6 +1133,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_X_TEXTURE_URL, QString, setXTextureURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Y_TEXTURE_URL, QString, setYTextureURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Z_TEXTURE_URL, QString, setZTextureURL); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_X_NEIGHBOR_ID, EntityItemID, setXNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Y_NEIGHBOR_ID, EntityItemID, setYNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Z_NEIGHBOR_ID, EntityItemID, setZNeighborID); } if (properties.getType() == EntityTypes::Line) { @@ -1248,13 +1269,17 @@ void EntityItemProperties::markAllChanged() { _descriptionChanged = true; _faceCameraChanged = true; _actionDataChanged = true; - + _normalsChanged = true; _strokeWidthsChanged = true; _xTextureURLChanged = true; _yTextureURLChanged = true; _zTextureURLChanged = true; + + _xNeighborIDChanged = true; + _yNeighborIDChanged = true; + _zNeighborIDChanged = true; } /// The maximum bounding cube for the entity, independent of it's rotation. diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 6d95faa9b1..0e0c36ad11 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -161,6 +161,9 @@ public: DEFINE_PROPERTY_REF(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString); DEFINE_PROPERTY_REF(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString); DEFINE_PROPERTY_REF(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString); + DEFINE_PROPERTY_REF(PROP_X_NEIGHBOR_ID, XNeighborID, xNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_Y_NEIGHBOR_ID, YNeighborID, yNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_Z_NEIGHBOR_ID, ZNeighborID, zNeighborID, EntityItemID); static QString getBackgroundModeString(BackgroundMode mode); @@ -327,6 +330,9 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, XTextureURL, xTextureURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, YTextureURL, yTextureURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZTextureURL, zTextureURL, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, XNeighborID, xNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, YNeighborID, yNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZNeighborID, zNeighborID, ""); properties.getStage().debugDump(); properties.getAtmosphere().debugDump(); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index e48be1da8c..a3e31024d1 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -14,6 +14,8 @@ #ifndef hifi_EntityItemPropertiesMacros_h #define hifi_EntityItemPropertiesMacros_h +#include "EntityItemID.h" + #define APPEND_ENTITY_PROPERTY(P,V) \ if (requestedProperties.getHasProperty(P)) { \ LevelDetails propertyLevel = packetData->startLevel(); \ @@ -106,6 +108,9 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) { return QScriptValue(QString(b64)); } +inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v) { return QScriptValue(QUuid(v).toString()); } + + #define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,g,P,p) \ if (!skipDefaults || defaultEntityProperties.get##G().get##P() != get##P()) { \ QScriptValue groupProperties = properties.property(#g); \ @@ -143,6 +148,9 @@ inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { re inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); } inline QString QString_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toString().trimmed(); } inline QUuid QUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); } +inline EntityItemID EntityItemID_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); } + + inline QDateTime QDateTime_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index abb8241d8f..9ad34fa69d 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -124,21 +124,25 @@ enum EntityPropertyList { PROP_FACE_CAMERA, PROP_SCRIPT_TIMESTAMP, - + PROP_ACTION_DATA, - + PROP_X_TEXTURE_URL, // used by PolyVox PROP_Y_TEXTURE_URL, // used by PolyVox PROP_Z_TEXTURE_URL, // used by PolyVox - + // Used by PolyLine entity PROP_NORMALS, PROP_STROKE_WIDTHS, - + // used by particles PROP_VELOCITY_SPREAD, PROP_ACCELERATION_SPREAD, + PROP_X_NEIGHBOR_ID, // used by PolyVox + PROP_Y_NEIGHBOR_ID, // used by PolyVox + PROP_Z_NEIGHBOR_ID, // used by PolyVox + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 9e45efe88d..7dab825adc 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -131,20 +131,20 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() { float maxVelocityX = fabsf(_velocity.x) + _velocitySpread.x; float maxAccelerationX = fabsf(_acceleration.x) + _accelerationSpread.x; - float maxXDistance = (maxVelocityX * time) + (0.5 * maxAccelerationX * time * time); + float maxXDistance = (maxVelocityX * time) + (0.5f * maxAccelerationX * time * time); - float maxVelocityY = fabs(_velocity.y) + _velocitySpread.y; + float maxVelocityY = fabsf(_velocity.y) + _velocitySpread.y; float maxAccelerationY = fabsf(_acceleration.y) + _accelerationSpread.y; - float maxYDistance = (maxVelocityY * time) + (0.5 * maxAccelerationY * time * time); + float maxYDistance = (maxVelocityY * time) + (0.5f * maxAccelerationY * time * time); float maxVelocityZ = fabsf(_velocity.z) + _velocitySpread.z; float maxAccelerationZ = fabsf(_acceleration.z) + _accelerationSpread.z; - float maxZDistance = (maxVelocityZ * time) + (0.5 * maxAccelerationZ * time * time); + float maxZDistance = (maxVelocityZ * time) + (0.5f * maxAccelerationZ * time * time); float maxDistance = std::max(maxXDistance, std::max(maxYDistance, maxZDistance)); //times 2 because dimensions are diameters not radii - glm::vec3 dims(2.0 * maxDistance); + glm::vec3 dims(2.0f * maxDistance); EntityItem::setDimensions(dims); } diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index e765afd430..dbf0f67288 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -56,7 +56,10 @@ PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const Ent _voxelSurfaceStyle(PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE), _xTextureURL(PolyVoxEntityItem::DEFAULT_X_TEXTURE_URL), _yTextureURL(PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL), - _zTextureURL(PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL) + _zTextureURL(PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL), + _xNeighborID(UNKNOWN_ENTITY_ID), + _yNeighborID(UNKNOWN_ENTITY_ID), + _zNeighborID(UNKNOWN_ENTITY_ID) { _type = EntityTypes::PolyVox; setProperties(properties); @@ -104,6 +107,9 @@ EntityItemProperties PolyVoxEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(xTextureURL, getXTextureURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(yTextureURL, getYTextureURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(zTextureURL, getZTextureURL); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(xNeighborID, getXNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(yNeighborID, getYNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(zNeighborID, getZNeighborID); return properties; } @@ -116,6 +122,9 @@ bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(xTextureURL, setXTextureURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(yTextureURL, setYTextureURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(zTextureURL, setZTextureURL); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(xNeighborID, setXNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(yNeighborID, setYNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(zNeighborID, setZNeighborID); if (somethingChanged) { bool wantDebug = false; @@ -143,6 +152,9 @@ int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* dat READ_ENTITY_PROPERTY(PROP_X_TEXTURE_URL, QString, setXTextureURL); READ_ENTITY_PROPERTY(PROP_Y_TEXTURE_URL, QString, setYTextureURL); READ_ENTITY_PROPERTY(PROP_Z_TEXTURE_URL, QString, setZTextureURL); + READ_ENTITY_PROPERTY(PROP_X_NEIGHBOR_ID, EntityItemID, setXNeighborID); + READ_ENTITY_PROPERTY(PROP_Y_NEIGHBOR_ID, EntityItemID, setYNeighborID); + READ_ENTITY_PROPERTY(PROP_Z_NEIGHBOR_ID, EntityItemID, setZNeighborID); return bytesRead; } @@ -160,13 +172,13 @@ EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams return requestedProperties; } -void PolyVoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, +void PolyVoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, - int& propertyCount, - OctreeElement::AppendState& appendState) const { + int& propertyCount, + OctreeElement::AppendState& appendState) const { bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_VOXEL_VOLUME_SIZE, getVoxelVolumeSize()); @@ -175,7 +187,9 @@ void PolyVoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeB APPEND_ENTITY_PROPERTY(PROP_X_TEXTURE_URL, getXTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Y_TEXTURE_URL, getYTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Z_TEXTURE_URL, getZTextureURL()); - + APPEND_ENTITY_PROPERTY(PROP_X_NEIGHBOR_ID, getXNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Y_NEIGHBOR_ID, getYNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Z_NEIGHBOR_ID, getZNeighborID()); } void PolyVoxEntityItem::debugDump() const { diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index c84dc9f4c1..1e22327df0 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -103,6 +103,17 @@ class PolyVoxEntityItem : public EntityItem { virtual void setZTextureURL(QString zTextureURL) { _zTextureURL = zTextureURL; } virtual const QString& getZTextureURL() const { return _zTextureURL; } + virtual void setXNeighborID(const EntityItemID& xNeighborID) { _xNeighborID = xNeighborID; } + virtual void setXNeighborID(const QString& xNeighborID) { _xNeighborID = QUuid(xNeighborID); } + virtual const EntityItemID& getXNeighborID() const { return _xNeighborID; } + virtual void setYNeighborID(const EntityItemID& yNeighborID) { _yNeighborID = yNeighborID; } + virtual void setYNeighborID(const QString& yNeighborID) { _yNeighborID = QUuid(yNeighborID); } + virtual const EntityItemID& getYNeighborID() const { return _yNeighborID; } + virtual void setZNeighborID(const EntityItemID& zNeighborID) { _zNeighborID = zNeighborID; } + virtual void setZNeighborID(const QString& zNeighborID) { _zNeighborID = QUuid(zNeighborID); } + virtual const EntityItemID& getZNeighborID() const { return _zNeighborID; } + + protected: glm::vec3 _voxelVolumeSize; // this is always 3 bytes @@ -116,6 +127,10 @@ class PolyVoxEntityItem : public EntityItem { QString _yTextureURL; QString _zTextureURL; + // for non-edged surface styles, these are used to compute the high-axis edges + EntityItemID _xNeighborID; + EntityItemID _yNeighborID; + EntityItemID _zNeighborID; }; #endif // hifi_PolyVoxEntityItem_h diff --git a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp b/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp index fabb488ab4..1b9b87684c 100755 --- a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp +++ b/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp @@ -230,7 +230,7 @@ void UserInputMapper::update(float deltaTime) { for (auto i = 0; i < NUM_ACTIONS; i++) { _actionStates[i] *= _actionScales[i]; // Emit only on change, and emit when moving back to 0 - if (fabs(_actionStates[i] - _lastActionStates[i]) > EPSILON) { + if (fabsf(_actionStates[i] - _lastActionStates[i]) > EPSILON) { _lastActionStates[i] = _actionStates[i]; emit actionEvent(i, _actionStates[i]); } @@ -319,4 +319,4 @@ void UserInputMapper::createActionNames() { _actionNames[SHIFT] = "SHIFT"; _actionNames[ACTION1] = "ACTION1"; _actionNames[ACTION2] = "ACTION2"; -} \ No newline at end of file +} diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 7e73b4c660..737e827c90 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -67,7 +67,7 @@ PacketVersion versionForPacketType(PacketType::Value packetType) { case EntityAdd: case EntityEdit: case EntityData: - return VERSION_ENTITIES_PARTICLE_MODIFICATIONS; + return VERSION_ENTITIES_POLYVOX_NEIGHBORS; case AvatarData: return 12; default: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fa6178b627..d22ee59cad 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -144,5 +144,6 @@ const PacketVersion VERSION_POLYVOX_TEXTURES = 36; const PacketVersion VERSION_ENTITIES_POLYLINE = 37; const PacketVersion VERSION_OCTREE_CENTERED_ORIGIN = 38; const PacketVersion VERSION_ENTITIES_PARTICLE_MODIFICATIONS = 39; +const PacketVersion VERSION_ENTITIES_POLYVOX_NEIGHBORS = 40; -#endif // hifi_PacketHeaders_h \ No newline at end of file +#endif // hifi_PacketHeaders_h diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 64f3bb6708..ebd2053442 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -243,7 +243,7 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons batch._glUniform2f(_depthTexCoordScaleLoc, depthTexCoordScaleS, depthTexCoordScaleT); batch._glUniform2f(_renderTargetResLoc, fbWidth, fbHeight); - batch._glUniform2f(_renderTargetResInvLoc, 1.0/fbWidth, 1.0/fbHeight); + batch._glUniform2f(_renderTargetResInvLoc, 1.0f / fbWidth, 1.0f / fbHeight); glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); glm::vec2 bottomLeft(-1.0f, -1.0f); diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 86707d9dcd..4ca8ed330b 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -372,20 +372,20 @@ QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size) { // create matrix from orientation and position glm::mat4 createMatFromQuatAndPos(const glm::quat& q, const glm::vec3& p) { glm::mat4 m = glm::mat4_cast(q); - m[3] = glm::vec4(p, 1); + m[3] = glm::vec4(p, 1.0f); return m; } // cancel out roll and pitch glm::quat cancelOutRollAndPitch(const glm::quat& q) { - glm::vec3 zAxis = q * glm::vec3(0, 0, 1); + glm::vec3 zAxis = q * glm::vec3(0.0f, 0.0f, 1.0f); // cancel out the roll and pitch - glm::vec3 newZ = (zAxis.x == 0 && zAxis.z == 0) ? vec3(1, 0, 0) : glm::normalize(vec3(zAxis.x, 0, zAxis.z)); - glm::vec3 newX = glm::cross(vec3(0, 1, 0), newZ); + glm::vec3 newZ = (zAxis.x == 0 && zAxis.z == 0.0f) ? vec3(1.0f, 0.0f, 0.0f) : glm::normalize(vec3(zAxis.x, 0.0f, zAxis.z)); + glm::vec3 newX = glm::cross(vec3(0.0f, 1.0f, 0.0f), newZ); glm::vec3 newY = glm::cross(newZ, newX); - glm::mat4 temp(glm::vec4(newX, 0), glm::vec4(newY, 0), glm::vec4(newZ, 0), glm::vec4(0, 0, 0, 1)); + glm::mat4 temp(glm::vec4(newX, 0.0f), glm::vec4(newY, 0.0f), glm::vec4(newZ, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); return glm::quat_cast(temp); } @@ -394,15 +394,15 @@ glm::mat4 cancelOutRollAndPitch(const glm::mat4& m) { glm::vec3 zAxis = glm::vec3(m[2]); // cancel out the roll and pitch - glm::vec3 newZ = (zAxis.x == 0 && zAxis.z == 0) ? vec3(1, 0, 0) : glm::normalize(vec3(zAxis.x, 0, zAxis.z)); - glm::vec3 newX = glm::cross(vec3(0, 1, 0), newZ); + glm::vec3 newZ = (zAxis.x == 0.0f && zAxis.z == 0.0f) ? vec3(1.0f, 0.0f, 0.0f) : glm::normalize(vec3(zAxis.x, 0.0f, zAxis.z)); + glm::vec3 newX = glm::cross(vec3(0.0f, 1.0f, 0.0f), newZ); glm::vec3 newY = glm::cross(newZ, newX); - glm::mat4 temp(glm::vec4(newX, 0), glm::vec4(newY, 0), glm::vec4(newZ, 0), m[3]); + glm::mat4 temp(glm::vec4(newX, 0.0f), glm::vec4(newY, 0.0f), glm::vec4(newZ, 0.0f), m[3]); return temp; } glm::vec3 transformPoint(const glm::mat4& m, const glm::vec3& p) { - glm::vec4 temp = m * glm::vec4(p, 1); + glm::vec4 temp = m * glm::vec4(p, 1.0f); return glm::vec3(temp.x / temp.w, temp.y / temp.w, temp.z / temp.w); } diff --git a/tests/entities/src/main.cpp b/tests/entities/src/main.cpp index 740d401107..a94bda9a86 100644 --- a/tests/entities/src/main.cpp +++ b/tests/entities/src/main.cpp @@ -93,8 +93,8 @@ template void testByteCountCoded() { testByteCountCodedStable(0); testByteCountCodedStable(1); - testByteCountCodedStable(1 << 16); - testByteCountCodedStable(std::numeric_limits::max() >> 16); + testByteCountCodedStable(1 << 8*sizeof(T)); + testByteCountCodedStable(std::numeric_limits::max() >> 8*sizeof(T)); testByteCountCodedStable(std::numeric_limits::max() >> 8); testByteCountCodedStable(std::numeric_limits::max() >> 1); testByteCountCodedStable(std::numeric_limits::max()); diff --git a/tests/gpu-test/src/main.cpp b/tests/gpu-test/src/main.cpp index 758d9b29bb..b27d10e312 100644 --- a/tests/gpu-test/src/main.cpp +++ b/tests/gpu-test/src/main.cpp @@ -342,8 +342,8 @@ public: glm::vec3 unitscale { 1.0f }; glm::vec3 up { 0.0f, 1.0f, 0.0f }; - glm::vec3 cam_pos { 1.5f * sin(t), 0.0f, 2.0f }; -// glm::vec3 camera_focus { 5.0f * cos(t * 0.1f), 0.0f, 0.0f }; + glm::vec3 cam_pos { 1.5f * sinf(t), 0.0f, 2.0f }; +// glm::vec3 camera_focus { 5.0f * cosf(t * 0.1f), 0.0f, 0.0f }; glm::vec3 camera_focus { 0.0f, 0.0f, 0.0f }; glm::quat cam_rotation; // glm::quat cam_rotation = glm::quat_cast(glm::lookAt(cam_pos, camera_focus, up)); From 41a2ff2fff61dc324daf9f67659a440dc3339641 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 30 Aug 2015 18:42:15 -0700 Subject: [PATCH 02/23] working on stitching marching-cube polyvoxs together --- examples/voxels.js | 109 +++++++--- .../src/RenderablePolyVoxEntityItem.cpp | 186 +++++++++--------- libraries/entities/src/PolyVoxEntityItem.cpp | 9 +- libraries/entities/src/PolyVoxEntityItem.h | 6 +- 4 files changed, 183 insertions(+), 127 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index d9049e2b0c..1859ac8a8b 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -155,48 +155,111 @@ var toolBar = (function () { }()); + +function getTerrainAlignedLocation(pos) { + var posDiv16 = Vec3.multiply(pos, 1.0 / 16.0); + var posDiv16Floored = floorVector(posDiv16); + return Vec3.multiply(posDiv16Floored, 16.0); +} + + +function lookupTerrainForLocation(pos) { + var baseLocation = getTerrainAlignedLocation(pos); + entitiesAtLoc = Entities.findEntities(baseLocation, 1.0); + for (var i = 0; i < entitiesAtLoc.length; i++) { + var id = entitiesAtLoc[i]; + var properties = Entities.getEntityProperties(id); + if (properties.name == "terrain") { + return id; + } + } + + return false; +} + + function addTerrainBlock() { - - var myPosDiv16 = Vec3.multiply(Vec3.sum(MyAvatar.position, {x:8, x:8, z:8}), 1.0 / 16.0); - var myPosDiv16Floored = floorVector(myPosDiv16); - var baseLocation = Vec3.multiply(myPosDiv16Floored, 16.0); - - if (baseLocation.y + 8 > MyAvatar.position.y) { + var baseLocation = getTerrainAlignedLocation(Vec3.sum(MyAvatar.position, {x:8, y:8, z:8})); + if (baseLocation.y > MyAvatar.position.y) { baseLocation.y -= 16; } - print("myPosDiv16 is " + vectorToString(myPosDiv16)); - print("MyPosDiv16Floored is " + vectorToString(myPosDiv16Floored)); - print("baseLocation is " + vectorToString(baseLocation)); - - alreadyThere = Entities.findEntities(baseLocation, 1.0); - for (var i = 0; i < alreadyThere.length; i++) { - var id = alreadyThere[i]; - var properties = Entities.getEntityProperties(id); - if (properties.name == "terrain") { - print("already terrain there"); - return; - } + var alreadyThere = lookupTerrainForLocation(baseLocation); + if (alreadyThere) { + return; } var polyVoxId = Entities.addEntity({ type: "PolyVox", name: "terrain", position: baseLocation, - dimensions: { x: 16, y: 16, z: 16 }, - voxelVolumeSize: {x:16, y:16, z:16}, - voxelSurfaceStyle: 2 + dimensions: { x:16, y:16, z:16 }, + voxelVolumeSize: {x:16, y:32, z:16}, + voxelSurfaceStyle: 0, + xTextureURL: "http://headache.hungry.com/~seth/hifi/dirt.jpeg", + yTextureURL: "http://headache.hungry.com/~seth/hifi/grass.png", + zTextureURL: "http://headache.hungry.com/~seth/hifi/dirt.jpeg" }); Entities.setAllVoxels(polyVoxId, 255); - for (var y = 8; y < 16; y++) { + // XXX use setCuboid + for (var y = 16; y < 32; y++) { for (var x = 0; x < 16; x++) { for (var z = 0; z < 16; z++) { - Entities.setVoxel(polyVoxId, {x: x, y: y, z: z}, 0); + Entities.setVoxel(polyVoxId, {x:x, y:y, z:z}, 0); } } } + ////////// + // stitch together the terrain with x/y/z NeighorID properties + ////////// + + // link plots which are lower on the axes to this one + imXNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:-16, y:0, z:0})); + if (imXNeighborFor) { + var properties = Entities.getEntityProperties(imXNeighborFor); + properties.xNeighborID = polyVoxId; + Entities.editEntity(imXNeighborFor, properties); + } + + imYNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:-16, z:0})); + if (imYNeighborFor) { + var properties = Entities.getEntityProperties(imYNeighborFor); + properties.yNeighborID = polyVoxId; + Entities.editEntity(imYNeighborFor, properties); + } + + imZNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:-16})); + if (imZNeighborFor) { + var properties = Entities.getEntityProperties(imZNeighborFor); + properties.zNeighborID = polyVoxId; + Entities.editEntity(imZNeighborFor, properties); + } + + + // link this plot to plots which are higher on the axes + xNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:16, y:0, z:0})); + if (xNeighborFor) { + var properties = Entities.getEntityProperties(polyVoxId); + properties.xNeighborID = xNeighborFor; + Entities.editEntity(polyVoxId, properties); + } + + yNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:16, z:0})); + if (yNeighborFor) { + var properties = Entities.getEntityProperties(polyVoxId); + properties.yNeighborID = yNeighborFor; + Entities.editEntity(polyVoxId, properties); + } + + zNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:16})); + if (zNeighborFor) { + var properties = Entities.getEntityProperties(polyVoxId); + properties.zNeighborID = zNeighborFor; + Entities.editEntity(polyVoxId, properties); + } + return true; } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 5ad23c91be..7ec9357dda 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -68,6 +68,19 @@ RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() { } +bool isEdged(PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle) { + switch (surfaceStyle) { + case PolyVoxEntityItem::SURFACE_CUBIC: + return true; + case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: + case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: + case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: + return true; + } + return false; +} + + void RenderablePolyVoxEntityItem::setVoxelData(QByteArray voxelData) { _voxelDataLock.lockForWrite(); if (_voxelData == voxelData) { @@ -88,10 +101,8 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel } // if we are switching to or from "edged" we need to force a resize of _volData. - bool wasEdged = (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC || - _voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES); - bool willBeEdged = (voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC || - voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES); + bool wasEdged = isEdged(_voxelSurfaceStyle); + bool willBeEdged = isEdged(voxelSurfaceStyle); if (wasEdged != willBeEdged) { _volDataLock.lockForWrite(); @@ -113,15 +124,10 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units - switch (_voxelSurfaceStyle) { - case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: - case PolyVoxEntityItem::SURFACE_CUBIC: - return scale / 2.0f; - case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: - case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: - return scale / -2.0f; + if (isEdged(_voxelSurfaceStyle)) { + return scale / -2.0f; } - return glm::vec3(0.0f, 0.0f, 0.0f); + return scale / 2.0f; } @@ -429,9 +435,12 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { _volDataLock.lockForRead(); if (_volDataDirty) { + _volDataLock.unlock(); getMesh(); + } else { + _volDataLock.unlock(); } - _volDataLock.unlock(); + _meshLock.lockForRead(); model::MeshPointer mesh = _mesh; @@ -551,18 +560,10 @@ glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3& voxel glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3& worldCoords) const { glm::vec3 result = glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f)); - switch (_voxelSurfaceStyle) { - case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: - case PolyVoxEntityItem::SURFACE_CUBIC: - result += glm::vec3(0.5f, 0.5f, 0.5f); - break; - case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: - case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: - result -= glm::vec3(0.5f, 0.5f, 0.5f); - break; + if (isEdged(_voxelSurfaceStyle)) { + return result - glm::vec3(0.5f, 0.5f, 0.5f); } - - return result; + return result + glm::vec3(0.5f, 0.5f, 0.5f); } glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const { @@ -588,8 +589,7 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) } _onCount = 0; - if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC || - _voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES) { + if (isEdged(_voxelSurfaceStyle)) { // with _EDGED_ we maintain an extra box of voxels around those that the user asked for. This // changes how the surface extractor acts -- mainly it becomes impossible to have holes in the // generated mesh. The non _EDGED_ modes will leave holes in the mesh at the edges of the @@ -601,27 +601,12 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) _volData = new PolyVox::SimpleVolume(PolyVox::Region(lowCorner, highCorner)); } else { PolyVox::Vector3DInt32 lowCorner(0, 0, 0); - PolyVox::Vector3DInt32 highCorner(_voxelVolumeSize.x, // -1 because these corners are inclusive + // these should each have -1 after them, but if we leave layers on the upper-axis faces, + // they act more like I expect. + PolyVox::Vector3DInt32 highCorner(_voxelVolumeSize.x, _voxelVolumeSize.y, _voxelVolumeSize.z); _volData = new PolyVox::SimpleVolume(PolyVox::Region(lowCorner, highCorner)); - - - // // XXX - // { - // for (int x = 0; x <= _voxelVolumeSize.x; x++) { - // for (int y = 0; y <= _voxelVolumeSize.y; y++) { - // for (int z = 0; z <= _voxelVolumeSize.z; z++) { - // if (x == _voxelVolumeSize.x || - // y == _voxelVolumeSize.y || - // z == _voxelVolumeSize.z) { - // setVoxelInternal(x, y, z, 255); - // } - // } - // } - // } - // } - } // having the "outside of voxel-space" value be 255 has helped me notice some problems. @@ -635,25 +620,19 @@ bool RenderablePolyVoxEntityItem::inUserBounds(const PolyVox::SimpleVolume= vol->getWidth() || y >= vol->getHeight() || z >= vol->getDepth()) { - return false; - } - return true; - - case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: - case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: - if (x < 0 || y < 0 || z < 0 || - x >= vol->getWidth() - 2 || y >= vol->getHeight() - 2 || z >= vol->getDepth() - 2) { - return false; - } - return true; + if (isEdged(surfaceStyle)) { + if (x < 0 || y < 0 || z < 0 || + x >= vol->getWidth() - 2 || y >= vol->getHeight() - 2 || z >= vol->getDepth() - 2) { + return false; + } + return true; + } else { + if (x < 0 || y < 0 || z < 0 || + x >= vol->getWidth() || y >= vol->getHeight() || z >= vol->getDepth()) { + return false; + } + return true; } - - return false; } @@ -670,19 +649,13 @@ uint8_t RenderablePolyVoxEntityItem::getVoxelInternal(int x, int y, int z) { return 0; } - // if _voxelSurfaceStyle is SURFACE_EDGED_CUBIC, we maintain an extra layer of + // if _voxelSurfaceStyle is *_EDGED_*, we maintain an extra layer of // voxels all around the requested voxel space. Having the empty voxels around // the edges changes how the surface extractor behaves. - - uint8_t result; - if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC || - _voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES) { - result = _volData->getVoxelAt(x + 1, y + 1, z + 1); - } else { - result = _volData->getVoxelAt(x, y, z); + if (isEdged(_voxelSurfaceStyle)) { + return _volData->getVoxelAt(x + 1, y + 1, z + 1); } - - return result; + return _volData->getVoxelAt(x, y, z); } @@ -695,9 +668,7 @@ bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t result = updateOnCount(x, y, z, toValue); - assert(_volData); - if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC || - _voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES) { + if (isEdged(_voxelSurfaceStyle)) { _volData->setVoxelAt(x + 1, y + 1, z + 1, toValue); } else { _volData->setVoxelAt(x, y, z, toValue); @@ -893,8 +864,7 @@ void RenderablePolyVoxEntityItem::clearOutOfDateNeighbors() { } void RenderablePolyVoxEntityItem::cacheNeighbors() { - if (_voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_CUBIC && - _voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { + if (_voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { return; } @@ -917,8 +887,7 @@ void RenderablePolyVoxEntityItem::cacheNeighbors() { } void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { - if (_voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_CUBIC && - _voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { + if (_voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { return; } @@ -927,36 +896,51 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { EntityItemPointer currentZNeighbor = _zNeighbor.lock(); if (currentXNeighbor) { - auto polyVoxXNeighbor = std::dynamic_pointer_cast(currentXNeighbor); - for (int y = 0; y < _voxelVolumeSize.y; y++) { - for (int z = 0; z < _voxelVolumeSize.z; y++) { - uint8_t neighborValue = polyVoxXNeighbor->getVoxel(0, y, z); - _volData->setVoxelAt(_voxelVolumeSize.x, y, z, neighborValue); + auto polyVoxXNeighbor = std::dynamic_pointer_cast(currentXNeighbor); + if (polyVoxXNeighbor->_volData->getEnclosingRegion() == _volData->getEnclosingRegion()) { + for (int y = 0; y < _volData->getHeight(); y++) { + for (int z = 0; z < _volData->getDepth(); z++) { + uint8_t neighborValue = polyVoxXNeighbor->_volData->getVoxelAt(1, y, z); + _volData->setVoxelAt(_volData->getWidth() - 1, y, z, neighborValue); + } } } } if (currentYNeighbor) { - auto polyVoxYNeighbor = std::dynamic_pointer_cast(currentYNeighbor); - for (int x = 0; x < _voxelVolumeSize.x; x++) { - for (int z = 0; z < _voxelVolumeSize.z; z++) { - uint8_t neighborValue = polyVoxYNeighbor->getVoxel(x, 0, z); - _volData->setVoxelAt(x, _voxelVolumeSize.y, z, neighborValue); + auto polyVoxYNeighbor = std::dynamic_pointer_cast(currentYNeighbor); + if (polyVoxYNeighbor->_volData->getEnclosingRegion() == _volData->getEnclosingRegion()) { + for (int x = 0; x < _volData->getWidth(); x++) { + for (int z = 0; z < _volData->getDepth(); z++) { + uint8_t neighborValue = polyVoxYNeighbor->_volData->getVoxelAt(x, 1, z); + _volData->setVoxelAt(x, _volData->getWidth() - 1, z, neighborValue); + } } } } if (currentZNeighbor) { - auto polyVoxZNeighbor = std::dynamic_pointer_cast(currentZNeighbor); - for (int x = 0; x < _voxelVolumeSize.x; x++) { - for (int y = 0; y < _voxelVolumeSize.y; y++) { - uint8_t neighborValue = polyVoxZNeighbor->getVoxel(x, y, 0); - _volData->setVoxelAt(x, y, _voxelVolumeSize.z, neighborValue); + auto polyVoxZNeighbor = std::dynamic_pointer_cast(currentZNeighbor); + if (polyVoxZNeighbor->_volData->getEnclosingRegion() == _volData->getEnclosingRegion()) { + for (int x = 0; x < _volData->getWidth(); x++) { + for (int y = 0; y < _volData->getHeight(); y++) { + uint8_t neighborValue = polyVoxZNeighbor->_volData->getVoxelAt(x, y, 1); + _volData->setVoxelAt(x, y, _volData->getDepth() - 1, neighborValue); + } } } } } + +// PolyVox::Region shrinkRegion(PolyVox::Region originalRegion) { +// PolyVox::Region smallerRegion = originalRegion; +// smallerRegion.shiftLowerCorner(PolyVox::Vector3DInt32(1, 1, 1)); +// smallerRegion.shiftUpperCorner(PolyVox::Vector3DInt32(-1, -1, -1)); +// return smallerRegion; +// } + + void RenderablePolyVoxEntityItem::getMeshAsync() { model::MeshPointer mesh(new model::Mesh()); @@ -968,14 +952,24 @@ void RenderablePolyVoxEntityItem::getMeshAsync() { _volDataLock.lockForRead(); switch (_voxelSurfaceStyle) { - case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: + case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: { + PolyVox::MarchingCubesSurfaceExtractor> surfaceExtractor + (_volData, _volData->getEnclosingRegion(), &polyVoxMesh); + surfaceExtractor.execute(); + break; + } case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: { PolyVox::MarchingCubesSurfaceExtractor> surfaceExtractor (_volData, _volData->getEnclosingRegion(), &polyVoxMesh); surfaceExtractor.execute(); break; } - case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: + case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: { + PolyVox::CubicSurfaceExtractorWithNormals> surfaceExtractor + (_volData, _volData->getEnclosingRegion(), &polyVoxMesh); + surfaceExtractor.execute(); + break; + } case PolyVoxEntityItem::SURFACE_CUBIC: { PolyVox::CubicSurfaceExtractorWithNormals> surfaceExtractor (_volData, _volData->getEnclosingRegion(), &polyVoxMesh); diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index dbf0f67288..0ce71a37ad 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -56,11 +56,7 @@ PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const Ent _voxelSurfaceStyle(PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE), _xTextureURL(PolyVoxEntityItem::DEFAULT_X_TEXTURE_URL), _yTextureURL(PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL), - _zTextureURL(PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL), - _xNeighborID(UNKNOWN_ENTITY_ID), - _yNeighborID(UNKNOWN_ENTITY_ID), - _zNeighborID(UNKNOWN_ENTITY_ID) -{ + _zTextureURL(PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL) { _type = EntityTypes::PolyVox; setProperties(properties); } @@ -169,6 +165,9 @@ EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams requestedProperties += PROP_X_TEXTURE_URL; requestedProperties += PROP_Y_TEXTURE_URL; requestedProperties += PROP_Z_TEXTURE_URL; + requestedProperties += PROP_X_NEIGHBOR_ID; + requestedProperties += PROP_Y_NEIGHBOR_ID; + requestedProperties += PROP_Z_NEIGHBOR_ID; return requestedProperties; } diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 1e22327df0..886a9c37c7 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -128,9 +128,9 @@ class PolyVoxEntityItem : public EntityItem { QString _zTextureURL; // for non-edged surface styles, these are used to compute the high-axis edges - EntityItemID _xNeighborID; - EntityItemID _yNeighborID; - EntityItemID _zNeighborID; + EntityItemID _xNeighborID{UNKNOWN_ENTITY_ID}; + EntityItemID _yNeighborID{UNKNOWN_ENTITY_ID}; + EntityItemID _zNeighborID{UNKNOWN_ENTITY_ID}; }; #endif // hifi_PolyVoxEntityItem_h From 376a6bbb210a8d0db3d56fab661d73582ef95cb9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 31 Aug 2015 11:48:08 -0700 Subject: [PATCH 03/23] don't reload textures if the url didn't change --- .../src/RenderablePolyVoxEntityItem.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 7ec9357dda..66054aad5a 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -71,8 +71,8 @@ RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() { bool isEdged(PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle) { switch (surfaceStyle) { case PolyVoxEntityItem::SURFACE_CUBIC: - return true; case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: + return false; case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: return true; @@ -414,18 +414,24 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { } void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) { - _xTexture.clear(); - PolyVoxEntityItem::setXTextureURL(xTextureURL); + if (xTextureURL != _xTextureURL) { + _xTexture.clear(); + PolyVoxEntityItem::setXTextureURL(xTextureURL); + } } void RenderablePolyVoxEntityItem::setYTextureURL(QString yTextureURL) { - _yTexture.clear(); - PolyVoxEntityItem::setYTextureURL(yTextureURL); + if (yTextureURL != _yTextureURL) { + _yTexture.clear(); + PolyVoxEntityItem::setYTextureURL(yTextureURL); + } } void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { - _zTexture.clear(); - PolyVoxEntityItem::setZTextureURL(zTextureURL); + if (zTextureURL != _zTextureURL) { + _zTexture.clear(); + PolyVoxEntityItem::setZTextureURL(zTextureURL); + } } void RenderablePolyVoxEntityItem::render(RenderArgs* args) { From 4d06890d90310ce2aff14d969436f4cef536e7a1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 31 Aug 2015 15:24:15 -0700 Subject: [PATCH 04/23] lock/unlock less --- .../src/RenderablePolyVoxEntityItem.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 66054aad5a..7d7607860d 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1081,10 +1081,16 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorkerAsync() { } else { unsigned int i = 0; + _volDataLock.lockForRead(); + if (!_volData) { + _volDataLock.unlock(); + 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++) { - if (getVoxel(x, y, z) > 0) { + if (getVoxelInternal(x, y, z) > 0) { if ((x > 0 && getVoxel(x - 1, y, z) > 0) && (y > 0 && getVoxel(x, y - 1, z) > 0) && @@ -1142,6 +1148,7 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorkerAsync() { } } } + _volDataLock.unlock(); } if (points.isEmpty()) { From 54ddcf2841a48c1a5f76c1b27a7c08df7710f02e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 31 Aug 2015 15:24:30 -0700 Subject: [PATCH 05/23] fix normals in shader --- libraries/entities-renderer/src/polyvox.slf | 23 +++++++-------------- libraries/entities-renderer/src/polyvox.slv | 4 ++-- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index 5772a93f7d..c694630770 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -12,16 +12,12 @@ // <@include gpu/Inputs.slh@> - -layout(location = 0) out vec4 _fragColor0; -layout(location = 1) out vec4 _fragColor1; -layout(location = 2) out vec4 _fragColor2; - <@include model/Material.slh@> +<@include DeferredBufferWrite.slh@> in vec3 _normal; in vec4 _position; -in vec4 _inPosition; +in vec4 _worldPosition; uniform sampler2D xMap; uniform sampler2D yMap; @@ -29,12 +25,12 @@ uniform sampler2D zMap; uniform vec3 voxelVolumeSize; void main(void) { - vec3 worldNormal = cross(dFdy(_inPosition.xyz), dFdx(_inPosition.xyz)); + vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); worldNormal = normalize(worldNormal); - float inPositionX = (_inPosition.x - 0.5) / voxelVolumeSize.x; - float inPositionY = (_inPosition.y - 0.5) / voxelVolumeSize.y; - float inPositionZ = (_inPosition.z - 0.5) / voxelVolumeSize.z; + float inPositionX = (_worldPosition.x - 0.5) / voxelVolumeSize.x; + float inPositionY = (_worldPosition.y - 0.5) / voxelVolumeSize.y; + float inPositionZ = (_worldPosition.z - 0.5) / voxelVolumeSize.z; vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY)); vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ)); @@ -43,12 +39,7 @@ void main(void) { vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z); vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y); vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); - vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); - Material mat = getMaterial(); - - _fragColor0 = vec4(diffuse.rgb, 0.0); - _fragColor1 = vec4(_normal, 1.0); - _fragColor2 = vec4(getMaterialSpecular(mat), getMaterialShininess(mat) / 128.0); + packDeferredFragment(_normal, 0.0, vec3(diffuse), vec3(0.01, 0.01, 0.01), 10.0); } diff --git a/libraries/entities-renderer/src/polyvox.slv b/libraries/entities-renderer/src/polyvox.slv index 0074993c80..eb8d264a1b 100644 --- a/libraries/entities-renderer/src/polyvox.slv +++ b/libraries/entities-renderer/src/polyvox.slv @@ -17,7 +17,7 @@ <$declareStandardTransform()$> out vec4 _position; -out vec4 _inPosition; +out vec4 _worldPosition; out vec3 _normal; void main(void) { @@ -26,5 +26,5 @@ void main(void) { TransformObject obj = getTransformObject(); <$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$> <$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$> - _inPosition = inPosition; + _worldPosition = inPosition; } From 6096c20db0817f2087343fda337601b21f7c8726 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 31 Aug 2015 18:00:31 -0700 Subject: [PATCH 06/23] allow adding and deleting spheres --- examples/voxels.js | 134 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 31 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 1859ac8a8b..3fbdb4b6e6 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -12,9 +12,12 @@ var toolWidth = 50; var addingVoxels = false; var deletingVoxels = false; +var addingSpheres = false; +var deletingSpheres = false; -offAlpha = 0.5; -onAlpha = 0.9; +var offAlpha = 0.5; +var onAlpha = 0.9; +var editSphereRadius = 3.0; function floorVector(v) { return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)}; @@ -30,6 +33,8 @@ var toolBar = (function () { activeButton, addVoxelButton, deleteVoxelButton, + addSphereButton, + deleteSphereButton, addTerrainButton; function initialize() { @@ -66,6 +71,24 @@ var toolBar = (function () { visible: false }); + addSphereButton = toolBar.addTool({ + imageURL: toolIconUrl + "sphere-add.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: toolWidth, + height: toolHeight, + alpha: offAlpha, + visible: false + }); + + deleteSphereButton = toolBar.addTool({ + imageURL: toolIconUrl + "sphere-delete.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: toolWidth, + height: toolHeight, + alpha: offAlpha, + visible: false + }); + addTerrainButton = toolBar.addTool({ imageURL: toolIconUrl + "voxel-terrain.svg", subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, @@ -78,6 +101,22 @@ var toolBar = (function () { that.setActive(false); } + function disableAllButtons() { + addingVoxels = false; + deletingVoxels = false; + addingSpheres = false; + deletingSpheres = false; + + toolBar.setAlpha(offAlpha, addVoxelButton); + toolBar.setAlpha(offAlpha, deleteVoxelButton); + toolBar.setAlpha(offAlpha, addSphereButton); + toolBar.setAlpha(offAlpha, deleteSphereButton); + + toolBar.selectTool(addVoxelButton, false); + toolBar.selectTool(deleteVoxelButton, false); + toolBar.selectTool(addSphereButton, false); + toolBar.selectTool(deleteSphereButton, false); + } that.setActive = function(active) { if (active != isActive) { @@ -91,6 +130,8 @@ var toolBar = (function () { that.showTools = function(doShow) { toolBar.showTool(addVoxelButton, doShow); toolBar.showTool(deleteVoxelButton, doShow); + toolBar.showTool(addSphereButton, doShow); + toolBar.showTool(deleteSphereButton, doShow); toolBar.showTool(addTerrainButton, doShow); }; @@ -103,37 +144,46 @@ var toolBar = (function () { } if (addVoxelButton === toolBar.clicked(clickedOverlay)) { - if (addingVoxels) { - addingVoxels = false; - deletingVoxels = false; - toolBar.setAlpha(offAlpha, addVoxelButton); - toolBar.setAlpha(offAlpha, deleteVoxelButton); - toolBar.selectTool(addVoxelButton, false); - toolBar.selectTool(deleteVoxelButton, false); - } else { + var wasAddingVoxels = addingVoxels; + disableAllButtons() + if (!wasAddingVoxels) { addingVoxels = true; - deletingVoxels = false; toolBar.setAlpha(onAlpha, addVoxelButton); - toolBar.setAlpha(offAlpha, deleteVoxelButton); } return true; } if (deleteVoxelButton === toolBar.clicked(clickedOverlay)) { - if (deletingVoxels) { - deletingVoxels = false; - addingVoxels = false; - toolBar.setAlpha(offAlpha, addVoxelButton); - toolBar.setAlpha(offAlpha, deleteVoxelButton); - } else { + var wasDeletingVoxels = deletingVoxels; + disableAllButtons() + if (!wasDeletingVoxels) { deletingVoxels = true; - addingVoxels = false; - toolBar.setAlpha(offAlpha, addVoxelButton); toolBar.setAlpha(onAlpha, deleteVoxelButton); } return true; } + if (addSphereButton === toolBar.clicked(clickedOverlay)) { + var wasAddingSpheres = addingSpheres + disableAllButtons() + if (!wasAddingSpheres) { + addingSpheres = true; + toolBar.setAlpha(onAlpha, addSphereButton); + } + return true; + } + + if (deleteSphereButton === toolBar.clicked(clickedOverlay)) { + var wasDeletingSpheres = deletingSpheres; + disableAllButtons() + if (!wasDeletingSpheres) { + deletingSpheres = true; + toolBar.setAlpha(onAlpha, deleteSphereButton); + } + return true; + } + + if (addTerrainButton === toolBar.clicked(clickedOverlay)) { addTerrainBlock(); return true; @@ -202,14 +252,15 @@ function addTerrainBlock() { }); Entities.setAllVoxels(polyVoxId, 255); - // XXX use setCuboid - for (var y = 16; y < 32; y++) { - for (var x = 0; x < 16; x++) { - for (var z = 0; z < 16; z++) { - Entities.setVoxel(polyVoxId, {x:x, y:y, z:z}, 0); - } - } - } + // for (var y = 16; y < 32; y++) { + // for (var x = 0; x < 16; x++) { + // for (var z = 0; z < 16; z++) { + // Entities.setVoxel(polyVoxId, {x:x, y:y, z:z}, 0); + // } + // } + // } + Entities.setVoxelsInCuboid(polyVoxId, {x:0, y:16, z:0}, {x:16, y:16, z:16}, 0); + ////////// // stitch together the terrain with x/y/z NeighorID properties @@ -271,7 +322,7 @@ function attemptVoxelChange(pickRayDir, intersection) { return false; } - if (addingVoxels == false && deletingVoxels == false) { + if (addingVoxels == false && deletingVoxels == false && addingSpheres == false && deletingSpheres == false) { return false; } @@ -281,10 +332,23 @@ function attemptVoxelChange(pickRayDir, intersection) { var doAdd = addingVoxels; var doDelete = deletingVoxels; + var doAddSphere = addingSpheres; + var doDeleteSphere = deletingSpheres; if (controlHeld) { - doAdd = deletingVoxels; - doDelete = addingVoxels; + if (doAdd) { + doAdd = false; + doDelete = true; + } else if (doDelete) { + doDelete = false; + doAdd = true; + } else if (doAddSphere) { + doAddSphere = false; + doDeleteSphere = true; + } else if (doDeleteSphere) { + doDeleteSphere = false; + doAddSphere = true; + } } if (doDelete) { @@ -295,6 +359,14 @@ function attemptVoxelChange(pickRayDir, intersection) { var toDrawPosition = Vec3.subtract(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); return Entities.setVoxel(intersection.entityID, floorVector(toDrawPosition), 255); } + if (doDeleteSphere) { + var toErasePosition = intersection.intersection; + return Entities.setVoxelSphere(intersection.entityID, floorVector(toErasePosition), editSphereRadius, 0); + } + if (doAddSphere) { + var toDrawPosition = intersection.intersection; + return Entities.setVoxelSphere(intersection.entityID, floorVector(toDrawPosition), editSphereRadius, 255); + } } function mousePressEvent(event) { From 7369ca19e9874498da5e27776547c1d34530e5e3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 31 Aug 2015 18:01:15 -0700 Subject: [PATCH 07/23] allow setting cuboid voxel spaces. clean up some locking --- .../src/RenderablePolyVoxEntityItem.cpp | 59 +++++++++++++++---- .../src/RenderablePolyVoxEntityItem.h | 1 + .../entities/src/EntityScriptingInterface.cpp | 7 +++ .../entities/src/EntityScriptingInterface.h | 2 + libraries/entities/src/PolyVoxEntityItem.cpp | 18 ++++-- libraries/entities/src/PolyVoxEntityItem.h | 3 +- 6 files changed, 70 insertions(+), 20 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 7d7607860d..2a7b3fe299 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -201,6 +201,37 @@ bool RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { } +bool RenderablePolyVoxEntityItem::setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) { + bool result = false; + if (_locked) { + return result; + } + + int xLow = std::max(std::min((int)roundf(lowPosition.x), (int)roundf(_voxelVolumeSize.x) - 1), 0); + int yLow = std::max(std::min((int)roundf(lowPosition.y), (int)roundf(_voxelVolumeSize.y) - 1), 0); + int zLow = std::max(std::min((int)roundf(lowPosition.z), (int)roundf(_voxelVolumeSize.z) - 1), 0); + int xHigh = std::max(std::min(xLow + (int)roundf(cuboidSize.x), (int)roundf(_voxelVolumeSize.x)), xLow); + int yHigh = std::max(std::min(yLow + (int)roundf(cuboidSize.y), (int)roundf(_voxelVolumeSize.y)), yLow); + int zHigh = std::max(std::min(zLow + (int)roundf(cuboidSize.z), (int)roundf(_voxelVolumeSize.z)), zLow); + + _volDataLock.lockForWrite(); + _volDataDirty = true; + + for (int x = xLow; x < xHigh; x++) { + for (int y = yLow; y < yHigh; y++) { + for (int z = zLow; z < zHigh; z++) { + result |= setVoxelInternal(x, y, z, toValue); + } + } + } + _volDataLock.unlock(); + if (result) { + compressVolumeDataAndSendEditPacket(); + } + return result; +} + + bool RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t toValue) { if (_locked) { @@ -408,9 +439,8 @@ bool RenderablePolyVoxEntityItem::isReadyToComputeShape() { } void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { - _shapeInfoLock.lockForRead(); + QReadLocker(&this->_shapeInfoLock); info = _shapeInfo; - _shapeInfoLock.unlock(); } void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) { @@ -643,10 +673,8 @@ bool RenderablePolyVoxEntityItem::inUserBounds(const PolyVox::SimpleVolume_volDataLock); + return getVoxelInternal(x, y, z); } @@ -903,10 +931,10 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { if (currentXNeighbor) { auto polyVoxXNeighbor = std::dynamic_pointer_cast(currentXNeighbor); - if (polyVoxXNeighbor->_volData->getEnclosingRegion() == _volData->getEnclosingRegion()) { + if (polyVoxXNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { for (int y = 0; y < _volData->getHeight(); y++) { for (int z = 0; z < _volData->getDepth(); z++) { - uint8_t neighborValue = polyVoxXNeighbor->_volData->getVoxelAt(1, y, z); + uint8_t neighborValue = polyVoxXNeighbor->getVoxel(0, y, z); _volData->setVoxelAt(_volData->getWidth() - 1, y, z, neighborValue); } } @@ -915,10 +943,10 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { if (currentYNeighbor) { auto polyVoxYNeighbor = std::dynamic_pointer_cast(currentYNeighbor); - if (polyVoxYNeighbor->_volData->getEnclosingRegion() == _volData->getEnclosingRegion()) { + if (polyVoxYNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { for (int x = 0; x < _volData->getWidth(); x++) { for (int z = 0; z < _volData->getDepth(); z++) { - uint8_t neighborValue = polyVoxYNeighbor->_volData->getVoxelAt(x, 1, z); + uint8_t neighborValue = polyVoxYNeighbor->getVoxel(x, 0, z); _volData->setVoxelAt(x, _volData->getWidth() - 1, z, neighborValue); } } @@ -927,10 +955,10 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { if (currentZNeighbor) { auto polyVoxZNeighbor = std::dynamic_pointer_cast(currentZNeighbor); - if (polyVoxZNeighbor->_volData->getEnclosingRegion() == _volData->getEnclosingRegion()) { + if (polyVoxZNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { for (int x = 0; x < _volData->getWidth(); x++) { for (int y = 0; y < _volData->getHeight(); y++) { - uint8_t neighborValue = polyVoxZNeighbor->_volData->getVoxelAt(x, y, 1); + uint8_t neighborValue = polyVoxZNeighbor->getVoxel(x, y, 0); _volData->setVoxelAt(x, y, _volData->getDepth() - 1, neighborValue); } } @@ -951,12 +979,17 @@ void RenderablePolyVoxEntityItem::getMeshAsync() { model::MeshPointer mesh(new model::Mesh()); cacheNeighbors(); - copyUpperEdgesFromNeighbors(); // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; _volDataLock.lockForRead(); + if (!_volData) { + _volDataLock.unlock(); + return; + } + copyUpperEdgesFromNeighbors(); + switch (_voxelSurfaceStyle) { case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: { PolyVox::MarchingCubesSurfaceExtractor> surfaceExtractor diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index fa203f5e4d..98d2b0665d 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -93,6 +93,7 @@ public: // coords are in world-space virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue); virtual bool setAll(uint8_t toValue); + virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue); virtual void setXTextureURL(QString xTextureURL); virtual void setYTextureURL(QString yTextureURL); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index fee2055bd0..b337c05776 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -493,6 +493,13 @@ bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) { }); } +bool EntityScriptingInterface::setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition, + const glm::vec3& cuboidSize, int value) { + return setVoxels(entityID, [lowPosition, cuboidSize, value](PolyVoxEntityItem& polyVoxEntity) { + return polyVoxEntity.setCuboid(lowPosition, cuboidSize, value); + }); +} + bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector& points) { EntityItemPointer entity = static_cast(_entityTree->findEntityByEntityItemID(entityID)); if (!entity) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index a51ebfb61c..ff693e4585 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -122,6 +122,8 @@ public slots: Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, 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, + const glm::vec3& cuboidSize, int value); Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 0ce71a37ad..0da66e962b 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -12,6 +12,7 @@ #include #include +#include #include @@ -62,6 +63,8 @@ PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const Ent } void PolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) { + QWriteLocker(&this->_voxelDataLock); + assert((int)_voxelVolumeSize.x == _voxelVolumeSize.x); assert((int)_voxelVolumeSize.y == _voxelVolumeSize.y); assert((int)_voxelVolumeSize.z == _voxelVolumeSize.z); @@ -95,6 +98,12 @@ void PolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) { } } +const glm::vec3& PolyVoxEntityItem::getVoxelVolumeSize() const { + QWriteLocker locker(&this->_voxelDataLock); + return _voxelVolumeSize; +} + + EntityItemProperties PolyVoxEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelVolumeSize, getVoxelVolumeSize); @@ -200,15 +209,12 @@ void PolyVoxEntityItem::debugDump() const { } void PolyVoxEntityItem::setVoxelData(QByteArray voxelData) { - _voxelDataLock.lockForWrite(); + QWriteLocker(&this->_voxelDataLock); _voxelData = voxelData; _voxelDataDirty = true; - _voxelDataLock.unlock(); } const QByteArray PolyVoxEntityItem::getVoxelData() const { - _voxelDataLock.lockForRead(); - auto result = _voxelData; - _voxelDataLock.unlock(); - return result; + QReadLocker(&this->_voxelDataLock); + return _voxelData; } diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 886a9c37c7..55118f9017 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -50,7 +50,7 @@ class PolyVoxEntityItem : public EntityItem { virtual void debugDump() const; virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize); - virtual const glm::vec3& getVoxelVolumeSize() const { return _voxelVolumeSize; } + virtual const glm::vec3& getVoxelVolumeSize() const; virtual void setVoxelData(QByteArray voxelData); virtual const QByteArray getVoxelData() const; @@ -85,6 +85,7 @@ class PolyVoxEntityItem : public EntityItem { // coords are in world-space virtual bool setSphere(glm::vec3 center, float radius, 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; } virtual uint8_t getVoxel(int x, int y, int z) { return 0; } virtual bool setVoxel(int x, int y, int z, uint8_t toValue) { return false; } From 4cbfe96b7081fabcc9ba4532cd1b58db101e5db7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 31 Aug 2015 18:16:32 -0700 Subject: [PATCH 08/23] allow a sphere set/clear to affect more than one polyvox at a time --- examples/voxels.js | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 3fbdb4b6e6..114e9bc5dd 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -17,7 +17,7 @@ var deletingSpheres = false; var offAlpha = 0.5; var onAlpha = 0.9; -var editSphereRadius = 3.0; +var editSphereRadius = 2.5; function floorVector(v) { return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)}; @@ -250,15 +250,8 @@ function addTerrainBlock() { yTextureURL: "http://headache.hungry.com/~seth/hifi/grass.png", zTextureURL: "http://headache.hungry.com/~seth/hifi/dirt.jpeg" }); - Entities.setAllVoxels(polyVoxId, 255); - // for (var y = 16; y < 32; y++) { - // for (var x = 0; x < 16; x++) { - // for (var z = 0; z < 16; z++) { - // Entities.setVoxel(polyVoxId, {x:x, y:y, z:z}, 0); - // } - // } - // } + Entities.setAllVoxels(polyVoxId, 255); Entities.setVoxelsInCuboid(polyVoxId, {x:0, y:16, z:0}, {x:16, y:16, z:16}, 0); @@ -315,9 +308,9 @@ function addTerrainBlock() { } -function attemptVoxelChange(pickRayDir, intersection) { +function attemptVoxelChangeForEntity(entityID, pickRayDir, intersectionLocation) { - var properties = Entities.getEntityProperties(intersection.entityID); + var properties = Entities.getEntityProperties(entityID); if (properties.type != "PolyVox") { return false; } @@ -326,8 +319,8 @@ function attemptVoxelChange(pickRayDir, intersection) { return false; } - var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection); - var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir); + var voxelPosition = Entities.worldCoordsToVoxelCoords(entityID, intersectionLocation); + var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(entityID, pickRayDir); pickRayDirInVoxelSpace = Vec3.normalize(pickRayDirInVoxelSpace); var doAdd = addingVoxels; @@ -353,22 +346,34 @@ function attemptVoxelChange(pickRayDir, intersection) { if (doDelete) { var toErasePosition = Vec3.sum(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); - return Entities.setVoxel(intersection.entityID, floorVector(toErasePosition), 0); + return Entities.setVoxel(entityID, floorVector(toErasePosition), 0); } if (doAdd) { var toDrawPosition = Vec3.subtract(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); - return Entities.setVoxel(intersection.entityID, floorVector(toDrawPosition), 255); + return Entities.setVoxel(entityID, floorVector(toDrawPosition), 255); } if (doDeleteSphere) { - var toErasePosition = intersection.intersection; - return Entities.setVoxelSphere(intersection.entityID, floorVector(toErasePosition), editSphereRadius, 0); + var toErasePosition = intersectionLocation; + return Entities.setVoxelSphere(entityID, floorVector(toErasePosition), editSphereRadius, 0); } if (doAddSphere) { - var toDrawPosition = intersection.intersection; - return Entities.setVoxelSphere(intersection.entityID, floorVector(toDrawPosition), editSphereRadius, 255); + var toDrawPosition = intersectionLocation; + return Entities.setVoxelSphere(entityID, floorVector(toDrawPosition), editSphereRadius, 255); } } + +function attemptVoxelChange(pickRayDir, intersection) { + var ids = Entities.findEntities(intersection.intersection, editSphereRadius + 1.0); + var success = false; + for (var i = 0; i < ids.length; i++) { + var entityID = ids[i]; + success |= attemptVoxelChangeForEntity(entityID, pickRayDir, intersection.intersection) + } + return success; +} + + function mousePressEvent(event) { if (!event.isLeftButton) { return; From ca1602e443755c5ec467d2c54b4083101ba69f31 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Sep 2015 11:09:46 -0700 Subject: [PATCH 09/23] if avatar is already standing on a terrain-polyvox, try creating a new one where they are facing --- examples/voxels.js | 75 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 114e9bc5dd..9537d821fb 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -17,14 +17,14 @@ var deletingSpheres = false; var offAlpha = 0.5; var onAlpha = 0.9; -var editSphereRadius = 2.5; +var editSphereRadius = 4; function floorVector(v) { return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)}; } function vectorToString(v){ - return "{" + v.x + ", " + v.x + ", " + v.x + "}"; + return "{" + v.x + ", " + v.y + ", " + v.z + "}"; } var toolBar = (function () { @@ -228,6 +228,19 @@ function lookupTerrainForLocation(pos) { } +function grabLowestJointY() { + var jointNames = MyAvatar.getJointNames(); + var floorY = MyAvatar.position.y; + for (var jointName in jointNames) { + if (MyAvatar.getJointPosition(jointNames[jointName]).y < floorY) { + floorY = MyAvatar.getJointPosition(jointNames[jointName]).y; + } + } + return floorY; +} + + + function addTerrainBlock() { var baseLocation = getTerrainAlignedLocation(Vec3.sum(MyAvatar.position, {x:8, y:8, z:8})); if (baseLocation.y > MyAvatar.position.y) { @@ -236,23 +249,41 @@ function addTerrainBlock() { var alreadyThere = lookupTerrainForLocation(baseLocation); if (alreadyThere) { - return; + // there is already a terrain block under MyAvatar. + // try in front of the avatar. + print("alreadyThere = " + alreadyThere); + print("MyAvatar.position = " + vectorToString(MyAvatar.position)); + print("baseLocation = " + vectorToString(baseLocation)); + facingPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(8.0, Quat.getFront(Camera.getOrientation()))); + facingPosition = Vec3.sum(facingPosition, {x:8, y:8, z:8}); + print("facingPosition = " + vectorToString(facingPosition)); + baseLocation = getTerrainAlignedLocation(facingPosition); + print("baseLocation = " + vectorToString(baseLocation)); + alreadyThere = lookupTerrainForLocation(baseLocation); + print("alreadyThere = " + alreadyThere); + if (alreadyThere) { + return; + } } - var polyVoxId = Entities.addEntity({ + var polyVoxID = Entities.addEntity({ type: "PolyVox", name: "terrain", position: baseLocation, dimensions: { x:16, y:16, z:16 }, - voxelVolumeSize: {x:16, y:32, z:16}, + voxelVolumeSize: {x:16, y:64, z:16}, voxelSurfaceStyle: 0, xTextureURL: "http://headache.hungry.com/~seth/hifi/dirt.jpeg", yTextureURL: "http://headache.hungry.com/~seth/hifi/grass.png", zTextureURL: "http://headache.hungry.com/~seth/hifi/dirt.jpeg" }); - Entities.setAllVoxels(polyVoxId, 255); - Entities.setVoxelsInCuboid(polyVoxId, {x:0, y:16, z:0}, {x:16, y:16, z:16}, 0); + var AvatarPositionInVoxelCoords = Entities.worldCoordsToVoxelCoords(polyVoxID, MyAvatar.position); + // TODO -- how to find the avatar's feet? + var topY = Math.round(AvatarPositionInVoxelCoords.y) - 4; + // Entities.setAllVoxels(polyVoxID, 255); + // Entities.setVoxelsInCuboid(polyVoxID, {x:0, y:topY, z:0}, {x:16, y:64 - topY, z:16}, 0); + Entities.setVoxelsInCuboid(polyVoxID, {x:0, y:0, z:0}, {x:16, y:topY, z:16}, 255); ////////// @@ -263,21 +294,21 @@ function addTerrainBlock() { imXNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:-16, y:0, z:0})); if (imXNeighborFor) { var properties = Entities.getEntityProperties(imXNeighborFor); - properties.xNeighborID = polyVoxId; + properties.xNeighborID = polyVoxID; Entities.editEntity(imXNeighborFor, properties); } imYNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:-16, z:0})); if (imYNeighborFor) { var properties = Entities.getEntityProperties(imYNeighborFor); - properties.yNeighborID = polyVoxId; + properties.yNeighborID = polyVoxID; Entities.editEntity(imYNeighborFor, properties); } imZNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:-16})); if (imZNeighborFor) { var properties = Entities.getEntityProperties(imZNeighborFor); - properties.zNeighborID = polyVoxId; + properties.zNeighborID = polyVoxID; Entities.editEntity(imZNeighborFor, properties); } @@ -285,23 +316,23 @@ function addTerrainBlock() { // link this plot to plots which are higher on the axes xNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:16, y:0, z:0})); if (xNeighborFor) { - var properties = Entities.getEntityProperties(polyVoxId); + var properties = Entities.getEntityProperties(polyVoxID); properties.xNeighborID = xNeighborFor; - Entities.editEntity(polyVoxId, properties); + Entities.editEntity(polyVoxID, properties); } yNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:16, z:0})); if (yNeighborFor) { - var properties = Entities.getEntityProperties(polyVoxId); + var properties = Entities.getEntityProperties(polyVoxID); properties.yNeighborID = yNeighborFor; - Entities.editEntity(polyVoxId, properties); + Entities.editEntity(polyVoxID, properties); } zNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:16})); if (zNeighborFor) { - var properties = Entities.getEntityProperties(polyVoxId); + var properties = Entities.getEntityProperties(polyVoxID); properties.zNeighborID = zNeighborFor; - Entities.editEntity(polyVoxId, properties); + Entities.editEntity(polyVoxID, properties); } return true; @@ -364,7 +395,17 @@ function attemptVoxelChangeForEntity(entityID, pickRayDir, intersectionLocation) function attemptVoxelChange(pickRayDir, intersection) { - var ids = Entities.findEntities(intersection.intersection, editSphereRadius + 1.0); + + var ids; + + if (addingSpheres || deletingSpheres) { + ids = Entities.findEntities(intersection.intersection, editSphereRadius + 1.0); + } else { + ids = [intersection.entityID]; + } + + print("ids = " + ids); + var success = false; for (var i = 0; i < ids.length; i++) { var entityID = ids[i]; From 930c5cefc909e954b44c8604f8c919dff3a14fba Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Sep 2015 11:10:21 -0700 Subject: [PATCH 10/23] fix setSphere to create a world-space sphere rather than a voxel-space one --- .../src/RenderablePolyVoxEntityItem.cpp | 54 ++++++++++++++++--- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 2a7b3fe299..5d3af51ddc 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -250,7 +250,6 @@ bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi // This three-level for loop iterates over every voxel in the volume _volDataLock.lockForWrite(); - _volDataDirty = true; for (int z = 0; z < _voxelVolumeSize.z; z++) { for (int y = 0; y < _voxelVolumeSize.y; y++) { for (int x = 0; x < _voxelVolumeSize.x; x++) { @@ -265,20 +264,59 @@ bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi } } } - _volDataLock.unlock(); + if (result) { + _volDataDirty = true; + _volDataLock.unlock(); compressVolumeDataAndSendEditPacket(); + } else { + _volDataLock.unlock(); } return result; } bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) { - // glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords); - glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f); - glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units - float scaleY = scale.y; - float radiusVoxelCoords = radiusWorldCoords / scaleY; - return setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue); + // // glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords); + // glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f); + // glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units + // float scaleY = scale.y; + // float radiusVoxelCoords = radiusWorldCoords / scaleY; + // return setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue); + + bool result = false; + if (_locked) { + return result; + } + + glm::mat4 vtwMatrix = voxelToWorldMatrix(); + + // This three-level for loop iterates over every voxel in the volume + _volDataLock.lockForWrite(); + for (int z = 0; z < _voxelVolumeSize.z; z++) { + for (int y = 0; y < _voxelVolumeSize.y; y++) { + for (int x = 0; x < _voxelVolumeSize.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); + } + } + } + } + + if (result) { + _volDataDirty = true; + _volDataLock.unlock(); + compressVolumeDataAndSendEditPacket(); + } else { + _volDataLock.unlock(); + } + return result; } class RaycastFunctor From 264d39aa9ba7e19dc37d89e0796a511b61ba502c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Sep 2015 14:49:17 -0700 Subject: [PATCH 11/23] have knitted polyvoxes keep track of low-axis neighbors as well as high --- .../src/RenderablePolyVoxEntityItem.cpp | 97 ++++++++++++------- .../src/RenderablePolyVoxEntityItem.h | 11 ++- .../entities/src/EntityItemProperties.cpp | 66 +++++++++---- libraries/entities/src/EntityItemProperties.h | 18 ++-- libraries/entities/src/EntityPropertyFlags.h | 9 +- libraries/entities/src/PolyVoxEntityItem.cpp | 45 ++++++--- libraries/entities/src/PolyVoxEntityItem.h | 38 +++++--- 7 files changed, 190 insertions(+), 94 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 5d3af51ddc..1944398cf6 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -915,24 +915,44 @@ void RenderablePolyVoxEntityItem::getMesh() { void RenderablePolyVoxEntityItem::clearOutOfDateNeighbors() { - if (_xNeighborID != UNKNOWN_ENTITY_ID) { - EntityItemPointer currentXNeighbor = _xNeighbor.lock(); - if (currentXNeighbor && currentXNeighbor->getID() != _xNeighborID) { - _xNeighbor.reset(); + if (_xNNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentXNNeighbor = _xNNeighbor.lock(); + if (currentXNNeighbor && currentXNNeighbor->getID() != _xNNeighborID) { + _xNNeighbor.reset(); } } - if (_yNeighborID != UNKNOWN_ENTITY_ID) { - EntityItemPointer currentYNeighbor = _yNeighbor.lock(); - if (currentYNeighbor && currentYNeighbor->getID() != _yNeighborID) { - _yNeighbor.reset(); + if (_yNNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentYNNeighbor = _yNNeighbor.lock(); + if (currentYNNeighbor && currentYNNeighbor->getID() != _yNNeighborID) { + _yNNeighbor.reset(); } } - if (_zNeighborID != UNKNOWN_ENTITY_ID) { - EntityItemPointer currentZNeighbor = _zNeighbor.lock(); - if (currentZNeighbor && currentZNeighbor->getID() != _zNeighborID) { - _zNeighbor.reset(); + if (_zNNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentZNNeighbor = _zNNeighbor.lock(); + if (currentZNNeighbor && currentZNNeighbor->getID() != _zNNeighborID) { + _zNNeighbor.reset(); } } + + if (_xPNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentXPNeighbor = _xPNeighbor.lock(); + if (currentXPNeighbor && currentXPNeighbor->getID() != _xPNeighborID) { + _xPNeighbor.reset(); + } + } + if (_yPNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentYPNeighbor = _yPNeighbor.lock(); + if (currentYPNeighbor && currentYPNeighbor->getID() != _yPNeighborID) { + _yPNeighbor.reset(); + } + } + if (_zPNeighborID != UNKNOWN_ENTITY_ID) { + EntityItemPointer currentZPNeighbor = _zPNeighbor.lock(); + if (currentZPNeighbor && currentZPNeighbor->getID() != _zPNeighborID) { + _zPNeighbor.reset(); + } + } + } void RenderablePolyVoxEntityItem::cacheNeighbors() { @@ -947,15 +967,26 @@ void RenderablePolyVoxEntityItem::cacheNeighbors() { return; } - if (_xNeighborID != UNKNOWN_ENTITY_ID && _xNeighbor.expired()) { - _xNeighbor = tree->findEntityByID(_xNeighborID); + if (_xPNeighborID != UNKNOWN_ENTITY_ID && _xPNeighbor.expired()) { + _xPNeighbor = tree->findEntityByID(_xPNeighborID); } - if (_yNeighborID != UNKNOWN_ENTITY_ID && _yNeighbor.expired()) { - _yNeighbor = tree->findEntityByID(_yNeighborID); + if (_yPNeighborID != UNKNOWN_ENTITY_ID && _yPNeighbor.expired()) { + _yPNeighbor = tree->findEntityByID(_yPNeighborID); } - if (_zNeighborID != UNKNOWN_ENTITY_ID && _zNeighbor.expired()) { - _zNeighbor = tree->findEntityByID(_zNeighborID); + if (_zPNeighborID != UNKNOWN_ENTITY_ID && _zPNeighbor.expired()) { + _zPNeighbor = tree->findEntityByID(_zPNeighborID); } + + if (_xPNeighborID != UNKNOWN_ENTITY_ID && _xPNeighbor.expired()) { + _xPNeighbor = tree->findEntityByID(_xPNeighborID); + } + if (_yPNeighborID != UNKNOWN_ENTITY_ID && _yPNeighbor.expired()) { + _yPNeighbor = tree->findEntityByID(_yPNeighborID); + } + if (_zPNeighborID != UNKNOWN_ENTITY_ID && _zPNeighbor.expired()) { + _zPNeighbor = tree->findEntityByID(_zPNeighborID); + } + } void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { @@ -963,40 +994,40 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { return; } - EntityItemPointer currentXNeighbor = _xNeighbor.lock(); - EntityItemPointer currentYNeighbor = _yNeighbor.lock(); - EntityItemPointer currentZNeighbor = _zNeighbor.lock(); + EntityItemPointer currentXPNeighbor = _xPNeighbor.lock(); + EntityItemPointer currentYPNeighbor = _yPNeighbor.lock(); + EntityItemPointer currentZPNeighbor = _zPNeighbor.lock(); - if (currentXNeighbor) { - auto polyVoxXNeighbor = std::dynamic_pointer_cast(currentXNeighbor); - if (polyVoxXNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { + if (currentXPNeighbor) { + auto polyVoxXPNeighbor = std::dynamic_pointer_cast(currentXPNeighbor); + if (polyVoxXPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { for (int y = 0; y < _volData->getHeight(); y++) { for (int z = 0; z < _volData->getDepth(); z++) { - uint8_t neighborValue = polyVoxXNeighbor->getVoxel(0, y, z); + uint8_t neighborValue = polyVoxXPNeighbor->getVoxel(0, y, z); _volData->setVoxelAt(_volData->getWidth() - 1, y, z, neighborValue); } } } } - if (currentYNeighbor) { - auto polyVoxYNeighbor = std::dynamic_pointer_cast(currentYNeighbor); - if (polyVoxYNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { + if (currentYPNeighbor) { + auto polyVoxYPNeighbor = std::dynamic_pointer_cast(currentYPNeighbor); + if (polyVoxYPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { for (int x = 0; x < _volData->getWidth(); x++) { for (int z = 0; z < _volData->getDepth(); z++) { - uint8_t neighborValue = polyVoxYNeighbor->getVoxel(x, 0, z); + uint8_t neighborValue = polyVoxYPNeighbor->getVoxel(x, 0, z); _volData->setVoxelAt(x, _volData->getWidth() - 1, z, neighborValue); } } } } - if (currentZNeighbor) { - auto polyVoxZNeighbor = std::dynamic_pointer_cast(currentZNeighbor); - if (polyVoxZNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { + if (currentZPNeighbor) { + auto polyVoxZPNeighbor = std::dynamic_pointer_cast(currentZPNeighbor); + if (polyVoxZPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { for (int x = 0; x < _volData->getWidth(); x++) { for (int y = 0; y < _volData->getHeight(); y++) { - uint8_t neighborValue = polyVoxZNeighbor->getVoxel(x, y, 0); + uint8_t neighborValue = polyVoxZPNeighbor->getVoxel(x, y, 0); _volData->setVoxelAt(x, y, _volData->getDepth() - 1, neighborValue); } } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 98d2b0665d..8e42884051 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -149,10 +149,13 @@ private: QSemaphore _threadRunning{1}; - // these are cached lookups of _xNeighborID, _yNeighborID, _zNeighborID - EntityItemWeakPointer _xNeighbor; - EntityItemWeakPointer _yNeighbor; - EntityItemWeakPointer _zNeighbor; + // these are cached lookups of _xNNeighborID, _yNNeighborID, _zNNeighborID, _xPNeighborID, _yPNeighborID, _zPNeighborID + EntityItemWeakPointer _xNNeighbor; // neighor found by going along negative X axis + EntityItemWeakPointer _yNNeighbor; + EntityItemWeakPointer _zNNeighbor; + EntityItemWeakPointer _xPNeighbor; // neighor found by going along positive X axis + EntityItemWeakPointer _yPNeighbor; + EntityItemWeakPointer _zPNeighbor; void clearOutOfDateNeighbors(); void cacheNeighbors(); void copyUpperEdgesFromNeighbors(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 199defbcb1..89284b2123 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -109,9 +109,12 @@ CONSTRUCT_PROPERTY(strokeWidths, QVector()), CONSTRUCT_PROPERTY(xTextureURL, ""), CONSTRUCT_PROPERTY(yTextureURL, ""), CONSTRUCT_PROPERTY(zTextureURL, ""), -CONSTRUCT_PROPERTY(xNeighborID, UNKNOWN_ENTITY_ID), -CONSTRUCT_PROPERTY(yNeighborID, UNKNOWN_ENTITY_ID), -CONSTRUCT_PROPERTY(zNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(xNNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(yNNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(zNNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(xPNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(yPNeighborID, UNKNOWN_ENTITY_ID), +CONSTRUCT_PROPERTY(zPNeighborID, UNKNOWN_ENTITY_ID), _id(UNKNOWN_ENTITY_ID), @@ -381,9 +384,12 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_X_TEXTURE_URL, xTextureURL); CHECK_PROPERTY_CHANGE(PROP_Y_TEXTURE_URL, yTextureURL); CHECK_PROPERTY_CHANGE(PROP_Z_TEXTURE_URL, zTextureURL); - CHECK_PROPERTY_CHANGE(PROP_X_NEIGHBOR_ID, xNeighborID); - CHECK_PROPERTY_CHANGE(PROP_Y_NEIGHBOR_ID, yNeighborID); - CHECK_PROPERTY_CHANGE(PROP_Z_NEIGHBOR_ID, zNeighborID); + CHECK_PROPERTY_CHANGE(PROP_X_N_NEIGHBOR_ID, xNNeighborID); + CHECK_PROPERTY_CHANGE(PROP_Y_N_NEIGHBOR_ID, yNNeighborID); + CHECK_PROPERTY_CHANGE(PROP_Z_N_NEIGHBOR_ID, zNNeighborID); + CHECK_PROPERTY_CHANGE(PROP_X_P_NEIGHBOR_ID, xPNeighborID); + CHECK_PROPERTY_CHANGE(PROP_Y_P_NEIGHBOR_ID, yPNeighborID); + CHECK_PROPERTY_CHANGE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID); changedProperties += _stage.getChangedProperties(); changedProperties += _atmosphere.getChangedProperties(); @@ -528,9 +534,13 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(yTextureURL); COPY_PROPERTY_TO_QSCRIPTVALUE(zTextureURL); - COPY_PROPERTY_TO_QSCRIPTVALUE(xNeighborID); - COPY_PROPERTY_TO_QSCRIPTVALUE(yNeighborID); - COPY_PROPERTY_TO_QSCRIPTVALUE(zNeighborID); + COPY_PROPERTY_TO_QSCRIPTVALUE(xNNeighborID); + COPY_PROPERTY_TO_QSCRIPTVALUE(yNNeighborID); + COPY_PROPERTY_TO_QSCRIPTVALUE(zNNeighborID); + + COPY_PROPERTY_TO_QSCRIPTVALUE(xPNeighborID); + COPY_PROPERTY_TO_QSCRIPTVALUE(yPNeighborID); + COPY_PROPERTY_TO_QSCRIPTVALUE(zPNeighborID); return properties; } @@ -631,9 +641,13 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(yTextureURL, QString, setYTextureURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(zTextureURL, QString, setZTextureURL); - COPY_PROPERTY_FROM_QSCRIPTVALUE(xNeighborID, EntityItemID, setXNeighborID); - COPY_PROPERTY_FROM_QSCRIPTVALUE(yNeighborID, EntityItemID, setYNeighborID); - COPY_PROPERTY_FROM_QSCRIPTVALUE(zNeighborID, EntityItemID, setZNeighborID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(xNNeighborID, EntityItemID, setXNNeighborID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(yNNeighborID, EntityItemID, setYNNeighborID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(zNNeighborID, EntityItemID, setZNNeighborID); + + COPY_PROPERTY_FROM_QSCRIPTVALUE(xPNeighborID, EntityItemID, setXPNeighborID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(yPNeighborID, EntityItemID, setYPNeighborID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(zPNeighborID, EntityItemID, setZPNeighborID); _lastEdited = usecTimestampNow(); } @@ -867,9 +881,12 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent APPEND_ENTITY_PROPERTY(PROP_X_TEXTURE_URL, properties.getXTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Y_TEXTURE_URL, properties.getYTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Z_TEXTURE_URL, properties.getZTextureURL()); - APPEND_ENTITY_PROPERTY(PROP_X_NEIGHBOR_ID, properties.getXNeighborID()); - APPEND_ENTITY_PROPERTY(PROP_Y_NEIGHBOR_ID, properties.getYNeighborID()); - APPEND_ENTITY_PROPERTY(PROP_Z_NEIGHBOR_ID, properties.getZNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_X_N_NEIGHBOR_ID, properties.getXNNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Y_N_NEIGHBOR_ID, properties.getYNNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Z_N_NEIGHBOR_ID, properties.getZNNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_X_P_NEIGHBOR_ID, properties.getXPNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Y_P_NEIGHBOR_ID, properties.getYPNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Z_P_NEIGHBOR_ID, properties.getZPNeighborID()); } if (properties.getType() == EntityTypes::Line) { @@ -1133,9 +1150,12 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_X_TEXTURE_URL, QString, setXTextureURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Y_TEXTURE_URL, QString, setYTextureURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Z_TEXTURE_URL, QString, setZTextureURL); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_X_NEIGHBOR_ID, EntityItemID, setXNeighborID); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Y_NEIGHBOR_ID, EntityItemID, setYNeighborID); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Z_NEIGHBOR_ID, EntityItemID, setZNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_X_N_NEIGHBOR_ID, EntityItemID, setXNNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Y_N_NEIGHBOR_ID, EntityItemID, setYNNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Z_N_NEIGHBOR_ID, EntityItemID, setZNNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_X_P_NEIGHBOR_ID, EntityItemID, setXPNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Y_P_NEIGHBOR_ID, EntityItemID, setYPNeighborID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_Z_P_NEIGHBOR_ID, EntityItemID, setZPNeighborID); } if (properties.getType() == EntityTypes::Line) { @@ -1277,9 +1297,13 @@ void EntityItemProperties::markAllChanged() { _yTextureURLChanged = true; _zTextureURLChanged = true; - _xNeighborIDChanged = true; - _yNeighborIDChanged = true; - _zNeighborIDChanged = true; + _xNNeighborIDChanged = true; + _yNNeighborIDChanged = true; + _zNNeighborIDChanged = true; + + _xPNeighborIDChanged = true; + _yPNeighborIDChanged = true; + _zPNeighborIDChanged = true; } /// The maximum bounding cube for the entity, independent of it's rotation. diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 0e0c36ad11..942dc3edb1 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -161,9 +161,12 @@ public: DEFINE_PROPERTY_REF(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString); DEFINE_PROPERTY_REF(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString); DEFINE_PROPERTY_REF(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString); - DEFINE_PROPERTY_REF(PROP_X_NEIGHBOR_ID, XNeighborID, xNeighborID, EntityItemID); - DEFINE_PROPERTY_REF(PROP_Y_NEIGHBOR_ID, YNeighborID, yNeighborID, EntityItemID); - DEFINE_PROPERTY_REF(PROP_Z_NEIGHBOR_ID, ZNeighborID, zNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); + DEFINE_PROPERTY_REF(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); static QString getBackgroundModeString(BackgroundMode mode); @@ -330,9 +333,12 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, XTextureURL, xTextureURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, YTextureURL, yTextureURL, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZTextureURL, zTextureURL, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, XNeighborID, xNeighborID, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, YNeighborID, yNeighborID, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZNeighborID, zNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, XNNeighborID, xNNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, YNNeighborID, yNNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZNNeighborID, zNNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, XPNeighborID, xPNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, YPNeighborID, yPNeighborID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ZPNeighborID, zPNeighborID, ""); properties.getStage().debugDump(); properties.getAtmosphere().debugDump(); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 9ad34fa69d..d929bdbef5 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -139,9 +139,12 @@ enum EntityPropertyList { PROP_VELOCITY_SPREAD, PROP_ACCELERATION_SPREAD, - PROP_X_NEIGHBOR_ID, // used by PolyVox - PROP_Y_NEIGHBOR_ID, // used by PolyVox - PROP_Z_NEIGHBOR_ID, // used by PolyVox + PROP_X_N_NEIGHBOR_ID, // used by PolyVox + PROP_Y_N_NEIGHBOR_ID, // used by PolyVox + PROP_Z_N_NEIGHBOR_ID, // used by PolyVox + PROP_X_P_NEIGHBOR_ID, // used by PolyVox + PROP_Y_P_NEIGHBOR_ID, // used by PolyVox + PROP_Z_P_NEIGHBOR_ID, // used by PolyVox //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 0da66e962b..6c53dbfa16 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -112,9 +112,12 @@ EntityItemProperties PolyVoxEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(xTextureURL, getXTextureURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(yTextureURL, getYTextureURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(zTextureURL, getZTextureURL); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(xNeighborID, getXNeighborID); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(yNeighborID, getYNeighborID); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(zNeighborID, getZNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(xNNeighborID, getXNNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(yNNeighborID, getYNNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(zNNeighborID, getZNNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(xPNeighborID, getXPNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(yPNeighborID, getYPNeighborID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(zPNeighborID, getZPNeighborID); return properties; } @@ -127,9 +130,12 @@ bool PolyVoxEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(xTextureURL, setXTextureURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(yTextureURL, setYTextureURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(zTextureURL, setZTextureURL); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(xNeighborID, setXNeighborID); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(yNeighborID, setYNeighborID); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(zNeighborID, setZNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(xNNeighborID, setXNNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(yNNeighborID, setYNNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(zNNeighborID, setZNNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(xPNeighborID, setXPNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(yPNeighborID, setYPNeighborID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(zPNeighborID, setZPNeighborID); if (somethingChanged) { bool wantDebug = false; @@ -157,9 +163,12 @@ int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* dat READ_ENTITY_PROPERTY(PROP_X_TEXTURE_URL, QString, setXTextureURL); READ_ENTITY_PROPERTY(PROP_Y_TEXTURE_URL, QString, setYTextureURL); READ_ENTITY_PROPERTY(PROP_Z_TEXTURE_URL, QString, setZTextureURL); - READ_ENTITY_PROPERTY(PROP_X_NEIGHBOR_ID, EntityItemID, setXNeighborID); - READ_ENTITY_PROPERTY(PROP_Y_NEIGHBOR_ID, EntityItemID, setYNeighborID); - READ_ENTITY_PROPERTY(PROP_Z_NEIGHBOR_ID, EntityItemID, setZNeighborID); + READ_ENTITY_PROPERTY(PROP_X_N_NEIGHBOR_ID, EntityItemID, setXNNeighborID); + READ_ENTITY_PROPERTY(PROP_Y_N_NEIGHBOR_ID, EntityItemID, setYNNeighborID); + READ_ENTITY_PROPERTY(PROP_Z_N_NEIGHBOR_ID, EntityItemID, setZNNeighborID); + READ_ENTITY_PROPERTY(PROP_X_P_NEIGHBOR_ID, EntityItemID, setXPNeighborID); + READ_ENTITY_PROPERTY(PROP_Y_P_NEIGHBOR_ID, EntityItemID, setYPNeighborID); + READ_ENTITY_PROPERTY(PROP_Z_P_NEIGHBOR_ID, EntityItemID, setZPNeighborID); return bytesRead; } @@ -174,9 +183,12 @@ EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams requestedProperties += PROP_X_TEXTURE_URL; requestedProperties += PROP_Y_TEXTURE_URL; requestedProperties += PROP_Z_TEXTURE_URL; - requestedProperties += PROP_X_NEIGHBOR_ID; - requestedProperties += PROP_Y_NEIGHBOR_ID; - requestedProperties += PROP_Z_NEIGHBOR_ID; + requestedProperties += PROP_X_N_NEIGHBOR_ID; + requestedProperties += PROP_Y_N_NEIGHBOR_ID; + requestedProperties += PROP_Z_N_NEIGHBOR_ID; + requestedProperties += PROP_X_P_NEIGHBOR_ID; + requestedProperties += PROP_Y_P_NEIGHBOR_ID; + requestedProperties += PROP_Z_P_NEIGHBOR_ID; return requestedProperties; } @@ -195,9 +207,12 @@ void PolyVoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeB APPEND_ENTITY_PROPERTY(PROP_X_TEXTURE_URL, getXTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Y_TEXTURE_URL, getYTextureURL()); APPEND_ENTITY_PROPERTY(PROP_Z_TEXTURE_URL, getZTextureURL()); - APPEND_ENTITY_PROPERTY(PROP_X_NEIGHBOR_ID, getXNeighborID()); - APPEND_ENTITY_PROPERTY(PROP_Y_NEIGHBOR_ID, getYNeighborID()); - APPEND_ENTITY_PROPERTY(PROP_Z_NEIGHBOR_ID, getZNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_X_N_NEIGHBOR_ID, getXNNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Y_N_NEIGHBOR_ID, getYNNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Z_N_NEIGHBOR_ID, getZNNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_X_P_NEIGHBOR_ID, getXPNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Y_P_NEIGHBOR_ID, getYPNeighborID()); + APPEND_ENTITY_PROPERTY(PROP_Z_P_NEIGHBOR_ID, getZPNeighborID()); } void PolyVoxEntityItem::debugDump() const { diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 55118f9017..69bfb9323b 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -104,15 +104,25 @@ class PolyVoxEntityItem : public EntityItem { virtual void setZTextureURL(QString zTextureURL) { _zTextureURL = zTextureURL; } virtual const QString& getZTextureURL() const { return _zTextureURL; } - virtual void setXNeighborID(const EntityItemID& xNeighborID) { _xNeighborID = xNeighborID; } - virtual void setXNeighborID(const QString& xNeighborID) { _xNeighborID = QUuid(xNeighborID); } - virtual const EntityItemID& getXNeighborID() const { return _xNeighborID; } - virtual void setYNeighborID(const EntityItemID& yNeighborID) { _yNeighborID = yNeighborID; } - virtual void setYNeighborID(const QString& yNeighborID) { _yNeighborID = QUuid(yNeighborID); } - virtual const EntityItemID& getYNeighborID() const { return _yNeighborID; } - virtual void setZNeighborID(const EntityItemID& zNeighborID) { _zNeighborID = zNeighborID; } - virtual void setZNeighborID(const QString& zNeighborID) { _zNeighborID = QUuid(zNeighborID); } - virtual const EntityItemID& getZNeighborID() const { return _zNeighborID; } + virtual void setXNNeighborID(const EntityItemID& xNNeighborID) { _xNNeighborID = xNNeighborID; } + virtual void setXNNeighborID(const QString& xNNeighborID) { _xNNeighborID = QUuid(xNNeighborID); } + virtual const EntityItemID& getXNNeighborID() const { return _xNNeighborID; } + virtual void setYNNeighborID(const EntityItemID& yNNeighborID) { _yNNeighborID = yNNeighborID; } + virtual void setYNNeighborID(const QString& yNNeighborID) { _yNNeighborID = QUuid(yNNeighborID); } + virtual const EntityItemID& getYNNeighborID() const { return _yNNeighborID; } + virtual void setZNNeighborID(const EntityItemID& zNNeighborID) { _zNNeighborID = zNNeighborID; } + virtual void setZNNeighborID(const QString& zNNeighborID) { _zNNeighborID = QUuid(zNNeighborID); } + virtual const EntityItemID& getZNNeighborID() const { return _zNNeighborID; } + + virtual void setXPNeighborID(const EntityItemID& xPNeighborID) { _xPNeighborID = xPNeighborID; } + virtual void setXPNeighborID(const QString& xPNeighborID) { _xPNeighborID = QUuid(xPNeighborID); } + virtual const EntityItemID& getXPNeighborID() const { return _xPNeighborID; } + virtual void setYPNeighborID(const EntityItemID& yPNeighborID) { _yPNeighborID = yPNeighborID; } + virtual void setYPNeighborID(const QString& yPNeighborID) { _yPNeighborID = QUuid(yPNeighborID); } + virtual const EntityItemID& getYPNeighborID() const { return _yPNeighborID; } + virtual void setZPNeighborID(const EntityItemID& zPNeighborID) { _zPNeighborID = zPNeighborID; } + virtual void setZPNeighborID(const QString& zPNeighborID) { _zPNeighborID = QUuid(zPNeighborID); } + virtual const EntityItemID& getZPNeighborID() const { return _zPNeighborID; } protected: @@ -129,9 +139,13 @@ class PolyVoxEntityItem : public EntityItem { QString _zTextureURL; // for non-edged surface styles, these are used to compute the high-axis edges - EntityItemID _xNeighborID{UNKNOWN_ENTITY_ID}; - EntityItemID _yNeighborID{UNKNOWN_ENTITY_ID}; - EntityItemID _zNeighborID{UNKNOWN_ENTITY_ID}; + EntityItemID _xNNeighborID{UNKNOWN_ENTITY_ID}; + EntityItemID _yNNeighborID{UNKNOWN_ENTITY_ID}; + EntityItemID _zNNeighborID{UNKNOWN_ENTITY_ID}; + + EntityItemID _xPNeighborID{UNKNOWN_ENTITY_ID}; + EntityItemID _yPNeighborID{UNKNOWN_ENTITY_ID}; + EntityItemID _zPNeighborID{UNKNOWN_ENTITY_ID}; }; #endif // hifi_PolyVoxEntityItem_h From 4ab8ac29b90206a1b9cb6ffaa5568213044d00a7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Sep 2015 15:23:47 -0700 Subject: [PATCH 12/23] make terrain a doubly linked list --- examples/voxels.js | 82 +++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 9537d821fb..809b8f95a6 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -290,50 +290,56 @@ function addTerrainBlock() { // stitch together the terrain with x/y/z NeighorID properties ////////// - // link plots which are lower on the axes to this one - imXNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:-16, y:0, z:0})); - if (imXNeighborFor) { - var properties = Entities.getEntityProperties(imXNeighborFor); - properties.xNeighborID = polyVoxID; - Entities.editEntity(imXNeighborFor, properties); + // link neighbors to this plot + imXNNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:16, y:0, z:0})); + imYNNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:16, z:0})); + imZNNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:16})); + imXPNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:-16, y:0, z:0})); + imYPNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:-16, z:0})); + imZPNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:-16})); + + if (imXNNeighborFor) { + var properties = Entities.getEntityProperties(imXNNeighborFor); + properties.xNNeighborID = polyVoxID; + Entities.editEntity(imXNNeighborFor, properties); + } + if (imYNNeighborFor) { + var properties = Entities.getEntityProperties(imYNNeighborFor); + properties.yNNeighborID = polyVoxID; + Entities.editEntity(imYNNeighborFor, properties); + } + if (imZNNeighborFor) { + var properties = Entities.getEntityProperties(imZNNeighborFor); + properties.zNNeighborID = polyVoxID; + Entities.editEntity(imZNNeighborFor, properties); } - imYNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:-16, z:0})); - if (imYNeighborFor) { - var properties = Entities.getEntityProperties(imYNeighborFor); - properties.yNeighborID = polyVoxID; - Entities.editEntity(imYNeighborFor, properties); + if (imXPNeighborFor) { + var properties = Entities.getEntityProperties(imXPNeighborFor); + properties.xPNeighborID = polyVoxID; + Entities.editEntity(imXPNeighborFor, properties); } - - imZNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:-16})); - if (imZNeighborFor) { - var properties = Entities.getEntityProperties(imZNeighborFor); - properties.zNeighborID = polyVoxID; - Entities.editEntity(imZNeighborFor, properties); + if (imYPNeighborFor) { + var properties = Entities.getEntityProperties(imYPNeighborFor); + properties.yPNeighborID = polyVoxID; + Entities.editEntity(imYPNeighborFor, properties); + } + if (imZPNeighborFor) { + var properties = Entities.getEntityProperties(imZPNeighborFor); + properties.zPNeighborID = polyVoxID; + Entities.editEntity(imZPNeighborFor, properties); } - // link this plot to plots which are higher on the axes - xNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:16, y:0, z:0})); - if (xNeighborFor) { - var properties = Entities.getEntityProperties(polyVoxID); - properties.xNeighborID = xNeighborFor; - Entities.editEntity(polyVoxID, properties); - } - - yNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:16, z:0})); - if (yNeighborFor) { - var properties = Entities.getEntityProperties(polyVoxID); - properties.yNeighborID = yNeighborFor; - Entities.editEntity(polyVoxID, properties); - } - - zNeighborFor = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:16})); - if (zNeighborFor) { - var properties = Entities.getEntityProperties(polyVoxID); - properties.zNeighborID = zNeighborFor; - Entities.editEntity(polyVoxID, properties); - } + // link this plot to its neighbors + var properties = Entities.getEntityProperties(polyVoxID); + properties.xNNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:-16, y:0, z:0})); + properties.yNNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:-16, z:0})); + properties.zNNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:-16})); + properties.xPNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:16, y:0, z:0})); + properties.yPNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:16, z:0})); + properties.zPNeighborID = lookupTerrainForLocation(Vec3.sum(baseLocation, {x:0, y:0, z:16})); + Entities.editEntity(polyVoxID, properties); return true; } From 9256917f150b85aa241eab5109de33dcef72340f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Sep 2015 16:21:12 -0700 Subject: [PATCH 13/23] rebake mesh when a neighbor changes --- .../src/RenderablePolyVoxEntityItem.cpp | 60 +++++++++++++++++++ .../src/RenderablePolyVoxEntityItem.h | 10 ++++ libraries/entities/src/PolyVoxEntityItem.h | 13 ++-- 3 files changed, 77 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 1944398cf6..cd150dc44c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -746,6 +746,25 @@ bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t _volData->setVoxelAt(x, y, z, toValue); } + EntityItemPointer currentXNNeighbor = _xNNeighbor.lock(); + EntityItemPointer currentYNNeighbor = _yNNeighbor.lock(); + EntityItemPointer currentZNNeighbor = _zNNeighbor.lock(); + + if (result) { + if (x == 0 && currentXNNeighbor && currentXNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxXNNeighbor = std::dynamic_pointer_cast(currentXNNeighbor); + polyVoxXNNeighbor->rebakeMesh(); + } + if (y == 0 && currentYNNeighbor && currentYNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxYNNeighbor = std::dynamic_pointer_cast(currentYNNeighbor); + polyVoxYNNeighbor->rebakeMesh(); + } + if (z == 0 && currentZNNeighbor && currentZNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxZNNeighbor = std::dynamic_pointer_cast(currentZNNeighbor); + polyVoxZNNeighbor->rebakeMesh(); + } + } + return result; } @@ -1274,3 +1293,44 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorkerAsync() { _threadRunning.release(); return; } + + +void RenderablePolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighborID) { + PolyVoxEntityItem::setXNNeighborID(xNNeighborID); +} + +void RenderablePolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighborID) { + PolyVoxEntityItem::setYNNeighborID(yNNeighborID); +} + +void RenderablePolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighborID) { + PolyVoxEntityItem::setZNNeighborID(zNNeighborID); +} + + +void RenderablePolyVoxEntityItem::setXPNeighborID(const EntityItemID& xPNeighborID) { + if (xPNeighborID != _xPNeighborID) { + PolyVoxEntityItem::setXPNeighborID(xPNeighborID); + rebakeMesh(); + } +} + +void RenderablePolyVoxEntityItem::setYPNeighborID(const EntityItemID& yPNeighborID) { + if (yPNeighborID != _yPNeighborID) { + PolyVoxEntityItem::setYPNeighborID(yPNeighborID); + rebakeMesh(); + } +} + +void RenderablePolyVoxEntityItem::setZPNeighborID(const EntityItemID& zPNeighborID) { + if (zPNeighborID != _zPNeighborID) { + PolyVoxEntityItem::setZPNeighborID(zPNeighborID); + rebakeMesh(); + } +} + + +void RenderablePolyVoxEntityItem::rebakeMesh() { + QReadLocker(&this->_volDataLock); + _volDataDirty = true; +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 8e42884051..ee94310e18 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -106,6 +106,16 @@ public: std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void setXNNeighborID(const EntityItemID& xNNeighborID); + virtual void setYNNeighborID(const EntityItemID& yNNeighborID); + virtual void setZNNeighborID(const EntityItemID& zNNeighborID); + + virtual void setXPNeighborID(const EntityItemID& xPNeighborID); + virtual void setYPNeighborID(const EntityItemID& yPNeighborID); + virtual void setZPNeighborID(const EntityItemID& zPNeighborID); + + virtual void rebakeMesh(); + private: // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize. diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 69bfb9323b..20a0646c9b 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -105,25 +105,26 @@ class PolyVoxEntityItem : public EntityItem { virtual const QString& getZTextureURL() const { return _zTextureURL; } virtual void setXNNeighborID(const EntityItemID& xNNeighborID) { _xNNeighborID = xNNeighborID; } - virtual void setXNNeighborID(const QString& xNNeighborID) { _xNNeighborID = QUuid(xNNeighborID); } + void setXNNeighborID(const QString& xNNeighborID) { setXNNeighborID(QUuid(xNNeighborID)); } virtual const EntityItemID& getXNNeighborID() const { return _xNNeighborID; } virtual void setYNNeighborID(const EntityItemID& yNNeighborID) { _yNNeighborID = yNNeighborID; } - virtual void setYNNeighborID(const QString& yNNeighborID) { _yNNeighborID = QUuid(yNNeighborID); } + void setYNNeighborID(const QString& yNNeighborID) { setYNNeighborID(QUuid(yNNeighborID)); } virtual const EntityItemID& getYNNeighborID() const { return _yNNeighborID; } virtual void setZNNeighborID(const EntityItemID& zNNeighborID) { _zNNeighborID = zNNeighborID; } - virtual void setZNNeighborID(const QString& zNNeighborID) { _zNNeighborID = QUuid(zNNeighborID); } + void setZNNeighborID(const QString& zNNeighborID) { setZNNeighborID(QUuid(zNNeighborID)); } virtual const EntityItemID& getZNNeighborID() const { return _zNNeighborID; } virtual void setXPNeighborID(const EntityItemID& xPNeighborID) { _xPNeighborID = xPNeighborID; } - virtual void setXPNeighborID(const QString& xPNeighborID) { _xPNeighborID = QUuid(xPNeighborID); } + void setXPNeighborID(const QString& xPNeighborID) { setXPNeighborID(QUuid(xPNeighborID)); } virtual const EntityItemID& getXPNeighborID() const { return _xPNeighborID; } virtual void setYPNeighborID(const EntityItemID& yPNeighborID) { _yPNeighborID = yPNeighborID; } - virtual void setYPNeighborID(const QString& yPNeighborID) { _yPNeighborID = QUuid(yPNeighborID); } + void setYPNeighborID(const QString& yPNeighborID) { setYPNeighborID(QUuid(yPNeighborID)); } virtual const EntityItemID& getYPNeighborID() const { return _yPNeighborID; } virtual void setZPNeighborID(const EntityItemID& zPNeighborID) { _zPNeighborID = zPNeighborID; } - virtual void setZPNeighborID(const QString& zPNeighborID) { _zPNeighborID = QUuid(zPNeighborID); } + void setZPNeighborID(const QString& zPNeighborID) { setZPNeighborID(QUuid(zPNeighborID)); } virtual const EntityItemID& getZPNeighborID() const { return _zPNeighborID; } + virtual void rebakeMesh() {}; protected: glm::vec3 _voxelVolumeSize; // this is always 3 bytes From 8608e4f2b0cadcf9e441b21444465026cb38c967 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 1 Sep 2015 16:51:55 -0700 Subject: [PATCH 14/23] small bug-fixes --- examples/voxels.js | 9 ++------- .../src/RenderablePolyVoxEntityItem.cpp | 18 ++++++++---------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 809b8f95a6..00d49ae711 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -404,13 +404,8 @@ function attemptVoxelChange(pickRayDir, intersection) { var ids; - if (addingSpheres || deletingSpheres) { - ids = Entities.findEntities(intersection.intersection, editSphereRadius + 1.0); - } else { - ids = [intersection.entityID]; - } - - print("ids = " + ids); + ids = Entities.findEntities(intersection.intersection, editSphereRadius + 1.0); + // print("ids = " + ids); var success = false; for (var i = 0; i < ids.length; i++) { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index cd150dc44c..9d6648ee04 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -164,6 +164,8 @@ bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) return false; } + cacheNeighbors(); + _volDataLock.lockForWrite(); bool result = setVoxelInternal(x, y, z, toValue); if (result) { @@ -975,10 +977,6 @@ void RenderablePolyVoxEntityItem::clearOutOfDateNeighbors() { } void RenderablePolyVoxEntityItem::cacheNeighbors() { - if (_voxelSurfaceStyle != PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { - return; - } - clearOutOfDateNeighbors(); EntityTreeElement* element = getElement(); EntityTree* tree = element ? element->getTree() : nullptr; @@ -986,14 +984,14 @@ void RenderablePolyVoxEntityItem::cacheNeighbors() { return; } - if (_xPNeighborID != UNKNOWN_ENTITY_ID && _xPNeighbor.expired()) { - _xPNeighbor = tree->findEntityByID(_xPNeighborID); + if (_xNNeighborID != UNKNOWN_ENTITY_ID && _xNNeighbor.expired()) { + _xNNeighbor = tree->findEntityByID(_xNNeighborID); } - if (_yPNeighborID != UNKNOWN_ENTITY_ID && _yPNeighbor.expired()) { - _yPNeighbor = tree->findEntityByID(_yPNeighborID); + if (_yNNeighborID != UNKNOWN_ENTITY_ID && _yNNeighbor.expired()) { + _yNNeighbor = tree->findEntityByID(_yNNeighborID); } - if (_zPNeighborID != UNKNOWN_ENTITY_ID && _zPNeighbor.expired()) { - _zPNeighbor = tree->findEntityByID(_zPNeighborID); + if (_zNNeighborID != UNKNOWN_ENTITY_ID && _zNNeighbor.expired()) { + _zNNeighbor = tree->findEntityByID(_zNNeighborID); } if (_xPNeighborID != UNKNOWN_ENTITY_ID && _xPNeighbor.expired()) { From f54d924f4ab79d1d494db0371ea032c71b863407 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Sep 2015 09:29:51 -0700 Subject: [PATCH 15/23] make sure intersected entity is in the list of possible polyvoxes to adjust --- examples/voxels.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/voxels.js b/examples/voxels.js index 00d49ae711..c5564fe391 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -405,6 +405,10 @@ function attemptVoxelChange(pickRayDir, intersection) { var ids; ids = Entities.findEntities(intersection.intersection, editSphereRadius + 1.0); + if (ids.indexOf(intersection.entityID) < 0) { + ids.push(intersection.entityID); + } + // print("ids = " + ids); var success = false; From 16ee5199e88f3db7679123f51c69cad8fee99c75 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Sep 2015 09:30:32 -0700 Subject: [PATCH 16/23] change how polyvox neighbors are notified of updates --- .../src/RenderablePolyVoxEntityItem.cpp | 82 +++++++++++++------ .../src/RenderablePolyVoxEntityItem.h | 1 + 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 9d6648ee04..6fb5648fe0 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -164,8 +164,6 @@ bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) return false; } - cacheNeighbors(); - _volDataLock.lockForWrite(); bool result = setVoxelInternal(x, y, z, toValue); if (result) { @@ -748,25 +746,6 @@ bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t _volData->setVoxelAt(x, y, z, toValue); } - EntityItemPointer currentXNNeighbor = _xNNeighbor.lock(); - EntityItemPointer currentYNNeighbor = _yNNeighbor.lock(); - EntityItemPointer currentZNNeighbor = _zNNeighbor.lock(); - - if (result) { - if (x == 0 && currentXNNeighbor && currentXNNeighbor->getType() == EntityTypes::PolyVox) { - auto polyVoxXNNeighbor = std::dynamic_pointer_cast(currentXNNeighbor); - polyVoxXNNeighbor->rebakeMesh(); - } - if (y == 0 && currentYNNeighbor && currentYNNeighbor->getType() == EntityTypes::PolyVox) { - auto polyVoxYNNeighbor = std::dynamic_pointer_cast(currentYNNeighbor); - polyVoxYNNeighbor->rebakeMesh(); - } - if (z == 0 && currentZNNeighbor && currentZNNeighbor->getType() == EntityTypes::PolyVox) { - auto polyVoxZNNeighbor = std::dynamic_pointer_cast(currentZNNeighbor); - polyVoxZNNeighbor->rebakeMesh(); - } - } - return result; } @@ -801,6 +780,10 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { } + + + + // take compressed data and expand it into _volData. void RenderablePolyVoxEntityItem::decompressVolumeDataAsync() { _voxelDataLock.lockForRead(); @@ -1136,7 +1119,7 @@ void RenderablePolyVoxEntityItem::getMeshAsync() { _meshLock.unlock(); _volDataDirty = false; _volDataLock.unlock(); - + bonkNeighbors(); _threadRunning.release(); } @@ -1294,15 +1277,42 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorkerAsync() { void RenderablePolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighborID) { - PolyVoxEntityItem::setXNNeighborID(xNNeighborID); + if (xNNeighborID != _xNNeighborID) { + PolyVoxEntityItem::setXNNeighborID(xNNeighborID); + cacheNeighbors(); + EntityItemPointer currentXNNeighbor = _xNNeighbor.lock(); + if (currentXNNeighbor && currentXNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxXNNeighbor = std::dynamic_pointer_cast(currentXNNeighbor); + polyVoxXNNeighbor->setXPNeighborID(_id); + polyVoxXNNeighbor->rebakeMesh(); + } + } } void RenderablePolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighborID) { - PolyVoxEntityItem::setYNNeighborID(yNNeighborID); + if (yNNeighborID != _yNNeighborID) { + PolyVoxEntityItem::setYNNeighborID(yNNeighborID); + cacheNeighbors(); + EntityItemPointer currentYNNeighbor = _yNNeighbor.lock(); + if (currentYNNeighbor && currentYNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxYNNeighbor = std::dynamic_pointer_cast(currentYNNeighbor); + polyVoxYNNeighbor->setYPNeighborID(_id); + polyVoxYNNeighbor->rebakeMesh(); + } + } } void RenderablePolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighborID) { - PolyVoxEntityItem::setZNNeighborID(zNNeighborID); + if (zNNeighborID != _zNNeighborID) { + PolyVoxEntityItem::setZNNeighborID(zNNeighborID); + cacheNeighbors(); + EntityItemPointer currentZNNeighbor = _yNNeighbor.lock(); + if (currentZNNeighbor && currentZNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxZNNeighbor = std::dynamic_pointer_cast(currentZNNeighbor); + polyVoxZNNeighbor->setZPNeighborID(_id); + polyVoxZNNeighbor->rebakeMesh(); + } + } } @@ -1332,3 +1342,25 @@ void RenderablePolyVoxEntityItem::rebakeMesh() { QReadLocker(&this->_volDataLock); _volDataDirty = true; } + +void RenderablePolyVoxEntityItem::bonkNeighbors() { + clearOutOfDateNeighbors(); + cacheNeighbors(); + + EntityItemPointer currentXNNeighbor = _xNNeighbor.lock(); + EntityItemPointer currentYNNeighbor = _yNNeighbor.lock(); + EntityItemPointer currentZNNeighbor = _zNNeighbor.lock(); + + if (currentXNNeighbor && currentXNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxXNNeighbor = std::dynamic_pointer_cast(currentXNNeighbor); + polyVoxXNNeighbor->rebakeMesh(); + } + if (currentYNNeighbor && currentYNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxYNNeighbor = std::dynamic_pointer_cast(currentYNNeighbor); + polyVoxYNNeighbor->rebakeMesh(); + } + if (currentZNNeighbor && currentZNNeighbor->getType() == EntityTypes::PolyVox) { + auto polyVoxZNNeighbor = std::dynamic_pointer_cast(currentZNNeighbor); + polyVoxZNNeighbor->rebakeMesh(); + } +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index ee94310e18..3b10a12bd2 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -169,6 +169,7 @@ private: void clearOutOfDateNeighbors(); void cacheNeighbors(); void copyUpperEdgesFromNeighbors(); + void bonkNeighbors(); }; From 2e880e9aab1e430ad4729ce596d69a7a6b4a1a80 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Sep 2015 16:29:15 -0700 Subject: [PATCH 17/23] change how pick-ray direction is calculated --- examples/voxels.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index c5564fe391..547585198c 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -356,8 +356,9 @@ function attemptVoxelChangeForEntity(entityID, pickRayDir, intersectionLocation) return false; } + var voxelOrigin = Entities.worldCoordsToVoxelCoords(entityID, Vec3.subtract(intersectionLocation, pickRayDir)); var voxelPosition = Entities.worldCoordsToVoxelCoords(entityID, intersectionLocation); - var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(entityID, pickRayDir); + var pickRayDirInVoxelSpace = Vec3.subtract(voxelPosition, voxelOrigin); pickRayDirInVoxelSpace = Vec3.normalize(pickRayDirInVoxelSpace); var doAdd = addingVoxels; @@ -409,8 +410,6 @@ function attemptVoxelChange(pickRayDir, intersection) { ids.push(intersection.entityID); } - // print("ids = " + ids); - var success = false; for (var i = 0; i < ids.length; i++) { var entityID = ids[i]; From 2fe6e9c3179a1fc75923f9b3d4a974162fc3434d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Sep 2015 16:30:11 -0700 Subject: [PATCH 18/23] use AABox's ray intersection code rather than the goofed-up version that was here --- .../src/RenderablePolyVoxEntityItem.cpp | 99 +++++-------------- 1 file changed, 23 insertions(+), 76 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 6fb5648fe0..f393391780 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -276,13 +276,6 @@ bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi } bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) { - // // glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords); - // glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f); - // glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units - // float scaleY = scale.y; - // float radiusVoxelCoords = radiusWorldCoords / scaleY; - // return setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue); - bool result = false; if (_locked) { return result; @@ -371,7 +364,6 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o glm::mat4 wtvMatrix = worldToVoxelMatrix(); glm::mat4 vtwMatrix = voxelToWorldMatrix(); - glm::mat4 vtlMatrix = voxelToLocalMatrix(); glm::vec3 normDirection = glm::normalize(direction); // the PolyVox ray intersection code requires a near and far point. @@ -379,67 +371,33 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o float distanceToEntity = glm::distance(origin, getPosition()); float largestDimension = glm::max(getDimensions().x, getDimensions().y, getDimensions().z) * 2.0f; glm::vec3 farPoint = origin + normDirection * (distanceToEntity + largestDimension); + glm::vec4 originInVoxel = wtvMatrix * glm::vec4(origin, 1.0f); glm::vec4 farInVoxel = wtvMatrix * glm::vec4(farPoint, 1.0f); - glm::vec4 result; + glm::vec4 directionInVoxel = glm::normalize(farInVoxel - originInVoxel); + + glm::vec4 result = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f); PolyVox::RaycastResult raycastResult = doRayCast(originInVoxel, farInVoxel, result); if (raycastResult == PolyVox::RaycastResults::Completed) { // the ray completed its path -- nothing was hit. return false; } - // set up ray tests against each face of the voxel. - glm::vec3 minXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.0f, 0.5f, 0.5f, 0.0f))); - glm::vec3 maxXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(1.0f, 0.5f, 0.5f, 0.0f))); - glm::vec3 minYPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.0f, 0.5f, 0.0f))); - glm::vec3 maxYPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 1.0f, 0.5f, 0.0f))); - glm::vec3 minZPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.5f, 0.0f, 0.0f))); - glm::vec3 maxZPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.5f, 1.0f, 0.0f))); + glm::vec3 result3 = vec3(result); - glm::vec4 baseDimensions = glm::vec4(1.0, 1.0, 1.0, 0.0); - glm::vec3 worldDimensions = glm::vec3(vtlMatrix * baseDimensions); - glm::vec2 xDimensions = glm::vec2(worldDimensions.z, worldDimensions.y); - glm::vec2 yDimensions = glm::vec2(worldDimensions.x, worldDimensions.z); - glm::vec2 zDimensions = glm::vec2(worldDimensions.x, worldDimensions.y); + AABox voxelBox; + voxelBox += result3 + glm::vec3(-0.5f, -0.5f, -0.5f); + voxelBox += result3 + glm::vec3(0.5f, 0.5f, 0.5f); - glm::quat vtwRotation = extractRotation(vtwMatrix); - glm::quat minXRotation = vtwRotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); - glm::quat maxXRotation = vtwRotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); - glm::quat minYRotation = vtwRotation * glm::quat(glm::vec3(PI_OVER_TWO, 0.0f, 0.0f)); - glm::quat maxYRotation = vtwRotation * glm::quat(glm::vec3(PI_OVER_TWO, 0.0f, 0.0f)); - glm::quat minZRotation = vtwRotation * glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); - glm::quat maxZRotation = vtwRotation * glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + float voxelDistance; - float bestDx = FLT_MAX; - bool hit[ 6 ]; - float dx[ 6 ] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX}; + bool hit = voxelBox.findRayIntersection(glm::vec3(originInVoxel), glm::vec3(directionInVoxel), voxelDistance, face); - hit[0] = findRayRectangleIntersection(origin, direction, minXRotation, minXPosition, xDimensions, dx[0]); - hit[1] = findRayRectangleIntersection(origin, direction, maxXRotation, maxXPosition, xDimensions, dx[1]); - hit[2] = findRayRectangleIntersection(origin, direction, minYRotation, minYPosition, yDimensions, dx[2]); - hit[3] = findRayRectangleIntersection(origin, direction, maxYRotation, maxYPosition, yDimensions, dx[3]); - hit[4] = findRayRectangleIntersection(origin, direction, minZRotation, minZPosition, zDimensions, dx[4]); - hit[5] = findRayRectangleIntersection(origin, direction, maxZRotation, maxZPosition, zDimensions, dx[5]); - - bool ok = false; - for (int i = 0; i < 6; i ++) { - if (hit[ i ] && dx[ i ] < bestDx) { - face = (BoxFace)i; - distance = dx[ i ]; - ok = true; - bestDx = dx[ i ]; - } - } - - if (!ok) { - // if the attempt to put the ray against one of the voxel-faces fails, just return the center - glm::vec4 intersectedWorldPosition = vtwMatrix * (result + vec4(0.5f, 0.5f, 0.5f, 0.0f)); - distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); - face = BoxFace::MIN_X_FACE; - } - - return true; + glm::vec4 voxelIntersectionPoint = glm::vec4(glm::vec3(originInVoxel) + glm::vec3(directionInVoxel) * voxelDistance, 1.0); + glm::vec4 intersectionPoint = vtwMatrix * voxelIntersectionPoint; + distance = glm::distance(origin, glm::vec3(intersectionPoint)); + return hit; } @@ -455,7 +413,7 @@ PolyVox::RaycastResult RenderablePolyVoxEntityItem::doRayCast(glm::vec4 originIn _volDataLock.unlock(); // result is in voxel-space coordinates. - result = callback._result - glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); + result = callback._result; return raycastResult; } @@ -629,7 +587,13 @@ namespace render { glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const { - return glm::vec3(voxelToWorldMatrix() * glm::vec4(voxelCoords, 1.0f)); + glm::vec3 adjustedCoords; + if (isEdged(_voxelSurfaceStyle)) { + adjustedCoords = voxelCoords + glm::vec3(0.5f, 0.5f, 0.5f); + } else { + adjustedCoords = voxelCoords - glm::vec3(0.5f, 0.5f, 0.5f); + } + return glm::vec3(voxelToWorldMatrix() * glm::vec4(adjustedCoords, 1.0f)); } glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3& worldCoords) const { @@ -773,17 +737,11 @@ bool RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toV return false; } - void RenderablePolyVoxEntityItem::decompressVolumeData() { _threadRunning.acquire(); QtConcurrent::run(this, &RenderablePolyVoxEntityItem::decompressVolumeDataAsync); } - - - - - // take compressed data and expand it into _volData. void RenderablePolyVoxEntityItem::decompressVolumeDataAsync() { _voxelDataLock.lockForRead(); @@ -844,7 +802,6 @@ void RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacket() { QtConcurrent::run(this, &RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacketAsync); } - // 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::compressVolumeDataAndSendEditPacketAsync() { @@ -917,7 +874,6 @@ void RenderablePolyVoxEntityItem::getMesh() { QtConcurrent::run(this, &RenderablePolyVoxEntityItem::getMeshAsync); } - void RenderablePolyVoxEntityItem::clearOutOfDateNeighbors() { if (_xNNeighborID != UNKNOWN_ENTITY_ID) { EntityItemPointer currentXNNeighbor = _xNNeighbor.lock(); @@ -1035,15 +991,6 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { } } - -// PolyVox::Region shrinkRegion(PolyVox::Region originalRegion) { -// PolyVox::Region smallerRegion = originalRegion; -// smallerRegion.shiftLowerCorner(PolyVox::Vector3DInt32(1, 1, 1)); -// smallerRegion.shiftUpperCorner(PolyVox::Vector3DInt32(-1, -1, -1)); -// return smallerRegion; -// } - - void RenderablePolyVoxEntityItem::getMeshAsync() { model::MeshPointer mesh(new model::Mesh()); @@ -1136,7 +1083,7 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorkerAsync() { if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_MARCHING_CUBES || _voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES) { - /* pull each triangle in the mesh into a polyhedron which can be collided with */ + // pull each triangle in the mesh into a polyhedron which can be collided with unsigned int i = 0; _meshLock.lockForRead(); From 07b241c778cceec658add5aaeb0e10846463ca27 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 3 Sep 2015 11:05:44 -0700 Subject: [PATCH 19/23] code review --- examples/voxels.js | 13 +------------ .../src/RenderablePolyVoxEntityItem.cpp | 16 ++++++++-------- .../src/RenderablePolyVoxEntityItem.h | 2 +- libraries/shared/src/GLMHelpers.cpp | 1 + libraries/shared/src/GLMHelpers.h | 1 + 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 547585198c..0776bce627 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -3,6 +3,7 @@ var shiftHeld = false; Script.include([ "libraries/toolBars.js", + "libraries/utils.js", ]); var isActive = false; @@ -23,10 +24,6 @@ function floorVector(v) { return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)}; } -function vectorToString(v){ - return "{" + v.x + ", " + v.y + ", " + v.z + "}"; -} - var toolBar = (function () { var that = {}, toolBar, @@ -251,16 +248,10 @@ function addTerrainBlock() { if (alreadyThere) { // there is already a terrain block under MyAvatar. // try in front of the avatar. - print("alreadyThere = " + alreadyThere); - print("MyAvatar.position = " + vectorToString(MyAvatar.position)); - print("baseLocation = " + vectorToString(baseLocation)); facingPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(8.0, Quat.getFront(Camera.getOrientation()))); facingPosition = Vec3.sum(facingPosition, {x:8, y:8, z:8}); - print("facingPosition = " + vectorToString(facingPosition)); baseLocation = getTerrainAlignedLocation(facingPosition); - print("baseLocation = " + vectorToString(baseLocation)); alreadyThere = lookupTerrainForLocation(baseLocation); - print("alreadyThere = " + alreadyThere); if (alreadyThere) { return; } @@ -281,8 +272,6 @@ function addTerrainBlock() { var AvatarPositionInVoxelCoords = Entities.worldCoordsToVoxelCoords(polyVoxID, MyAvatar.position); // TODO -- how to find the avatar's feet? var topY = Math.round(AvatarPositionInVoxelCoords.y) - 4; - // Entities.setAllVoxels(polyVoxID, 255); - // Entities.setVoxelsInCuboid(polyVoxID, {x:0, y:topY, z:0}, {x:16, y:64 - topY, z:16}, 0); Entities.setVoxelsInCuboid(polyVoxID, {x:0, y:0, z:0}, {x:16, y:topY, z:16}, 255); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index f393391780..43f97c23ee 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -136,7 +136,7 @@ glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { glm::vec3 center = getCenterPosition(); glm::vec3 position = getPosition(); glm::vec3 positionToCenter = center - position; - positionToCenter -= getDimensions() * glm::vec3(0.5f, 0.5f, 0.5f) - getSurfacePositionAdjustment(); + positionToCenter -= getDimensions() * Vectors::HALF - getSurfacePositionAdjustment(); glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter); glm::mat4 scaled = glm::scale(centerToCorner, scale); return scaled; @@ -387,8 +387,8 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o glm::vec3 result3 = vec3(result); AABox voxelBox; - voxelBox += result3 + glm::vec3(-0.5f, -0.5f, -0.5f); - voxelBox += result3 + glm::vec3(0.5f, 0.5f, 0.5f); + voxelBox += result3 - Vectors::HALF; + voxelBox += result3 + Vectors::HALF; float voxelDistance; @@ -589,9 +589,9 @@ namespace render { glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const { glm::vec3 adjustedCoords; if (isEdged(_voxelSurfaceStyle)) { - adjustedCoords = voxelCoords + glm::vec3(0.5f, 0.5f, 0.5f); + adjustedCoords = voxelCoords + Vectors::HALF; } else { - adjustedCoords = voxelCoords - glm::vec3(0.5f, 0.5f, 0.5f); + adjustedCoords = voxelCoords - Vectors::HALF; } return glm::vec3(voxelToWorldMatrix() * glm::vec4(adjustedCoords, 1.0f)); } @@ -599,9 +599,9 @@ glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3& voxel glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3& worldCoords) const { glm::vec3 result = glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f)); if (isEdged(_voxelSurfaceStyle)) { - return result - glm::vec3(0.5f, 0.5f, 0.5f); + return result - Vectors::HALF; } - return result + glm::vec3(0.5f, 0.5f, 0.5f); + return result + Vectors::HALF; } glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const { @@ -656,7 +656,7 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) bool RenderablePolyVoxEntityItem::inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, - int x, int y, int z) { + int x, int y, int z) const { // x, y, z are in user voxel-coords, not adjusted-for-edge voxel-coords. if (isEdged(surfaceStyle)) { if (x < 0 || y < 0 || z < 0 || diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 3b10a12bd2..01578b5e58 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -141,7 +141,7 @@ private: int _onCount; // how many non-zero voxels are in _volData bool inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, - int x, int y, int z); + int x, int y, int z) const; uint8_t getVoxelInternal(int x, int y, int z); bool setVoxelInternal(int x, int y, int z, uint8_t toValue); bool updateOnCount(int x, int y, int z, uint8_t toValue); diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 4ca8ed330b..ead08f5654 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -27,6 +27,7 @@ const vec3 Vectors::MAX{ FLT_MAX }; const vec3 Vectors::MIN{ -FLT_MAX }; const vec3 Vectors::ZERO{ 0.0f }; const vec3 Vectors::ONE{ 1.0f }; +const vec3 Vectors::HALF{ 0.5f }; const vec3& Vectors::RIGHT = Vectors::UNIT_X; const vec3& Vectors::UP = Vectors::UNIT_Y; const vec3& Vectors::FRONT = Vectors::UNIT_NEG_Z; diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 4b03ed2525..e05e075e5d 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -70,6 +70,7 @@ public: static const vec3 MIN; static const vec3 ZERO; static const vec3 ONE; + static const vec3 HALF; static const vec3& RIGHT; static const vec3& UP; static const vec3& FRONT; From 16dfc39f5f7fb6351dba84b39feaaf97beb9cd48 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 3 Sep 2015 18:22:35 -0700 Subject: [PATCH 20/23] fix collision shape of avatars --- interface/src/avatar/SkeletonModel.cpp | 13 +++----- libraries/fbx/src/FBXReader.cpp | 44 ++++++++++---------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 35536eabd1..181816ed5f 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -547,14 +547,11 @@ void SkeletonModel::computeBoundingShape() { // compute the default transform of this joint const JointState& state = _rig->getJointState(i); - // HACK WORKAROUND: ignore joints that may have bad translation (e.g. have been flagged as such with zero radius) - if (state.getBoneRadius() > 0.0f) { - // Each joint contributes a sphere at its position - glm::vec3 axis(state.getBoneRadius()); - glm::vec3 jointPosition = state.getPosition(); - totalExtents.addPoint(jointPosition + axis); - totalExtents.addPoint(jointPosition - axis); - } + // Each joint contributes a sphere at its position + glm::vec3 axis(state.getBoneRadius()); + glm::vec3 jointPosition = state.getPosition(); + totalExtents.addPoint(jointPosition + axis); + totalExtents.addPoint(jointPosition - axis); } // compute bounding shape parameters diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 6d83a87a1c..de28aee4c8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -2557,6 +2557,7 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping int maxJointIndex = firstFBXCluster.jointIndex; glm::mat4 inverseModelTransform = glm::inverse(modelTransform); if (clusterIDs.size() > 1) { + // this is a multi-mesh joint extracted.mesh.clusterIndices.resize(extracted.mesh.vertices.size()); extracted.mesh.clusterWeights.resize(extracted.mesh.vertices.size()); float maxWeight = 0.0f; @@ -2640,6 +2641,7 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping } } } else { + // this is a single-mesh joint int jointIndex = maxJointIndex; FBXJoint& joint = geometry.joints[jointIndex]; JointShapeInfo& jointShapeInfo = jointShapeInfos[jointIndex]; @@ -2660,6 +2662,7 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping } float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix); + // compute average vertex glm::vec3 averageVertex(0.0f); foreach (const glm::vec3& vertex, extracted.mesh.vertices) { float proj = glm::dot(boneDirection, boneEnd - vertex); @@ -2669,29 +2672,26 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping ++jointShapeInfo.numVertexWeights; averageVertex += vertex; } + + // compute joint's radius int numVertices = extracted.mesh.vertices.size(); jointShapeInfo.numVertices = numVertices; if (numVertices > 0) { + // compute average radius averageVertex /= (float)jointShapeInfo.numVertices; float averageRadius = 0.0f; foreach (const glm::vec3& vertex, extracted.mesh.vertices) { averageRadius += glm::distance(vertex, averageVertex); } - jointShapeInfo.averageRadius = averageRadius * radiusScale / (float)jointShapeInfo.numVertices; + averageRadius *= radiusScale / (float)jointShapeInfo.numVertices; + + // final radius is minimum of average and weighted + float weightedRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights; + jointShapeInfo.averageRadius = glm::min(weightedRadius, averageRadius); } - // BUG: the boneBegin and/or boneEnd are incorrect for meshes that are "connected - // under the bone" without weights. Unfortunately we haven't been able to find it yet. - // Although the the mesh vertices are correct in the model-frame, the joint's transform - // in the same frame is just BAD. - // - // HACK WORKAROUND: prevent these shapes from contributing to the collision capsule by setting - // some key members of jointShapeInfo to zero: - jointShapeInfo.numVertices = 0; + // clear sumVertexWeights (this flags it as a single-mesh joint for later) jointShapeInfo.sumVertexWeights = 0.0f; - jointShapeInfo.numVertexWeights = 0; - jointShapeInfo.boneBegin = glm::vec3(0.0f); - jointShapeInfo.averageRadius = 0.0f; } extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex); @@ -2727,22 +2727,12 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping } if (jointShapeInfo.sumVertexWeights > 0.0f) { + // mutiple meshes contributed to the bone radius and now that all + // contributing meshes are done we can finally compute the boneRadius joint.boneRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights; - } - - // the joint is "capsule-like" if it had ANY mesh vertices successfully projected onto the bone - // AND its boneRadius is not too close to zero - bool collideLikeCapsule = jointShapeInfo.numVertexWeights > 0 - && glm::length(jointShapeInfo.boneBegin) > EPSILON; - - if (!collideLikeCapsule) { - // this joint's mesh did not successfully project onto the bone axis - // so it isn't "capsule-like" and we need to estimate its radius a different way: - // the average radius to the average point. - if (jointShapeInfo.numVertexWeights == 0 - && jointShapeInfo.numVertices > 0) { - joint.boneRadius = jointShapeInfo.averageRadius; - } + } else { + // single-mesh joint + joint.boneRadius = jointShapeInfo.averageRadius; } } geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString()); From 895028134b736f061ddf32e234cf345767ddc59c Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 4 Sep 2015 09:40:09 -0700 Subject: [PATCH 21/23] add breakdance game as entity script that works with hydra grab --- examples/entityScripts/breakdanceEntity.js | 88 +++++++++++++++++++++ examples/entityScripts/detectGrabExample.js | 81 +++++++++++++++++++ examples/toys/breakdanceCore.js | 4 +- examples/toys/breakdanceToy.js | 1 + 4 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 examples/entityScripts/breakdanceEntity.js create mode 100644 examples/entityScripts/detectGrabExample.js diff --git a/examples/entityScripts/breakdanceEntity.js b/examples/entityScripts/breakdanceEntity.js new file mode 100644 index 0000000000..77980c0d13 --- /dev/null +++ b/examples/entityScripts/breakdanceEntity.js @@ -0,0 +1,88 @@ +// +// breakdanceEntity.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 9/3/15. +// Copyright 2015 High Fidelity, Inc. +// +// This is an example of an entity script which when assigned to an entity, will start the breakdance game if you grab and hold the entity +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + Script.include("../toys/breakdanceCore.js"); + Script.include("../libraries/utils.js"); + + var _this; + + // this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember + // our this object, so we can access it in cases where we're called without a this (like in the case of various global signals) + BreakdanceEntity = function() { + _this = this; + print("BreakdanceEntity constructor"); + }; + + BreakdanceEntity.prototype = { + + // update() will be called regulary, because we've hooked the update signal in our preload() function + // we will check out userData for the grabData. In the case of the hydraGrab script, it will tell us + // if we're currently being grabbed and if the person grabbing us is the current interfaces avatar. + // we will watch this for state changes and print out if we're being grabbed or released when it changes. + update: function() { + var GRAB_USER_DATA_KEY = "grabKey"; + + // because the update() signal doesn't have a valid this, we need to use our memorized _this to access our entityID + var entityID = _this.entityID; + + // we want to assume that if there is no grab data, then we are not being grabbed + var defaultGrabData = { activated: false, avatarId: null }; + + // this handy function getEntityCustomData() is available in utils.js and it will return just the specific section + // of user data we asked for. If it's not available it returns our default data. + var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, defaultGrabData); + + // if the grabData says we're being grabbed, and the owner ID is our session, then we are being grabbed by this interface + if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) { + + if (!_this.beingGrabbed) { + // remember we're being grabbed so we can detect being released + _this.beingGrabbed = true; + breakdanceStart(); + print("I'm was grabbed..."); + } else { + breakdanceUpdate(); + } + + } else if (_this.beingGrabbed) { + + // if we are not being grabbed, and we previously were, then we were just released, remember that + // and print out a message + _this.beingGrabbed = false; + print("I'm was released..."); + breakdanceEnd(); + } + }, + + // preload() will be called when the entity has become visible (or known) to the interface + // it gives us a chance to set our local JavaScript object up. In this case it means: + // * remembering our entityID, so we can access it in cases where we're called without an entityID + // * connecting to the update signal so we can check our grabbed state + preload: function(entityID) { + this.entityID = entityID; + Script.update.connect(this.update); + }, + + // unload() will be called when our entity is no longer available. It may be because we were deleted, + // or because we've left the domain or quit the application. In all cases we want to unhook our connection + // to the update signal + unload: function(entityID) { + Script.update.disconnect(this.update); + }, + + }; + + // entity scripts always need to return a newly constructed object of our type + return new BreakdanceEntity(); +}) diff --git a/examples/entityScripts/detectGrabExample.js b/examples/entityScripts/detectGrabExample.js new file mode 100644 index 0000000000..cdc79e119d --- /dev/null +++ b/examples/entityScripts/detectGrabExample.js @@ -0,0 +1,81 @@ +// +// detectGrabExample.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 9/3/15. +// Copyright 2015 High Fidelity, Inc. +// +// This is an example of an entity script which when assigned to an entity, will detect when the entity is being grabbed by the hydraGrab script +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + Script.include("../libraries/utils.js"); + + var _this; + + // this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember + // our this object, so we can access it in cases where we're called without a this (like in the case of various global signals) + DetectGrabbed = function() { + _this = this; + }; + + DetectGrabbed.prototype = { + + // update() will be called regulary, because we've hooked the update signal in our preload() function + // we will check out userData for the grabData. In the case of the hydraGrab script, it will tell us + // if we're currently being grabbed and if the person grabbing us is the current interfaces avatar. + // we will watch this for state changes and print out if we're being grabbed or released when it changes. + update: function() { + var GRAB_USER_DATA_KEY = "grabKey"; + + // because the update() signal doesn't have a valid this, we need to use our memorized _this to access our entityID + var entityID = _this.entityID; + + // we want to assume that if there is no grab data, then we are not being grabbed + var defaultGrabData = { activated: false, avatarId: null }; + + // this handy function getEntityCustomData() is available in utils.js and it will return just the specific section + // of user data we asked for. If it's not available it returns our default data. + var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, defaultGrabData); + + // if the grabData says we're being grabbed, and the owner ID is our session, then we are being grabbed by this interface + if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) { + + // remember we're being grabbed so we can detect being released + _this.beingGrabbed = true; + + // print out that we're being grabbed + print("I'm being grabbed..."); + + } else if (_this.beingGrabbed) { + + // if we are not being grabbed, and we previously were, then we were just released, remember that + // and print out a message + _this.beingGrabbed = false; + print("I'm was released..."); + } + }, + + // preload() will be called when the entity has become visible (or known) to the interface + // it gives us a chance to set our local JavaScript object up. In this case it means: + // * remembering our entityID, so we can access it in cases where we're called without an entityID + // * connecting to the update signal so we can check our grabbed state + preload: function(entityID) { + this.entityID = entityID; + Script.update.connect(this.update); + }, + + // unload() will be called when our entity is no longer available. It may be because we were deleted, + // or because we've left the domain or quit the application. In all cases we want to unhook our connection + // to the update signal + unload: function(entityID) { + Script.update.disconnect(this.update); + }, + }; + + // entity scripts always need to return a newly constructed object of our type + return new DetectGrabbed(); +}) diff --git a/examples/toys/breakdanceCore.js b/examples/toys/breakdanceCore.js index 0f346537eb..9bf63850ab 100644 --- a/examples/toys/breakdanceCore.js +++ b/examples/toys/breakdanceCore.js @@ -11,8 +11,6 @@ // -Script.include("../libraries/utils.js"); - function getPositionPuppet() { var DISTANCE_IN_FRONT = 2; var DISTANCE_UP = 0.4; @@ -513,7 +511,7 @@ breakdanceUpdate = function(deltaTime) { } else { Overlays.editOverlay(textOverlay, { text: "pose:" + poses[poseValue].name + "\n" + "animation:" + poses[poseValue].animation }); var props = Entities.getEntityProperties(puppetEntityID); - print("puppetEntityID:" + puppetEntityID + "age:"+props.age); + //print("puppetEntityID:" + puppetEntityID + "age:"+props.age); Entities.editEntity(puppetEntityID, { animationURL: poses[poseValue].animation, lifetime: TEMPORARY_LIFETIME + props.age // renew lifetime diff --git a/examples/toys/breakdanceToy.js b/examples/toys/breakdanceToy.js index 841d5ad111..0190ab74e9 100644 --- a/examples/toys/breakdanceToy.js +++ b/examples/toys/breakdanceToy.js @@ -11,6 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +Script.include("../libraries/utils.js"); Script.include("breakdanceCore.js"); breakdanceStart(); Script.update.connect(breakdanceUpdate); From 1b92ae95d7428bc7e4655aea4acf71fbdb2a6cf4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 4 Sep 2015 09:41:53 -0700 Subject: [PATCH 22/23] put glm:: before vec3 --- libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 43f97c23ee..5ddee32f88 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -384,7 +384,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o return false; } - glm::vec3 result3 = vec3(result); + glm::vec3 result3 = glm::vec3(result); AABox voxelBox; voxelBox += result3 - Vectors::HALF; From 80f2ecbab6cad9310523d5842b681676132d37c7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 4 Sep 2015 09:59:42 -0700 Subject: [PATCH 23/23] Cleaning up some debugging spew and fixing UI HTML paths --- examples/libraries/omniTool/models/wand.js | 3 --- examples/toys/magBalls.js | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/libraries/omniTool/models/wand.js b/examples/libraries/omniTool/models/wand.js index af28afb81c..e14c90b36a 100644 --- a/examples/libraries/omniTool/models/wand.js +++ b/examples/libraries/omniTool/models/wand.js @@ -91,10 +91,7 @@ Wand.prototype.setTipColors = function(color1, color2) { } Wand.prototype.onUpdate = function(deltaTime) { - logDebug("Z4"); - if (this.visible) { - logDebug("5"); var time = new Date().getTime() / 250; var scale1 = Math.abs(Math.sin(time)); var scale2 = Math.abs(Math.cos(time)); diff --git a/examples/toys/magBalls.js b/examples/toys/magBalls.js index 7c11a94e06..e163aa5ffd 100644 --- a/examples/toys/magBalls.js +++ b/examples/toys/magBalls.js @@ -34,7 +34,7 @@ MODE_INFO[BALL_EDIT_MODE_ADD] = { }, colors: [ COLORS.GREEN, COLORS.BLUE ], // FIXME use an http path or find a way to get the relative path to the file - url: "file:///" + Script.resolvePath('../html/magBalls/addMode.html').replace("c:", "C:"), + url: Script.resolvePath('../html/magBalls/addMode.html'), }; MODE_INFO[BALL_EDIT_MODE_DELETE] = { @@ -45,10 +45,9 @@ MODE_INFO[BALL_EDIT_MODE_DELETE] = { }, colors: [ COLORS.RED, COLORS.BLUE ], // FIXME use an http path or find a way to get the relative path to the file - url: "file:///" + Script.resolvePath('../html/magBalls/deleteMode.html').replace("c:", "C:"), + url: Script.resolvePath('../html/magBalls/deleteMode.html'), }; - var UI_POSITION_MODE_LABEL = Vec3.multiply(0.5, Vec3.sum(MODE_INFO[BALL_EDIT_MODE_ADD].uiPosition, MODE_INFO[BALL_EDIT_MODE_DELETE].uiPosition));