From 2b4146125f8da04fac811b2d996bc6f67b1a6521 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 16:27:06 -0700 Subject: [PATCH 01/12] adding logic to check points of line are inside bounds --- .../entities/src/EntityScriptingInterface.cpp | 41 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.h | 4 ++ libraries/entities/src/LineEntityItem.cpp | 3 +- libraries/entities/src/LineEntityItem.h | 2 +- libraries/shared/src/RegisteredMetaTypes.cpp | 10 +++++ libraries/shared/src/RegisteredMetaTypes.h | 1 + 6 files changed, 59 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index a091c786b7..e8de8b723b 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -442,6 +442,40 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID, return true; } +bool EntityScriptingInterface::setPoints(QUuid entityID, std::function actor) { + if (_entityTree) { + return false; + } + + EntityItemPointer entity = static_cast(_entityTree->findEntityByEntityItemID(entityID)); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID; + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::Line) { + return false; + } + + auto now = usecTimestampNow(); + + LineEntityItem* lineEntity = static_cast(entity.get()); + _entityTree->lockForWrite(); + bool success = actor(*lineEntity); + entity->setLastEdited(now); + entity->setLastBroadcast(now); + _entityTree->unlock(); + + _entityTree->lockForRead(); + EntityItemProperties properties = entity->getProperties(); + _entityTree->unlock(); + + properties.setLastEdited(now); + + queueEntityMessage(PacketTypeEntityEdit, entityID, properties); + return success; +} + bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) { return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) { polyVoxEntity.setSphere(center, radius, value); @@ -460,6 +494,13 @@ bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) { }); } +bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector& points) { + return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool + { + return lineEntity.setLinePoints(points); + }); +} + bool EntityScriptingInterface::actionWorker(const QUuid& entityID, std::function actor) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index c6bc43c8c6..17183264b9 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -22,6 +22,7 @@ #include #include #include "PolyVoxEntityItem.h" +#include "LineEntityItem.h" #include "EntityEditPacketSender.h" @@ -121,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 setAllPoints(QUuid entityID, const QVector& points); Q_INVOKABLE void dumpTree() const; @@ -157,6 +160,7 @@ signals: private: bool actionWorker(const QUuid& entityID, std::function actor); bool setVoxels(QUuid entityID, std::function actor); + bool setPoints(QUuid entityID, std::function actor); void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 094536f63a..6bc8c94f2f 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -85,7 +85,7 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } -void LineEntityItem::setLinePoints(const QVector& points) { +bool LineEntityItem::setLinePoints(const QVector& points) { QVector sanitizedPoints; int invalidPoints = 0; for (int i = 0; i < points.size(); i++) { @@ -103,6 +103,7 @@ void LineEntityItem::setLinePoints(const QVector& points) { } _points = sanitizedPoints; _pointsChanged = true; + return true; } int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 5151244b3c..0918dd2d06 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -54,7 +54,7 @@ class LineEntityItem : public EntityItem { void setLineWidth(float lineWidth){ _lineWidth = lineWidth; } float getLineWidth() const{ return _lineWidth; } - void setLinePoints(const QVector& points); + bool setLinePoints(const QVector& points); const QVector& getLinePoints() const{ return _points; } diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 241f835a46..5ad29abc08 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -93,6 +93,16 @@ QVector qVectorVec3FromScriptValue(const QScriptValue& array){ return newVector; } +void qVectorVec3FromScriptValue(const QScriptValue& array, QVector& vector ) { + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + glm::vec3 newVec3 = glm::vec3(); + vec3FromScriptValue(array.property(i), newVec3); + vector << newVec3; + } +} + QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2) { QScriptValue obj = engine->newObject(); obj.setProperty("x", vec2.x); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 1dcc85107a..231878ab3a 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -58,6 +58,7 @@ void qURLFromScriptValue(const QScriptValue& object, QUrl& url); QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); +void qVectorVec3FromScriptValue( const QScriptValue& array, QVector vector); class PickRay { public: From 6a5deaaef127524259cf192a5b4b747d13174784 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 16:54:39 -0700 Subject: [PATCH 02/12] returning true from set line points --- libraries/entities/src/EntityScriptingInterface.cpp | 3 ++- libraries/shared/src/RegisteredMetaTypes.cpp | 2 ++ libraries/shared/src/RegisteredMetaTypes.h | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index e8de8b723b..69b31468d2 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -443,7 +443,7 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID, } bool EntityScriptingInterface::setPoints(QUuid entityID, std::function actor) { - if (_entityTree) { + if (!_entityTree) { return false; } @@ -453,6 +453,7 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::functiongetType(); + if (entityType != EntityTypes::Line) { return false; } diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 5ad29abc08..50f87fe258 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -20,6 +20,7 @@ static int vec4MetaTypeId = qRegisterMetaType(); static int vec3MetaTypeId = qRegisterMetaType(); +static int qVectorVec3MetaTypeId = qRegisterMetaType>(); static int vec2MetaTypeId = qRegisterMetaType(); static int quatMetaTypeId = qRegisterMetaType(); static int xColorMetaTypeId = qRegisterMetaType(); @@ -31,6 +32,7 @@ static int collisionMetaTypeId = qRegisterMetaType(); void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue); qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue); + qScriptRegisterMetaType(engine, qVectorVec3ToScriptValue, qVectorVec3FromScriptValue); qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue); qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue); qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 231878ab3a..2ea2bb52fa 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -57,8 +57,9 @@ QScriptValue qURLToScriptValue(QScriptEngine* engine, const QUrl& url); void qURLFromScriptValue(const QScriptValue& object, QUrl& url); QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorVec3FromScriptValue( const QScriptValue& array, QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); -void qVectorVec3FromScriptValue( const QScriptValue& array, QVector vector); + class PickRay { public: From 8183e7393d6b8ee0baab8d9a5782917a0a5d14c0 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 17:00:27 -0700 Subject: [PATCH 03/12] adding check for points inside bounds' --- libraries/entities/src/LineEntityItem.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 6bc8c94f2f..955e827d92 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -86,22 +86,19 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { } bool LineEntityItem::setLinePoints(const QVector& points) { - QVector sanitizedPoints; int invalidPoints = 0; for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); // Make sure all of our points are valid numbers. // Must be greater than 0 because vector component is set to 0 if it is invalid data. Also should never be greater than TREE_SCALE - if ( (point.x > 0 && point.x < TREE_SCALE) && (point.y > 0 && point.y < TREE_SCALE) && (point.z > 0 && point.z < TREE_SCALE) ) { - sanitizedPoints << point; - } else { - ++invalidPoints; + if ( (point.x <= 0 || point.x >= TREE_SCALE) || (point.y <= 0 || point.y >= TREE_SCALE) || (point.z <= 0 || point.z >= TREE_SCALE) ) { + return false; } } if (invalidPoints > 0) { qDebug() << "Line with" << invalidPoints << "INVALID POINTS"; } - _points = sanitizedPoints; + _points = points; _pointsChanged = true; return true; } From 830a8b69090437baa8f9acc5ae07975007157244 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 18:14:03 -0700 Subject: [PATCH 04/12] checking for bounds and modified paint script to start a new line entity if user paints outside of line entity's bounding box --- examples/paint.js | 70 +++++++++++++---------- libraries/entities/src/LineEntityItem.cpp | 12 ++-- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index c0cc93afc7..384b4916f3 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -13,14 +13,15 @@ // Script.include('lineRider.js') var MAX_POINTS_PER_LINE = 30; -var LINE_LIFETIME = 60 * 5 //5 minute lifetime +var DRAWING_DISTANCE = 5; +var LINE_DIMENSIONS = 5; var colorPalette = [{ red: 236, green: 208, blue: 120 }, { - red: 217, + red: 214, green: 91, blue: 67 }, { @@ -69,7 +70,7 @@ function hydraCheck() { //************ Mouse Paint ************************** function MousePaint() { - var DRAWING_DISTANCE = 2; + var lines = []; var deletedLines = []; var isDrawing = false; @@ -92,7 +93,7 @@ function MousePaint() { var points = []; - var BRUSH_SIZE = 0.02; + var BRUSH_SIZE = .05; var brush = Entities.addEntity({ type: 'Sphere', @@ -111,45 +112,46 @@ function MousePaint() { function newLine(point) { + if (!point) { + return; + } line = Entities.addEntity({ - position: MyAvatar.position, + position: point, type: "Line", color: currentColor, dimensions: { - x: 10, - y: 10, - z: 10 + x: LINE_DIMENSIONS, + y: LINE_DIMENSIONS, + z: LINE_DIMENSIONS }, - lineWidth: LINE_WIDTH, - lifetime: LINE_LIFETIME + lineWidth: LINE_WIDTH }); points = []; - if (point) { - - points.push(point); - path.push(point); - } + points.push(point); + path.push(point); lines.push(line); } function mouseMoveEvent(event) { + var point = computePoint(event) + Entities.editEntity(brush, { + position: point + }); + if (!isDrawing) { return; } - var pickRay = Camera.computePickRay(event.x, event.y); - var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); - var point = Vec3.sum(Camera.getPosition(), addVector); points.push(point); path.push(point); - Entities.editEntity(line, { - linePoints: points - }); - Entities.editEntity(brush, { - position: point - }); + var success = Entities.setAllPoints(line, points); + if (!success) { + //We're out of bounds of entity bounding box, so start a new line + newLine(point) + return; + } if (points.length === MAX_POINTS_PER_LINE) { @@ -158,6 +160,8 @@ function MousePaint() { } } + + function undoStroke() { var deletedLine = lines.pop(); var deletedLineProps = Entities.getEntityProperties(deletedLine); @@ -172,13 +176,14 @@ function MousePaint() { } function mousePressEvent(event) { - if(!event.isLeftButton) { + if (!event.isLeftButton) { isDrawing = false; return; } lineRider.mousePressEvent(event); path = []; - newLine(); + var point = computePoint(event); + newLine(point); isDrawing = true; @@ -198,14 +203,14 @@ function MousePaint() { if (event.text === "z") { undoStroke(); } - if(event.text === "x") { + if (event.text === "x") { redoStroke(); } } function cleanup() { lines.forEach(function(line) { - Entities.deleteEntity(line); + // Entities.deleteEntity(line); }); Entities.deleteEntity(brush); lineRider.cleanup(); @@ -255,6 +260,7 @@ function HydraPaint() { var maxLineWidth = 10; var currentLineWidth = minLineWidth; var MIN_PAINT_TRIGGER_THRESHOLD = .01; + var LINE_LIFETIME = 20; var COLOR_CHANGE_TIME_FACTOR = 0.1; var RIGHT_BUTTON_1 = 7 @@ -331,7 +337,7 @@ function HydraPaint() { z: 10 }, lineWidth: 5, - lifetime: LINE_LIFETIME + // lifetime: LINE_LIFETIME }); this.points = []; if (point) { @@ -482,6 +488,12 @@ function HydraPaint() { } +function computePoint(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); + return Vec3.sum(Camera.getPosition(), addVector); +} + function randFloat(low, high) { return low + Math.random() * (high - low); } diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 955e827d92..0686f64a89 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -86,17 +86,21 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { } bool LineEntityItem::setLinePoints(const QVector& points) { - int invalidPoints = 0; for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); // Make sure all of our points are valid numbers. // Must be greater than 0 because vector component is set to 0 if it is invalid data. Also should never be greater than TREE_SCALE if ( (point.x <= 0 || point.x >= TREE_SCALE) || (point.y <= 0 || point.y >= TREE_SCALE) || (point.z <= 0 || point.z >= TREE_SCALE) ) { + qDebug() << "Point is outside domain bounds"; return false; } - } - if (invalidPoints > 0) { - qDebug() << "Line with" << invalidPoints << "INVALID POINTS"; + glm::vec3 pos = getPosition(); + glm::vec3 halfBox = getDimensions() * 0.5f; + if ( (point.x < pos.x - halfBox.x || point.x > pos.x + halfBox.x) || (point.y < pos.y - halfBox.y || point.y > pos.y + halfBox.y) || (point.z < pos.z - halfBox.z || point.z > pos.z + halfBox.z) ) { + qDebug() << "Point is outside entity's bounding box"; + return false; + } + } _points = points; _pointsChanged = true; From 7293330cedd59d56c3de620d61741adda1647df4 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 18:17:02 -0700 Subject: [PATCH 05/12] fixed indentation and lines delete when user exits to help with large model.svo/json file size --- examples/paint.js | 2 +- libraries/shared/src/RegisteredMetaTypes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index 384b4916f3..c1ea71597b 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -210,7 +210,7 @@ function MousePaint() { function cleanup() { lines.forEach(function(line) { - // Entities.deleteEntity(line); + Entities.deleteEntity(line); }); Entities.deleteEntity(brush); lineRider.cleanup(); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 2ea2bb52fa..0a6795d285 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -57,7 +57,7 @@ QScriptValue qURLToScriptValue(QScriptEngine* engine, const QUrl& url); void qURLFromScriptValue(const QScriptValue& object, QUrl& url); QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); -void qVectorVec3FromScriptValue( const QScriptValue& array, QVector& vector); +void qVectorVec3FromScriptValue(const QScriptValue& array, QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); From 0e177a3e31a5a44b06d5d6791de76426852f0403 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 18 Jun 2015 18:23:09 -0700 Subject: [PATCH 06/12] deleted unnessary line break --- libraries/shared/src/RegisteredMetaTypes.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 0a6795d285..f5f39cd3f6 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -60,7 +60,6 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); QVector qVectorVec3FromScriptValue( const QScriptValue& array); - class PickRay { public: PickRay() : origin(0.0f), direction(0.0f) { } From dbec1aad0c682b098afb38b2820cdb055c9d869f Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 18:54:28 -0700 Subject: [PATCH 07/12] line entity points are now local to entity position. Changed paint script to reflect this --- .../src/RenderableLineEntityItem.cpp | 6 ++--- libraries/entities/src/EntityItemProperties.h | 2 ++ .../entities/src/EntityScriptingInterface.cpp | 10 +++++++ .../entities/src/EntityScriptingInterface.h | 1 + libraries/entities/src/LineEntityItem.cpp | 27 ++++++++++++++----- libraries/entities/src/LineEntityItem.h | 2 ++ 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 65407c74e7..4b94992d59 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -43,9 +43,9 @@ void RenderableLineEntityItem::render(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - // TODO: Figure out clean , efficient way to do relative line positioning. For now we'll just use absolute positioning. - //batch.setModelTransform(getTransformToCenter()); - batch.setModelTransform(Transform()); + Transform transform = Transform(); + transform.setTranslation(getPosition()); + batch.setModelTransform(transform); batch._glLineWidth(getLineWidth()); if (getLinePoints().size() > 1) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 068bc98f7e..5f33da52f8 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -197,6 +197,8 @@ public: QString getSimulatorIDAsString() const { return _simulatorID.toString().mid(1,36).toUpper(); } void setVoxelDataDirty() { _voxelDataChanged = true; } + + void setLinePointsDirty() {_linePointsChanged = true; } void setCreated(QDateTime& v); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 69b31468d2..c9f7378bc8 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -471,8 +471,10 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::functiongetProperties(); _entityTree->unlock(); + properties.setLinePointsDirty(); properties.setLastEdited(now); + queueEntityMessage(PacketTypeEntityEdit, entityID, properties); return success; } @@ -502,6 +504,14 @@ bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector bool + { + return lineEntity.appendPoint(point); + }); + +} + bool EntityScriptingInterface::actionWorker(const QUuid& entityID, std::function actor) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 17183264b9..12c8688816 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -124,6 +124,7 @@ public slots: Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); + Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); Q_INVOKABLE void dumpTree() const; diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 0686f64a89..fccf57c7c7 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -23,6 +23,7 @@ const float LineEntityItem::DEFAULT_LINE_WIDTH = 2.0f; +const int LineEntityItem::MAX_POINTS_PER_LINE = 70; EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -85,18 +86,30 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } +bool LineEntityItem::appendPoint(const glm::vec3& point) { + if (_points.size() > MAX_POINTS_PER_LINE - 1) { + qDebug() << "MAX POINTS REACHED!"; + return false; + } + glm::vec3 halfBox = getDimensions() * 0.5f; + if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { + qDebug() << "Point is outside entity's bounding box"; + return false; + } + _points << point; + _pointsChanged = true; + return true; +} + bool LineEntityItem::setLinePoints(const QVector& points) { + if (points.size() > MAX_POINTS_PER_LINE) { + return false; + } for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); - // Make sure all of our points are valid numbers. - // Must be greater than 0 because vector component is set to 0 if it is invalid data. Also should never be greater than TREE_SCALE - if ( (point.x <= 0 || point.x >= TREE_SCALE) || (point.y <= 0 || point.y >= TREE_SCALE) || (point.z <= 0 || point.z >= TREE_SCALE) ) { - qDebug() << "Point is outside domain bounds"; - return false; - } glm::vec3 pos = getPosition(); glm::vec3 halfBox = getDimensions() * 0.5f; - if ( (point.x < pos.x - halfBox.x || point.x > pos.x + halfBox.x) || (point.y < pos.y - halfBox.y || point.y > pos.y + halfBox.y) || (point.z < pos.z - halfBox.z || point.z > pos.z + halfBox.z) ) { + if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { qDebug() << "Point is outside entity's bounding box"; return false; } diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 0918dd2d06..6d0f00ef04 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -55,6 +55,7 @@ class LineEntityItem : public EntityItem { float getLineWidth() const{ return _lineWidth; } bool setLinePoints(const QVector& points); + bool appendPoint(const glm::vec3& point); const QVector& getLinePoints() const{ return _points; } @@ -68,6 +69,7 @@ class LineEntityItem : public EntityItem { virtual void debugDump() const; static const float DEFAULT_LINE_WIDTH; + static const int MAX_POINTS_PER_LINE; protected: rgbColor _color; From 8bc9fc2e1f9c59edbd65c9d321b380d68f70d966 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 19 Jun 2015 18:58:09 -0700 Subject: [PATCH 08/12] simplified paint.js script to allow for faster iteration and more thorough testing --- examples/paint.js | 383 +++++----------------------------------------- 1 file changed, 40 insertions(+), 343 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index c1ea71597b..ebda5e2e18 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -10,11 +10,9 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -Script.include('lineRider.js') -var MAX_POINTS_PER_LINE = 30; -var DRAWING_DISTANCE = 5; -var LINE_DIMENSIONS = 5; + +var LINE_DIMENSIONS = 1; +var LIFETIME = 6000; var colorPalette = [{ red: 236, @@ -41,15 +39,6 @@ var colorPalette = [{ var currentColorIndex = 0; var currentColor = colorPalette[currentColorIndex]; - - -if (hydraCheck() === true) { - HydraPaint(); -} else { - MousePaint(); -} - - function cycleColor() { currentColor = colorPalette[++currentColorIndex]; if (currentColorIndex === colorPalette.length - 1) { @@ -58,40 +47,15 @@ function cycleColor() { } -function hydraCheck() { - var numberOfButtons = Controller.getNumberOfButtons(); - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - hydrasConnected = (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2); - return hydrasConnected; //hydrasConnected; -} - -//************ Mouse Paint ************************** +MousePaint(); function MousePaint() { - + var DRAWING_DISTANCE = 5; var lines = []; - var deletedLines = []; var isDrawing = false; - var path = []; - - var lineRider = new LineRider(); - lineRider.addStartHandler(function() { - var points = []; - //create points array from list of all points in path - path.forEach(function(point) { - points.push(point); - }); - lineRider.setPath(points); - }); - - var LINE_WIDTH = 7; - var line; - var points = []; - + var line, linePosition; var BRUSH_SIZE = .05; @@ -102,7 +66,11 @@ function MousePaint() { y: 0, z: 0 }, - color: currentColor, + color: { + red: 100, + green: 10, + blue: 100 + }, dimensions: { x: BRUSH_SIZE, y: BRUSH_SIZE, @@ -111,12 +79,10 @@ function MousePaint() { }); - function newLine(point) { - if (!point) { - return; - } + function newLine(position) { + linePosition = position; line = Entities.addEntity({ - position: point, + position: position, type: "Line", color: currentColor, dimensions: { @@ -124,44 +90,34 @@ function MousePaint() { y: LINE_DIMENSIONS, z: LINE_DIMENSIONS }, - lineWidth: LINE_WIDTH + linePoints: [], + lineWidth: LINE_WIDTH, + lifetime: LIFETIME }); - points = []; - points.push(point); - path.push(point); lines.push(line); } function mouseMoveEvent(event) { - var point = computePoint(event) + var worldPoint = computeWorldPoint(event); Entities.editEntity(brush, { - position: point + position: worldPoint }); if (!isDrawing) { return; } - points.push(point); - path.push(point); - var success = Entities.setAllPoints(line, points); + var localPoint = computeLocalPoint(event) + var success = Entities.appendPoint(line, localPoint); + if (!success) { - //We're out of bounds of entity bounding box, so start a new line - newLine(point) - return; - } - - - if (points.length === MAX_POINTS_PER_LINE) { - //We need to start a new line! - newLine(point); + newLine(worldPoint); + Entities.appendPoint(line, computeLocalPoint(event)); } } - - function undoStroke() { var deletedLine = lines.pop(); var deletedLineProps = Entities.getEntityProperties(deletedLine); @@ -175,18 +131,26 @@ function MousePaint() { lines.push(restoredLine); } + function computeWorldPoint(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); + return Vec3.sum(Camera.getPosition(), addVector); + } + + function computeLocalPoint(event) { + + var localPoint = Vec3.subtract(computeWorldPoint(event), linePosition); + return localPoint; + } + function mousePressEvent(event) { if (!event.isLeftButton) { isDrawing = false; return; } - lineRider.mousePressEvent(event); - path = []; - var point = computePoint(event); - newLine(point); + newLine(computeWorldPoint(event)); isDrawing = true; - } function mouseReleaseEvent() { @@ -208,16 +172,16 @@ function MousePaint() { } } + + function cleanup() { lines.forEach(function(line) { - Entities.deleteEntity(line); + // Entities.deleteEntity(line); }); Entities.deleteEntity(brush); - lineRider.cleanup(); } - Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.mouseMoveEvent.connect(mouseMoveEvent); @@ -227,273 +191,6 @@ function MousePaint() { } - -//*****************HYDRA PAINT ******************************************* - - - -function HydraPaint() { - - - - var lineRider = new LineRider(); - lineRider.addStartHandler(function() { - var points = []; - //create points array from list of all points in path - rightController.path.forEach(function(point) { - points.push(point); - }); - lineRider.setPath(points); - }); - - var LEFT = 0; - var RIGHT = 1; - - var currentTime = 0; - - - var minBrushSize = .02; - var maxBrushSize = .04 - - - var minLineWidth = 5; - var maxLineWidth = 10; - var currentLineWidth = minLineWidth; - var MIN_PAINT_TRIGGER_THRESHOLD = .01; - var LINE_LIFETIME = 20; - var COLOR_CHANGE_TIME_FACTOR = 0.1; - - var RIGHT_BUTTON_1 = 7 - var RIGHT_BUTTON_2 = 8 - var RIGHT_BUTTON_3 = 9; - var RIGHT_BUTTON_4 = 10 - - var LEFT_BUTTON_1 = 1; - var LEFT_BUTTON_2 = 2; - var LEFT_BUTTON_3 = 3; - var LEFT_BUTTON_4 = 4; - - var STROKE_SMOOTH_FACTOR = 1; - - var MIN_DRAW_DISTANCE = 0.2; - var MAX_DRAW_DISTANCE = 0.4; - - function controller(side, undoButton, redoButton, cycleColorButton, startRideButton) { - this.triggerHeld = false; - this.triggerThreshold = 0.9; - this.side = side; - this.palm = 2 * side; - this.tip = 2 * side + 1; - this.trigger = side; - this.lines = []; - this.deletedLines = [] //just an array of properties objects - this.isPainting = false; - - this.undoButton = undoButton; - this.undoButtonPressed = false; - this.prevUndoButtonPressed = false; - - this.redoButton = redoButton; - this.redoButtonPressed = false; - this.prevRedoButtonPressed = false; - - this.cycleColorButton = cycleColorButton; - this.cycleColorButtonPressed = false; - this.prevColorCycleButtonPressed = false; - - this.startRideButton = startRideButton; - this.startRideButtonPressed = false; - this.prevStartRideButtonPressed = false; - - this.strokeCount = 0; - this.currentBrushSize = minBrushSize; - this.points = []; - this.path = []; - - this.brush = Entities.addEntity({ - type: 'Sphere', - position: { - x: 0, - y: 0, - z: 0 - }, - color: currentColor, - dimensions: { - x: minBrushSize, - y: minBrushSize, - z: minBrushSize - } - }); - - - this.newLine = function(point) { - this.line = Entities.addEntity({ - position: MyAvatar.position, - type: "Line", - color: currentColor, - dimensions: { - x: 10, - y: 10, - z: 10 - }, - lineWidth: 5, - // lifetime: LINE_LIFETIME - }); - this.points = []; - if (point) { - this.points.push(point); - this.path.push(point); - } - this.lines.push(this.line); - } - - this.update = function(deltaTime) { - this.updateControllerState(); - this.avatarPalmOffset = Vec3.subtract(this.palmPosition, MyAvatar.position); - this.projectedForwardDistance = Vec3.dot(Quat.getFront(Camera.getOrientation()), this.avatarPalmOffset); - this.mappedPalmOffset = map(this.projectedForwardDistance, -.5, .5, MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE); - this.tipDirection = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - this.offsetVector = Vec3.multiply(this.mappedPalmOffset, this.tipDirection); - this.drawPoint = Vec3.sum(this.palmPosition, this.offsetVector); - this.currentBrushSize = map(this.triggerValue, 0, 1, minBrushSize, maxBrushSize); - Entities.editEntity(this.brush, { - position: this.drawPoint, - dimensions: { - x: this.currentBrushSize, - y: this.currentBrushSize, - z: this.currentBrushSize - }, - color: currentColor - }); - if (this.triggerValue > MIN_PAINT_TRIGGER_THRESHOLD) { - if (!this.isPainting) { - this.isPainting = true; - this.newLine(); - this.path = []; - } - if (this.strokeCount % STROKE_SMOOTH_FACTOR === 0) { - this.paint(this.drawPoint); - } - this.strokeCount++; - } else if (this.triggerValue < MIN_PAINT_TRIGGER_THRESHOLD && this.isPainting) { - this.releaseTrigger(); - } - - this.oldPalmPosition = this.palmPosition; - this.oldTipPosition = this.tipPosition; - } - - this.releaseTrigger = function() { - this.isPainting = false; - - } - - - this.updateControllerState = function() { - this.undoButtonPressed = Controller.isButtonPressed(this.undoButton); - this.redoButtonPressed = Controller.isButtonPressed(this.redoButton); - this.cycleColorButtonPressed = Controller.isButtonPressed(this.cycleColorButton); - this.startRideButtonPressed = Controller.isButtonPressed(this.startRideButton); - - //This logic gives us button release - if (this.prevUndoButtonPressed === true && this.undoButtonPressed === false) { - //User released undo button, so undo - this.undoStroke(); - } - if (this.prevRedoButtonPressed === true && this.redoButtonPressed === false) { - this.redoStroke(); - } - - if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { - cycleColor(); - Entities.editEntity(this.brush, { - color: currentColor - }); - } - if (this.prevStartRideButtonPressed === true && this.startRideButtonPressed === false) { - lineRider.toggleRide(); - } - this.prevRedoButtonPressed = this.redoButtonPressed; - this.prevUndoButtonPressed = this.undoButtonPressed; - this.prevCycleColorButtonPressed = this.cycleColorButtonPressed; - this.prevStartRideButtonPressed = this.startRideButtonPressed; - - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - this.triggerValue = Controller.getTriggerValue(this.trigger); - } - - this.undoStroke = function() { - var deletedLine = this.lines.pop(); - var deletedLineProps = Entities.getEntityProperties(deletedLine); - this.deletedLines.push(deletedLineProps); - Entities.deleteEntity(deletedLine); - } - - this.redoStroke = function() { - var restoredLine = Entities.addEntity(this.deletedLines.pop()); - Entities.addEntity(restoredLine); - this.lines.push(restoredLine); - } - - this.paint = function(point) { - - currentLineWidth = map(this.triggerValue, 0, 1, minLineWidth, maxLineWidth); - this.points.push(point); - this.path.push(point); - Entities.editEntity(this.line, { - linePoints: this.points, - lineWidth: currentLineWidth, - }); - if (this.points.length > MAX_POINTS_PER_LINE) { - this.newLine(point); - } - } - - this.cleanup = function() { - Entities.deleteEntity(this.brush); - this.lines.forEach(function(line) { - Entities.deleteEntity(line); - }); - } - } - - function update(deltaTime) { - rightController.update(deltaTime); - leftController.update(deltaTime); - currentTime += deltaTime; - } - - function cleanup() { - rightController.cleanup(); - leftController.cleanup(); - lineRider.cleanup(); - } - - function mousePressEvent(event) { - lineRider.mousePressEvent(event); - } - - function vectorIsZero(v) { - return v.x === 0 && v.y === 0 && v.z === 0; - } - - - var rightController = new controller(RIGHT, RIGHT_BUTTON_3, RIGHT_BUTTON_4, RIGHT_BUTTON_1, RIGHT_BUTTON_2); - var leftController = new controller(LEFT, LEFT_BUTTON_3, LEFT_BUTTON_4, LEFT_BUTTON_1, LEFT_BUTTON_2); - - Script.update.connect(update); - Script.scriptEnding.connect(cleanup); - Controller.mousePressEvent.connect(mousePressEvent); - -} - -function computePoint(event) { - var pickRay = Camera.computePickRay(event.x, event.y); - var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); - return Vec3.sum(Camera.getPosition(), addVector); -} - function randFloat(low, high) { return low + Math.random() * (high - low); } From 362d9a24817577ddae17d51147eb64717eb449c5 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 10:35:00 -0700 Subject: [PATCH 09/12] syncing brush sphere with line color --- examples/paint.js | 2 +- libraries/entities/src/QuadEntityItem.cpp | 9 +++++++++ libraries/entities/src/QuadEntityItem.h | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 libraries/entities/src/QuadEntityItem.cpp create mode 100644 libraries/entities/src/QuadEntityItem.h diff --git a/examples/paint.js b/examples/paint.js index ebda5e2e18..3f4a08cb28 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -83,7 +83,7 @@ function MousePaint() { linePosition = position; line = Entities.addEntity({ position: position, - type: "Line", + type: "Quad", color: currentColor, dimensions: { x: LINE_DIMENSIONS, diff --git a/libraries/entities/src/QuadEntityItem.cpp b/libraries/entities/src/QuadEntityItem.cpp new file mode 100644 index 0000000000..0ac04129be --- /dev/null +++ b/libraries/entities/src/QuadEntityItem.cpp @@ -0,0 +1,9 @@ +// +// QuadEntityItem.cpp +// hifi +// +// Created by eric levin on 6/22/15. +// +// + +#include "QuadEntityItem.h" diff --git a/libraries/entities/src/QuadEntityItem.h b/libraries/entities/src/QuadEntityItem.h new file mode 100644 index 0000000000..64f733d6b5 --- /dev/null +++ b/libraries/entities/src/QuadEntityItem.h @@ -0,0 +1,14 @@ +// +// QuadEntityItem.h +// hifi +// +// Created by eric levin on 6/22/15. +// +// + +#ifndef __hifi__QuadEntityItem__ +#define __hifi__QuadEntityItem__ + +#include + +#endif /* defined(__hifi__QuadEntityItem__) */ From 1b69563b29b855f448c64acf2608369818b59b5d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 11:06:40 -0700 Subject: [PATCH 10/12] changed quad back to line; --- examples/paint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/paint.js b/examples/paint.js index 3f4a08cb28..ebda5e2e18 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -83,7 +83,7 @@ function MousePaint() { linePosition = position; line = Entities.addEntity({ position: position, - type: "Quad", + type: "Line", color: currentColor, dimensions: { x: LINE_DIMENSIONS, From 6c84e5ad77464ccca34d1b4de3a3b2ab7a45571d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 11:08:40 -0700 Subject: [PATCH 11/12] actually syncing brush to line color --- examples/paint.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index ebda5e2e18..20196601df 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -66,11 +66,7 @@ function MousePaint() { y: 0, z: 0 }, - color: { - red: 100, - green: 10, - blue: 100 - }, + color: currentColor, dimensions: { x: BRUSH_SIZE, y: BRUSH_SIZE, From 9014e8c03838a8cbf5d097a61af8496429414522 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 22 Jun 2015 15:34:46 -0700 Subject: [PATCH 12/12] increased dimensions for line entity --- examples/paint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/paint.js b/examples/paint.js index 20196601df..31ffd02506 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -11,7 +11,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -var LINE_DIMENSIONS = 1; +var LINE_DIMENSIONS = 5; var LIFETIME = 6000; var colorPalette = [{