From 6b9b4d4e6e38d6c8428261c1699f3074ecedc570 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 Oct 2015 10:44:39 -0700 Subject: [PATCH 01/23] Add libraries/line.js --- examples/libraries/line.js | 149 +++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 examples/libraries/line.js diff --git a/examples/libraries/line.js b/examples/libraries/line.js new file mode 100644 index 0000000000..62811e50bc --- /dev/null +++ b/examples/libraries/line.js @@ -0,0 +1,149 @@ +function error(message) { + print("[ERROR] " + message); +} + +// PolyLine +var LINE_DIMENSIONS = { x: 2000, y: 2000, z: 2000 }; +var MAX_LINE_LENGTH = 40; // This must be 2 or greater; +var PolyLine = function(position, color, defaultStrokeWidth) { + this.position = position; + this.color = color; + this.defaultStrokeWidth = 0.10; + this.points = [ + { x: 0, y: 0, z: 0 } + ]; + this.strokeWidths = [ + this.defaultStrokeWidth + ]; + this.normals = [ + { x: 1, y: 0, z: 0 } + ] + this.entityID = Entities.addEntity({ + type: "PolyLine", + position: position, + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths, + dimensions: LINE_DIMENSIONS, + color: color, + lifetime: 20, + }); +}; + +PolyLine.prototype.enqueuePoint = function(position) { + if (this.isFull()) { + error("Hit max PolyLine size"); + return; + } + + position = Vec3.subtract(position, this.position); + this.points.push(position); + this.normals.push({ x: 1, y: 0, z: 0 }); + this.strokeWidths.push(this.defaultStrokeWidth * Math.min(1.0, this.points.length / 10)); + Entities.editEntity(this.entityID, { + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths, + }); +}; + +PolyLine.prototype.dequeuePoint = function() { + if (this.points.length == 0) { + error("Hit min PolyLine size"); + return; + } + + this.points = this.points.slice(1); + this.normals = this.normals.slice(1); + this.strokeWidths = this.strokeWidths.slice(1); + + Entities.editEntity(this.entityID, { + linePoints: this.points, + normals: this.normals, + strokeWidths: this.strokeWidths, + }); +}; + +PolyLine.prototype.getFirstPoint = function() { + return Vec3.sum(this.position, this.points[0]); +}; + +PolyLine.prototype.getLastPoint = function() { + return Vec3.sum(this.position, this.points[this.points.length - 1]); +}; + +PolyLine.prototype.getSize = function() { + return this.points.length; +} + +PolyLine.prototype.isFull = function() { + return this.points.length >= MAX_LINE_LENGTH; +}; + +PolyLine.prototype.destroy = function() { + Entities.deleteEntity(this.entityID); + this.points = []; +}; + + + +// InfiniteLine +InfiniteLine = function(position, color) { + this.position = position; + this.color = color; + this.lines = [new PolyLine(position, color)]; + this.size = 0; +}; + +InfiniteLine.prototype.enqueuePoint = function(position) { + var currentLine; + + if (this.lines.length == 0) { + currentLine = new PolyLine(position, this.color); + this.lines.push(currentLine); + } else { + currentLine = this.lines[this.lines.length - 1]; + } + + if (currentLine.isFull()) { + var newLine = new PolyLine(currentLine.getLastPoint(), this.color); + this.lines.push(newLine); + currentLine = newLine; + } + + currentLine.enqueuePoint(position); + + ++this.size; +}; + +InfiniteLine.prototype.dequeuePoint = function() { + if (this.lines.length == 0) { + error("Trying to dequeue from InfiniteLine when no points are left"); + return; + } + + var lastLine = this.lines[0]; + lastLine.dequeuePoint(); + + if (lastLine.getSize() <= 1) { + this.lines = this.lines.slice(1); + } + + --this.size; +}; + +InfiniteLine.prototype.getFirstPoint = function() { + return this.lines.length > 0 ? this.lines[0].getFirstPoint() : null; +}; + +InfiniteLine.prototype.getLastPoint = function() { + return this.lines.length > 0 ? this.lines[lines.length - 1].getLastPoint() : null; +}; + +InfiniteLine.prototype.destroy = function() { + for (var i = 0; i < this.lines.length; ++i) { + this.lines[i].destroy(); + } + + this.size = 0; +}; From d6230fbed329f5db5780adca536012939d035a4c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 Oct 2015 10:46:36 -0700 Subject: [PATCH 02/23] Remove trailing commas in line.js --- examples/libraries/line.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/libraries/line.js b/examples/libraries/line.js index 62811e50bc..0834c6176e 100644 --- a/examples/libraries/line.js +++ b/examples/libraries/line.js @@ -26,7 +26,7 @@ var PolyLine = function(position, color, defaultStrokeWidth) { strokeWidths: this.strokeWidths, dimensions: LINE_DIMENSIONS, color: color, - lifetime: 20, + lifetime: 20 }); }; @@ -43,7 +43,7 @@ PolyLine.prototype.enqueuePoint = function(position) { Entities.editEntity(this.entityID, { linePoints: this.points, normals: this.normals, - strokeWidths: this.strokeWidths, + strokeWidths: this.strokeWidths }); }; @@ -60,7 +60,7 @@ PolyLine.prototype.dequeuePoint = function() { Entities.editEntity(this.entityID, { linePoints: this.points, normals: this.normals, - strokeWidths: this.strokeWidths, + strokeWidths: this.strokeWidths }); }; From 1a1ab29978e04302fb49aff32a2afcfd3611b147 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 Oct 2015 16:45:43 -0700 Subject: [PATCH 03/23] Add lineExample.js --- examples/example/lineExample.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 examples/example/lineExample.js diff --git a/examples/example/lineExample.js b/examples/example/lineExample.js new file mode 100644 index 0000000000..6642e499fb --- /dev/null +++ b/examples/example/lineExample.js @@ -0,0 +1,12 @@ +Script.include("../libraries/line.js"); + +var basePosition = MyAvatar.position; +var line = new InfiniteLine(basePosition); + +for (var i = 0; i < (16 * Math.PI); i += 0.05) { + var x = 0 + var y = 0.25 * Math.sin(i); + var z = i / 10; + + line.enqueuePoint(Vec3.sum(basePosition, { x: x, y: y, z: z })); +} From 2abb6a2fd5921f474a999eba368296fb00def4b4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 Oct 2015 16:45:58 -0700 Subject: [PATCH 04/23] Clean up line.js --- examples/libraries/line.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/libraries/line.js b/examples/libraries/line.js index 0834c6176e..991b691ae8 100644 --- a/examples/libraries/line.js +++ b/examples/libraries/line.js @@ -8,15 +8,12 @@ var MAX_LINE_LENGTH = 40; // This must be 2 or greater; var PolyLine = function(position, color, defaultStrokeWidth) { this.position = position; this.color = color; - this.defaultStrokeWidth = 0.10; + this.defaultStrokeWidth = defaultStrokeWidth; this.points = [ - { x: 0, y: 0, z: 0 } ]; this.strokeWidths = [ - this.defaultStrokeWidth ]; this.normals = [ - { x: 1, y: 0, z: 0 } ] this.entityID = Entities.addEntity({ type: "PolyLine", @@ -39,7 +36,7 @@ PolyLine.prototype.enqueuePoint = function(position) { position = Vec3.subtract(position, this.position); this.points.push(position); this.normals.push({ x: 1, y: 0, z: 0 }); - this.strokeWidths.push(this.defaultStrokeWidth * Math.min(1.0, this.points.length / 10)); + this.strokeWidths.push(this.defaultStrokeWidth); Entities.editEntity(this.entityID, { linePoints: this.points, normals: this.normals, @@ -91,7 +88,7 @@ PolyLine.prototype.destroy = function() { InfiniteLine = function(position, color) { this.position = position; this.color = color; - this.lines = [new PolyLine(position, color)]; + this.lines = [new PolyLine(position, color, 0.01)]; this.size = 0; }; @@ -99,14 +96,15 @@ InfiniteLine.prototype.enqueuePoint = function(position) { var currentLine; if (this.lines.length == 0) { - currentLine = new PolyLine(position, this.color); + currentLine = new PolyLine(position, this.color, 0.01); this.lines.push(currentLine); } else { currentLine = this.lines[this.lines.length - 1]; } if (currentLine.isFull()) { - var newLine = new PolyLine(currentLine.getLastPoint(), this.color); + var newLine = new PolyLine(currentLine.getLastPoint(), this.color, 0.01); + newLine.enqueuePoint(currentLine.getLastPoint()); this.lines.push(newLine); currentLine = newLine; } From 983c551ce35c0ff5c153d31fa4294a89f38d422c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 Oct 2015 09:13:16 -0700 Subject: [PATCH 05/23] Clean up line.js and make lifetime settable --- examples/example/lineExample.js | 7 +++++-- examples/libraries/line.js | 27 +++++++++++++++------------ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/examples/example/lineExample.js b/examples/example/lineExample.js index 6642e499fb..e6c3d90cba 100644 --- a/examples/example/lineExample.js +++ b/examples/example/lineExample.js @@ -1,12 +1,15 @@ Script.include("../libraries/line.js"); var basePosition = MyAvatar.position; -var line = new InfiniteLine(basePosition); +var color = { red: 128, green: 220, blue: 190 }; +var strokeWidth = 0.01; +var line = new InfiniteLine(basePosition, color, 20); for (var i = 0; i < (16 * Math.PI); i += 0.05) { var x = 0 var y = 0.25 * Math.sin(i); var z = i / 10; - line.enqueuePoint(Vec3.sum(basePosition, { x: x, y: y, z: z })); + var position = Vec3.sum(basePosition, { x: x, y: y, z: z }); + line.enqueuePoint(position, strokeWidth); } diff --git a/examples/libraries/line.js b/examples/libraries/line.js index 991b691ae8..77cb13c124 100644 --- a/examples/libraries/line.js +++ b/examples/libraries/line.js @@ -5,10 +5,13 @@ function error(message) { // PolyLine var LINE_DIMENSIONS = { x: 2000, y: 2000, z: 2000 }; var MAX_LINE_LENGTH = 40; // This must be 2 or greater; -var PolyLine = function(position, color, defaultStrokeWidth) { +var DEFAULT_STROKE_WIDTH = 0.1; +var DEFAULT_LIFETIME = 20; +var DEFAULT_COLOR = { red: 255, green: 255, blue: 255 }; +var PolyLine = function(position, color, lifetime) { this.position = position; this.color = color; - this.defaultStrokeWidth = defaultStrokeWidth; + this.lifetime = lifetime === undefined ? DEFAULT_LIFETIME : lifetime; this.points = [ ]; this.strokeWidths = [ @@ -23,11 +26,11 @@ var PolyLine = function(position, color, defaultStrokeWidth) { strokeWidths: this.strokeWidths, dimensions: LINE_DIMENSIONS, color: color, - lifetime: 20 + lifetime: lifetime }); }; -PolyLine.prototype.enqueuePoint = function(position) { +PolyLine.prototype.enqueuePoint = function(position, strokeWidth) { if (this.isFull()) { error("Hit max PolyLine size"); return; @@ -36,7 +39,7 @@ PolyLine.prototype.enqueuePoint = function(position) { position = Vec3.subtract(position, this.position); this.points.push(position); this.normals.push({ x: 1, y: 0, z: 0 }); - this.strokeWidths.push(this.defaultStrokeWidth); + this.strokeWidths.push(strokeWidth); Entities.editEntity(this.entityID, { linePoints: this.points, normals: this.normals, @@ -83,33 +86,33 @@ PolyLine.prototype.destroy = function() { }; - // InfiniteLine -InfiniteLine = function(position, color) { +InfiniteLine = function(position, color, lifetime) { this.position = position; this.color = color; + this.lifetime = lifetime === undefined ? DEFAULT_LIFETIME : lifetime; this.lines = [new PolyLine(position, color, 0.01)]; this.size = 0; }; -InfiniteLine.prototype.enqueuePoint = function(position) { +InfiniteLine.prototype.enqueuePoint = function(position, strokeWidth) { var currentLine; if (this.lines.length == 0) { - currentLine = new PolyLine(position, this.color, 0.01); + currentLine = new PolyLine(position, this.color, this.lifetime); this.lines.push(currentLine); } else { currentLine = this.lines[this.lines.length - 1]; } if (currentLine.isFull()) { - var newLine = new PolyLine(currentLine.getLastPoint(), this.color, 0.01); - newLine.enqueuePoint(currentLine.getLastPoint()); + var newLine = new PolyLine(currentLine.getLastPoint(), this.color, this.lifetime); + newLine.enqueuePoint(currentLine.getLastPoint(), strokeWidth); this.lines.push(newLine); currentLine = newLine; } - currentLine.enqueuePoint(position); + currentLine.enqueuePoint(position, strokeWidth); ++this.size; }; From 2cd2af2b13421341224910654921e9413bccd6f6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 Oct 2015 09:49:52 -0700 Subject: [PATCH 06/23] Add headers to line.js and lineExample.js --- examples/example/lineExample.js | 11 +++++++++++ examples/libraries/line.js | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/examples/example/lineExample.js b/examples/example/lineExample.js index e6c3d90cba..d424d4f9f3 100644 --- a/examples/example/lineExample.js +++ b/examples/example/lineExample.js @@ -1,3 +1,14 @@ +// +// lineExample.js +// examples/example +// +// Created by Ryan Huffman on October 27, 2015 +// Copyright 2015 High Fidelity, Inc. +// +// 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("../libraries/line.js"); var basePosition = MyAvatar.position; diff --git a/examples/libraries/line.js b/examples/libraries/line.js index 77cb13c124..d31a34867b 100644 --- a/examples/libraries/line.js +++ b/examples/libraries/line.js @@ -1,3 +1,14 @@ +// +// line.js +// examples/libraries +// +// Created by Ryan Huffman on October 27, 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + function error(message) { print("[ERROR] " + message); } From 93503d0a216019cff88a2b08441f88539881932f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 30 Oct 2015 11:03:13 -0700 Subject: [PATCH 07/23] make kinematic grab set entities kinematic in bullet and update entity position --- examples/controllers/handControllerGrab.js | 24 ++++++++++++++++------ interface/src/avatar/AvatarActionHold.cpp | 5 +++++ libraries/physics/src/ObjectAction.cpp | 15 +++++++++++++- libraries/physics/src/ObjectMotionState.h | 9 ++++++++ 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index cb445a0960..9ee9ed1e04 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -55,6 +55,7 @@ var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held var NEAR_PICK_MAX_DISTANCE = 0.3; // max length of pick-ray for close grabbing to be selected var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object +var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed ///////////////////////////////////////////////////////////////// // @@ -404,8 +405,9 @@ function MyController(hand, triggerAction) { var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", - "gravity", "ignoreForCollisions"]); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity", + "ignoreForCollisions", + "collisionsWillMove"]); var now = Date.now(); // add the action and initialize some variables @@ -549,8 +551,14 @@ function MyController(hand, triggerAction) { this.lineOff(); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, - ["position", "rotation", "gravity", "ignoreForCollisions"]); + ["position", "rotation", "gravity", + "ignoreForCollisions", "collisionsWillMove"]); this.activateEntity(this.grabbedEntity, grabbedProperties); + if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) { + Entities.editEntity(this.grabbedEntity, { + collisionsWillMove: false + }); + } var handRotation = this.getHandRotation(); var handPosition = this.getHandPosition(); @@ -579,7 +587,8 @@ function MyController(hand, triggerAction) { timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, - ttl: ACTION_TTL + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; @@ -631,7 +640,8 @@ function MyController(hand, triggerAction) { timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, - ttl: ACTION_TTL + ttl: ACTION_TTL, + kinematic: NEAR_GRABBING_KINEMATIC }); this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); } @@ -828,6 +838,7 @@ function MyController(hand, triggerAction) { if (data["refCount"] == 1) { data["gravity"] = grabbedProperties.gravity; data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; + data["collisionsWillMove"] = grabbedProperties.collisionsWillMove; var whileHeldProperties = {gravity: {x:0, y:0, z:0}}; if (invertSolidWhileHeld) { whileHeldProperties["ignoreForCollisions"] = ! grabbedProperties.ignoreForCollisions; @@ -845,7 +856,8 @@ function MyController(hand, triggerAction) { if (data["refCount"] < 1) { Entities.editEntity(entityID, { gravity: data["gravity"], - ignoreForCollisions: data["ignoreForCollisions"] + ignoreForCollisions: data["ignoreForCollisions"], + collisionsWillMove: data["collisionsWillMove"] }); data = null; } diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 238e48d2fd..59bfd88be6 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -119,6 +119,9 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) { worldTrans.setRotation(glmToBullet(_rotationalTarget)); rigidBody->setWorldTransform(worldTrans); + ownerEntity->setPosition(_positionalTarget); + ownerEntity->setRotation(_rotationalTarget); + _previousPositionalTarget = _positionalTarget; _previousRotationalTarget = _rotationalTarget; _previousSet = true; @@ -224,6 +227,8 @@ QVariantMap AvatarActionHold::getArguments() { arguments["relativeRotation"] = glmToQMap(_relativeRotation); arguments["timeScale"] = _linearTimeScale; arguments["hand"] = _hand; + arguments["kinematic"] = _kinematic; + arguments["kinematicSetVelocity"] = _kinematicSetVelocity; }); return arguments; } diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index ff8382a143..d44ebc30b1 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -35,7 +35,9 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta if (ownerEntityExpired) { qDebug() << "warning -- action with no entity removing self from btCollisionWorld."; btDynamicsWorld* dynamicsWorld = static_cast(collisionWorld); - dynamicsWorld->removeAction(this); + if (dynamicsWorld) { + dynamicsWorld->removeAction(this); + } return; } @@ -120,6 +122,17 @@ QVariantMap ObjectAction::getArguments() { arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND; } arguments["tag"] = _tag; + + EntityItemPointer entity = _ownerEntity.lock(); + if (entity) { + ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); + if (motionState) { + arguments["::active"] = motionState->isActive(); + arguments["::motion-type"] = motionTypeToString(motionState->getMotionType()); + } else { + arguments["::no-motion-state"] = true; + } + } }); return arguments; } diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 450ac34a90..22f0e9dcb0 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -29,6 +29,15 @@ enum MotionType { MOTION_TYPE_KINEMATIC // keyframed motion }; +inline QString motionTypeToString(MotionType motionType) { + switch(motionType) { + case MOTION_TYPE_STATIC: return QString("static"); + case MOTION_TYPE_DYNAMIC: return QString("dynamic"); + case MOTION_TYPE_KINEMATIC: return QString("kinematic"); + } + return QString("unknown"); +} + enum MotionStateType { MOTIONSTATE_TYPE_INVALID, MOTIONSTATE_TYPE_ENTITY, From b102081f2f1dd0a0bc63c9f7d9c9972c7cb2eb38 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 30 Oct 2015 11:35:51 -0700 Subject: [PATCH 08/23] upon release, set velocity after returning entity to being dynamic --- examples/controllers/handControllerGrab.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 9ee9ed1e04..353e7b3daa 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -588,7 +588,8 @@ function MyController(hand, triggerAction) { relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, ttl: ACTION_TTL, - kinematic: NEAR_GRABBING_KINEMATIC + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; @@ -641,7 +642,8 @@ function MyController(hand, triggerAction) { relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, ttl: ACTION_TTL, - kinematic: NEAR_GRABBING_KINEMATIC + kinematic: NEAR_GRABBING_KINEMATIC, + kinematicSetVelocity: true }); this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); } @@ -810,12 +812,13 @@ function MyController(hand, triggerAction) { Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); } + this.deactivateEntity(this.grabbedEntity); + // the action will tend to quickly bring an object's velocity to zero. now that // the action is gone, set the objects velocity to something the holder might expect. Entities.editEntity(this.grabbedEntity, { velocity: this.grabbedVelocity }); - this.deactivateEntity(this.grabbedEntity); this.grabbedVelocity = ZERO_VEC; this.grabbedEntity = null; From f652e983a979daa9d4007f3e0ff2836563fa9779 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 30 Oct 2015 14:53:29 -0700 Subject: [PATCH 09/23] flag kinematic objs when changed in stepSimulation() --- interface/src/avatar/AvatarActionHold.cpp | 3 +- libraries/physics/src/ObjectAction.cpp | 1 - libraries/physics/src/ObjectAction.h | 10 ++--- libraries/physics/src/ObjectMotionState.cpp | 10 ++--- libraries/physics/src/ObjectMotionState.h | 16 ++++--- .../physics/src/ThreadSafeDynamicsWorld.cpp | 43 +++++++++++++++---- .../physics/src/ThreadSafeDynamicsWorld.h | 9 ++-- 7 files changed, 62 insertions(+), 30 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 59bfd88be6..e7d030e17a 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -119,8 +119,7 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) { worldTrans.setRotation(glmToBullet(_rotationalTarget)); rigidBody->setWorldTransform(worldTrans); - ownerEntity->setPosition(_positionalTarget); - ownerEntity->setRotation(_rotationalTarget); + motionState->dirtyInternalKinematicChanges(); _previousPositionalTarget = _positionalTarget; _previousRotationalTarget = _rotationalTarget; diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index d44ebc30b1..3188283f68 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -16,7 +16,6 @@ ObjectAction::ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) : btActionInterface(), EntityActionInterface(type, id), - _active(false), _ownerEntity(ownerEntity) { } diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index fca446aec4..45b40a9fb3 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -50,6 +50,8 @@ public: virtual quint64 getExpires() { return _expires; } protected: + quint64 localTimeToServerTime(quint64 timeValue) const; + quint64 serverTimeToLocalTime(quint64 timeValue) const; virtual btRigidBody* getRigidBody(); virtual glm::vec3 getPosition(); @@ -62,14 +64,10 @@ protected: virtual void setAngularVelocity(glm::vec3 angularVelocity); virtual void activateBody(); - bool _active; EntityItemWeakPointer _ownerEntity; - - quint64 _expires; // in seconds since epoch QString _tag; - - quint64 localTimeToServerTime(quint64 timeValue) const; - quint64 serverTimeToLocalTime(quint64 timeValue) const; + quint64 _expires { 0 }; // in seconds since epoch + bool _active { false }; private: int getEntityServerClockSkew() const; diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 4f3d0396c6..be0edafff5 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -20,17 +20,17 @@ // origin of physics simulation in world-frame glm::vec3 _worldOffset(0.0f); -// static +// static void ObjectMotionState::setWorldOffset(const glm::vec3& offset) { _worldOffset = offset; } -// static +// static const glm::vec3& ObjectMotionState::getWorldOffset() { return _worldOffset; } -// static +// static uint32_t worldSimulationStep = 0; void ObjectMotionState::setWorldSimulationStep(uint32_t step) { assert(step > worldSimulationStep); @@ -41,7 +41,7 @@ uint32_t ObjectMotionState::getWorldSimulationStep() { return worldSimulationStep; } -// static +// static ShapeManager* shapeManager = nullptr; void ObjectMotionState::setShapeManager(ShapeManager* manager) { assert(manager); @@ -85,7 +85,7 @@ glm::vec3 ObjectMotionState::getBodyLinearVelocity() const { glm::vec3 ObjectMotionState::getBodyLinearVelocityGTSigma() const { // NOTE: the threshold to use here relates to the linear displacement threshold (dX) for sending updates - // to objects that are tracked server-side (e.g. entities which use dX = 2mm). Hence an object moving + // to objects that are tracked server-side (e.g. entities which use dX = 2mm). Hence an object moving // just under this velocity threshold would trigger an update about V/dX times per second. const float MIN_LINEAR_SPEED_SQUARED = 0.0036f; // 6 mm/sec diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 22f0e9dcb0..992bdd11d7 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -44,12 +44,12 @@ enum MotionStateType { MOTIONSTATE_TYPE_AVATAR }; -// The update flags trigger two varieties of updates: "hard" which require the body to be pulled +// The update flags trigger two varieties of updates: "hard" which require the body to be pulled // and re-added to the physics engine and "easy" which just updates the body properties. -const uint32_t HARD_DIRTY_PHYSICS_FLAGS = (uint32_t)(Simulation::DIRTY_MOTION_TYPE | Simulation::DIRTY_SHAPE | +const uint32_t HARD_DIRTY_PHYSICS_FLAGS = (uint32_t)(Simulation::DIRTY_MOTION_TYPE | Simulation::DIRTY_SHAPE | Simulation::DIRTY_COLLISION_GROUP); const uint32_t EASY_DIRTY_PHYSICS_FLAGS = (uint32_t)(Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES | - Simulation::DIRTY_MASS | Simulation::DIRTY_MATERIAL | + Simulation::DIRTY_MASS | Simulation::DIRTY_MATERIAL | Simulation::DIRTY_SIMULATOR_ID | Simulation::DIRTY_SIMULATOR_OWNERSHIP); // These are the set of incoming flags that the PhysicsEngine needs to hear about: @@ -66,7 +66,7 @@ class PhysicsEngine; class ObjectMotionState : public btMotionState { public: // These poroperties of the PhysicsEngine are "global" within the context of all ObjectMotionStates - // (assuming just one PhysicsEngine). They are cached as statics for fast calculations in the + // (assuming just one PhysicsEngine). They are cached as statics for fast calculations in the // ObjectMotionState context. static void setWorldOffset(const glm::vec3& offset); static const glm::vec3& getWorldOffset(); @@ -121,7 +121,7 @@ public: virtual float getObjectFriction() const = 0; virtual float getObjectLinearDamping() const = 0; virtual float getObjectAngularDamping() const = 0; - + virtual glm::vec3 getObjectPosition() const = 0; virtual glm::quat getObjectRotation() const = 0; virtual glm::vec3 getObjectLinearVelocity() const = 0; @@ -140,6 +140,11 @@ public: bool isActive() const { return _body ? _body->isActive() : false; } + bool hasInternalKinematicChanges() const { return _hasInternalKinematicChanges; } + + void dirtyInternalKinematicChanges() { _hasInternalKinematicChanges = true; } + void clearInternalKinematicChanges() { _hasInternalKinematicChanges = false; } + friend class PhysicsEngine; protected: @@ -160,6 +165,7 @@ protected: float _mass; uint32_t _lastKinematicStep; + bool _hasInternalKinematicChanges { false }; }; typedef QSet SetOfMotionStates; diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index 94d6315705..c7dddb95c4 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -4,8 +4,8 @@ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it freely, + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it freely, * subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. @@ -75,7 +75,7 @@ int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep } } - // NOTE: We do NOT call synchronizeMotionState() after each substep (to avoid multiple locks on the + // NOTE: We do NOT call synchronizeMotionStates() after each substep (to avoid multiple locks on the // object data outside of the physics engine). A consequence of this is that the transforms of the // external objects only ever update at the end of the full step. @@ -87,6 +87,33 @@ int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep return subSteps; } +// call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState() +void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { + btAssert(body); + if (body->getMotionState() && !body->isStaticObject()) { + //we need to call the update at least once, even for sleeping objects + //otherwise the 'graphics' transform never updates properly + ///@todo: add 'dirty' flag + //if (body->getActivationState() != ISLAND_SLEEPING) + { + if (body->isKinematicObject()) { + ObjectMotionState* objectMotionState = static_cast(body->getMotionState()); + if (!objectMotionState->hasInternalKinematicChanges()) { + return; + } else { + objectMotionState->clearInternalKinematicChanges(); + } + } + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(), + (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(), + interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); + } + } +} + void ThreadSafeDynamicsWorld::synchronizeMotionStates() { _changedMotionStates.clear(); BT_PROFILE("synchronizeMotionStates"); @@ -97,22 +124,22 @@ void ThreadSafeDynamicsWorld::synchronizeMotionStates() { btRigidBody* body = btRigidBody::upcast(colObj); if (body) { if (body->getMotionState()) { - synchronizeSingleMotionState(body); + synchronizeMotionState(body); _changedMotionStates.push_back(static_cast(body->getMotionState())); } } } - } else { + } else { //iterate over all active rigid bodies for (int i=0;iisActive()) { if (body->getMotionState()) { - synchronizeSingleMotionState(body); + synchronizeMotionState(body); _changedMotionStates.push_back(static_cast(body->getMotionState())); } } } - } -} + } +} diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.h b/libraries/physics/src/ThreadSafeDynamicsWorld.h index 26954832cf..de37554f56 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.h +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.h @@ -4,8 +4,8 @@ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it freely, + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it freely, * subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. @@ -43,13 +43,16 @@ public: void synchronizeMotionStates(); // btDiscreteDynamicsWorld::m_localTime is the portion of real-time that has not yet been simulated - // but is used for MotionState::setWorldTransform() extrapolation (a feature that Bullet uses to provide + // but is used for MotionState::setWorldTransform() extrapolation (a feature that Bullet uses to provide // smoother rendering of objects when the physics simulation loop is ansynchronous to the render loop). float getLocalTimeAccumulation() const { return m_localTime; } VectorOfMotionStates& getChangedMotionStates() { return _changedMotionStates; } private: + // call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState() + void synchronizeMotionState(btRigidBody* body); + VectorOfMotionStates _changedMotionStates; }; From 22324eb281f7b3f46f91fdbe06c04f0196976f13 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 30 Oct 2015 14:55:33 -0700 Subject: [PATCH 10/23] more tweaking of keyboard input routes --- .../resources/controllers/keyboardMouse.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index fbc1533fff..8af6b1dc98 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -2,6 +2,15 @@ "name": "Keyboard/Mouse to Actions", "channels": [ + { "from": "Keyboard.A", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" }, + { "from": "Keyboard.D", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" }, + { "from": "Keyboard.A", "when": "Keyboard.RightMouseClick", "to": "Actions.LATERAL_LEFT" }, + { "from": "Keyboard.D", "when": "Keyboard.RightMouseClick", "to": "Actions.LATERAL_RIGHT" }, + { "from": "Keyboard.E", "when": "Keyboard.Shift", "to": "Actions.BOOM_IN", "filters": [ { "type": "scale", "scale": 0.05 } ] }, + { "from": "Keyboard.C", "when": "Keyboard.Shift", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.05 } ] }, + { "from": "Keyboard.S", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" }, + { "from": "Keyboard.W", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" }, + { "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] }, "when": [ "Application.InHMD", "Application.ComfortMode", "Keyboard.RightMouseClick" ], @@ -41,15 +50,6 @@ "to": "Actions.Yaw" }, - { "from": "Keyboard.A", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" }, - { "from": "Keyboard.D", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" }, - { "from": "Keyboard.A", "when": "Keyboard.RightMouseClick", "to": "Actions.LATERAL_LEFT" }, - { "from": "Keyboard.D", "when": "Keyboard.RightMouseClick", "to": "Actions.LATERAL_RIGHT" }, - { "from": "Keyboard.E", "when": "Keyboard.Shift", "to": "Actions.BOOM_IN", "filters": [ { "type": "scale", "scale": 0.05 } ] }, - { "from": "Keyboard.C", "when": "Keyboard.Shift", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.05 } ] }, - { "from": "Keyboard.S", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" }, - { "from": "Keyboard.W", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" }, - { "from": "Keyboard.W", "to": "Actions.LONGITUDINAL_FORWARD" }, { "from": "Keyboard.S", "to": "Actions.LONGITUDINAL_BACKWARD" }, { "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" }, From b8a2fcbb2c74dfac021108e244c423e83e888453 Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Fri, 30 Oct 2015 15:21:48 -0700 Subject: [PATCH 11/23] Vive controller - fix inverted inputs --- .../input-plugins/src/input-plugins/ViveControllerManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index 69303bb079..e90006e014 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -254,7 +254,7 @@ void ViveControllerManager::update(float deltaTime, bool jointsCaptured) { } numTrackedControllers++; - bool left = numTrackedControllers == 1; + bool left = numTrackedControllers == 2; const mat4& mat = _trackedDevicePoseMat4[device]; @@ -307,13 +307,13 @@ void ViveControllerManager::focusOutEvent() { // These functions do translation from the Steam IDs to the standard controller IDs void ViveControllerManager::handleAxisEvent(uint32_t axis, float x, float y, bool left) { #ifdef Q_OS_WIN + //FIX ME? It enters here every frame: probably we want to enter only if an event occurs axis += vr::k_EButton_Axis0; using namespace controller; if (axis == vr::k_EButton_SteamVR_Touchpad) { _axisStateMap[left ? LX : RX] = x; _axisStateMap[left ? LY : RY] = y; } else if (axis == vr::k_EButton_SteamVR_Trigger) { - //FIX ME: Seems that enters here everytime _axisStateMap[left ? LT : RT] = x; } #endif From cf83ca22bbaa77a195268e49ff720096f61d5a15 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 30 Oct 2015 15:30:54 -0700 Subject: [PATCH 12/23] change how kinematic objects get data back to entity when an action is active --- examples/controllers/handControllerGrab.js | 64 ++++++++++++++----- libraries/physics/src/EntityMotionState.cpp | 3 +- .../physics/src/ThreadSafeDynamicsWorld.cpp | 2 + 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 353e7b3daa..10775a483f 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -80,6 +80,18 @@ var ACTION_TTL_REFRESH = 5; var PICKS_PER_SECOND_PER_HAND = 5; var MSECS_PER_SEC = 1000.0; + +var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js +var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js + +var DEFAULT_GRABBABLE_DATA = { + grabbable: true, + invertSolidWhileHeld: false +}; + +var disabledHand ='none'; + + // states for the state machine var STATE_OFF = 0; var STATE_SEARCHING = 1; @@ -93,15 +105,35 @@ var STATE_FAR_GRABBING_NON_COLLIDING = 8; var STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING = 9; var STATE_RELEASE = 10; -var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js -var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js -var DEFAULT_GRABBABLE_DATA = { - grabbable: true, - invertSolidWhileHeld: false -}; +function stateToName(state) { + switch (state) { + case STATE_OFF: + return "off"; + case STATE_SEARCHING: + return "searching"; + case STATE_DISTANCE_HOLDING: + return "distance_holding"; + case STATE_CONTINUE_DISTANCE_HOLDING: + return "continue_distance_holding"; + case STATE_NEAR_GRABBING: + return "near_grabbing"; + case STATE_CONTINUE_NEAR_GRABBING: + return "continue_near_grabbing"; + case STATE_NEAR_GRABBING_NON_COLLIDING: + return "near_grabbing_non_colliding"; + case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: + return "continue_near_grabbing_non_colliding"; + case STATE_FAR_GRABBING_NON_COLLIDING: + return "far_grabbing_non_colliding"; + case STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING: + return "continue_far_grabbing_non_colliding"; + case STATE_RELEASE: + return "release"; + } -var disabledHand ='none'; + return "unknown"; +} function getTag() { return "grab-" + MyAvatar.sessionUUID; @@ -196,7 +228,7 @@ function MyController(hand, triggerAction) { this.setState = function(newState) { if (WANT_DEBUG) { - print("STATE: " + this.state + " --> " + newState); + print("STATE: " + stateToName(this.state) + " --> " + newState + ", hand: " + this.hand); } this.state = newState; } @@ -348,10 +380,11 @@ function MyController(hand, triggerAction) { } if (intersectionDistance <= NEAR_PICK_MAX_DISTANCE) { // the hand is very close to the intersected object. go into close-grabbing mode. - if (intersection.properties.collisionsWillMove === 1) { - this.setState(STATE_NEAR_GRABBING); - } else { + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); + if (grabbableData.wantsTrigger) { this.setState(STATE_NEAR_GRABBING_NON_COLLIDING); + } else { + this.setState(STATE_NEAR_GRABBING); } } else { // don't allow two people to distance grab the same object @@ -392,11 +425,11 @@ function MyController(hand, triggerAction) { } if (this.grabbedEntity === null) { return; - } else if (props.locked === 0 && props.collisionsWillMove === 1) { - this.setState(STATE_NEAR_GRABBING); - } else if (props.collisionsWillMove === 0 && grabbableData.wantsTrigger) { - // We have grabbed a non-physical object, so we want to trigger a non-colliding event as opposed to a grab event + } + if (grabbableData.wantsTrigger) { this.setState(STATE_NEAR_GRABBING_NON_COLLIDING); + } else if (props.locked === 0) { + this.setState(STATE_NEAR_GRABBING); } } }; @@ -816,6 +849,7 @@ function MyController(hand, triggerAction) { // the action will tend to quickly bring an object's velocity to zero. now that // the action is gone, set the objects velocity to something the holder might expect. + print("release velocity is " + vec3toStr(this.grabbedVelocity)); Entities.editEntity(this.grabbedEntity, { velocity: this.grabbedVelocity }); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 6832b8daff..42aaea33c2 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -146,7 +146,7 @@ MotionType EntityMotionState::computeObjectMotionType() const { if (_entity->getCollisionsWillMove()) { return MOTION_TYPE_DYNAMIC; } - return _entity->isMoving() ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC; + return (_entity->isMoving() || _entity->hasActions()) ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC; } bool EntityMotionState::isMoving() const { @@ -184,6 +184,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { if (!_entity) { return; } + assert(entityTreeIsLocked()); measureBodyAcceleration(); _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index c7dddb95c4..f725315330 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -102,6 +102,8 @@ void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { return; } else { objectMotionState->clearInternalKinematicChanges(); + body->getMotionState()->setWorldTransform(body->getWorldTransform()); + return; } } btTransform interpolatedTransform; From 085282db4f4cf1ed69ec4489c3906a3ab9f32bcf Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 30 Oct 2015 16:13:04 -0700 Subject: [PATCH 13/23] Crash fix for AvatarManager when iterating over _avatarHash The main problem is that a null shared pointer was inserted into the _avatarHash via the AvatarManager::getAvatarBySessionID(). When the sessionID is not present in the _avatarHash, [QHash](http://doc.qt.io/qt-5/qhash.html#operator-5b-5d) will *insert* an empty smart_ptr into the hash. --- interface/src/avatar/AvatarManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index fbfbbad2de..b0da8faeca 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -366,5 +366,10 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) return std::static_pointer_cast(_myAvatar); } QReadLocker locker(&_hashLock); - return _avatarHash[sessionID]; + auto iter = _avatarHash.find(sessionID); + if (iter != _avatarHash.end()) { + return iter.value(); + } else { + return AvatarSharedPointer(); + } } From 77e0023b43ddcfe6db2fd7b9852cba2b0977cdd2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 30 Oct 2015 16:31:15 -0700 Subject: [PATCH 14/23] Fix lifetime bug with first PolyLine in InfiniteLine --- examples/libraries/line.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/line.js b/examples/libraries/line.js index d31a34867b..c21bf2f3ad 100644 --- a/examples/libraries/line.js +++ b/examples/libraries/line.js @@ -102,7 +102,7 @@ InfiniteLine = function(position, color, lifetime) { this.position = position; this.color = color; this.lifetime = lifetime === undefined ? DEFAULT_LIFETIME : lifetime; - this.lines = [new PolyLine(position, color, 0.01)]; + this.lines = []; this.size = 0; }; From 944f0965c059a1d9af6a30d8c18523d59c836cff Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 30 Oct 2015 16:35:50 -0700 Subject: [PATCH 15/23] some refactoring and a bug fix -- grab script can throw things again --- examples/controllers/handControllerGrab.js | 8 +------- libraries/physics/src/PhysicsEngine.cpp | 9 ++++++--- libraries/physics/src/ThreadSafeDynamicsWorld.cpp | 6 ++---- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 10775a483f..815f903bfa 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -15,13 +15,11 @@ Script.include("../libraries/utils.js"); -//////////////////////////////////////////////////////////// // // add lines where the hand ray picking is happening // var WANT_DEBUG = false; -///////////////////////////////////////////////////////////////// // // these tune time-averaging and "on" value for analog trigger // @@ -30,7 +28,6 @@ var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value var TRIGGER_ON_VALUE = 0.4; var TRIGGER_OFF_VALUE = 0.15; -///////////////////////////////////////////////////////////////// // // distant manipulation // @@ -44,7 +41,6 @@ var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000,z: 1000}; var LINE_LENGTH = 500; var PICK_MAX_DISTANCE = 500; // max length of pick-ray -///////////////////////////////////////////////////////////////// // // near grabbing // @@ -57,7 +53,6 @@ var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things var PICK_BACKOFF_DISTANCE = 0.2; // helps when hand is intersecting the grabble object var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-grabbed -///////////////////////////////////////////////////////////////// // // other constants // @@ -228,7 +223,7 @@ function MyController(hand, triggerAction) { this.setState = function(newState) { if (WANT_DEBUG) { - print("STATE: " + stateToName(this.state) + " --> " + newState + ", hand: " + this.hand); + print("STATE: " + stateToName(this.state) + " --> " + stateToName(newState) + ", hand: " + this.hand); } this.state = newState; } @@ -849,7 +844,6 @@ function MyController(hand, triggerAction) { // the action will tend to quickly bring an object's velocity to zero. now that // the action is gone, set the objects velocity to something the holder might expect. - print("release velocity is " + vec3toStr(this.grabbedVelocity)); Entities.editEntity(this.grabbedEntity, { velocity: this.grabbedVelocity }); diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 1e652b75c4..f3ef855e50 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -82,12 +82,12 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) { btCollisionShape* shape = motionState->getShape(); assert(shape); body = new btRigidBody(mass, motionState, shape, inertia); + motionState->setRigidBody(body); } else { body->setMassProps(mass, inertia); } body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT); body->updateInertiaTensor(); - motionState->setRigidBody(body); motionState->updateBodyVelocities(); const float KINEMATIC_LINEAR_VELOCITY_THRESHOLD = 0.01f; // 1 cm/sec const float KINEMATIC_ANGULAR_VELOCITY_THRESHOLD = 0.01f; // ~1 deg/sec @@ -101,12 +101,15 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) { shape->calculateLocalInertia(mass, inertia); if (!body) { body = new btRigidBody(mass, motionState, shape, inertia); + motionState->setRigidBody(body); } else { body->setMassProps(mass, inertia); } + body->setCollisionFlags(body->getCollisionFlags() & ~(btCollisionObject::CF_KINEMATIC_OBJECT | + btCollisionObject::CF_STATIC_OBJECT)); body->updateInertiaTensor(); - motionState->setRigidBody(body); motionState->updateBodyVelocities(); + // NOTE: Bullet will deactivate any object whose velocity is below these thresholds for longer than 2 seconds. // (the 2 seconds is determined by: static btRigidBody::gDeactivationTime const float DYNAMIC_LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec @@ -123,12 +126,12 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) { if (!body) { assert(motionState->getShape()); body = new btRigidBody(mass, motionState, motionState->getShape(), inertia); + motionState->setRigidBody(body); } else { body->setMassProps(mass, inertia); } body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT); body->updateInertiaTensor(); - motionState->setRigidBody(body); break; } } diff --git a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp index f725315330..d06a9b8e07 100644 --- a/libraries/physics/src/ThreadSafeDynamicsWorld.cpp +++ b/libraries/physics/src/ThreadSafeDynamicsWorld.cpp @@ -98,13 +98,11 @@ void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) { { if (body->isKinematicObject()) { ObjectMotionState* objectMotionState = static_cast(body->getMotionState()); - if (!objectMotionState->hasInternalKinematicChanges()) { - return; - } else { + if (objectMotionState->hasInternalKinematicChanges()) { objectMotionState->clearInternalKinematicChanges(); body->getMotionState()->setWorldTransform(body->getWorldTransform()); - return; } + return; } btTransform interpolatedTransform; btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), From f50e1a0977f92d28c5e117f80a2e7723e6acd8ae Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 30 Oct 2015 17:18:37 -0700 Subject: [PATCH 16/23] Fix for rare crash in LogHandler::flushRepeatedMessages() This can happen when LogHandler::flushRepetedMessages is called on the main thread, while the application is printing messages on a separate thread. The access to the _lastRepeatedMessage QHash was not guarded. I've added two mutexes to guard access to both the repeatedMessage hashes/regexes and the onlyOnceMessages/regexes. This will unfortunately incur a performance hit for frequent debug logging, but that's better then crashing. Also, I've added the ability to print threadIDs as well as Process ids. This is helpful when debugging multi-threaded access to shared variables. --- assignment-client/src/AssignmentClient.cpp | 2 +- .../src/AssignmentClientMonitor.cpp | 2 +- libraries/shared/src/LogHandler.cpp | 66 ++++++++++++------- libraries/shared/src/LogHandler.h | 26 ++++---- 4 files changed, 60 insertions(+), 36 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index f4f98114d0..bf5f9c3b7f 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -74,7 +74,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); // make sure we output process IDs for a child AC otherwise it's insane to parse - LogHandler::getInstance().setShouldOutputPID(true); + LogHandler::getInstance().setShouldOutputProcessID(true); // setup our _requestAssignment member variable from the passed arguments _requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 58cf3c49f3..7b3d5695e1 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -44,7 +44,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME); // make sure we output process IDs for a monitor otherwise it's insane to parse - LogHandler::getInstance().setShouldOutputPID(true); + LogHandler::getInstance().setShouldOutputProcessID(true); // create a NodeList so we can receive stats from children DependencyManager::registerInheritance(); diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index cc3519e43e..0e05df277b 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -12,9 +12,10 @@ #include -#include -#include -#include +#include +#include +#include +#include #include "LogHandler.h" @@ -24,13 +25,14 @@ LogHandler& LogHandler::getInstance() { } LogHandler::LogHandler() : - _shouldOutputPID(false) + _shouldOutputProcessID(false), + _shouldOutputThreadID(false) { // setup our timer to flush the verbose logs every 5 seconds QTimer* logFlushTimer = new QTimer(this); connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); - + // when the log handler is first setup we should print our timezone QString timezoneString = "Time zone: " + QDateTime::currentDateTime().toString("t"); printf("%s\n", qPrintable(timezoneString)); @@ -57,51 +59,55 @@ const char* stringForLogType(LogMsgType msgType) { const QString DATE_STRING_FORMAT = "MM/dd hh:mm:ss"; void LogHandler::flushRepeatedMessages() { + QMutexLocker locker(&_repeatedMessageLock); QHash::iterator message = _repeatMessageCountHash.begin(); while (message != _repeatMessageCountHash.end()) { - + if (message.value() > 0) { QString repeatMessage = QString("%1 repeated log entries matching \"%2\" - Last entry: \"%3\"") .arg(message.value()).arg(message.key()).arg(_lastRepeatedMessage.value(message.key())); - + QMessageLogContext emptyContext; printMessage(LogSuppressed, emptyContext, repeatMessage); } - + _lastRepeatedMessage.remove(message.key()); message = _repeatMessageCountHash.erase(message); } } QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& context, const QString& message) { - + if (message.isEmpty()) { return QString(); } - + if (type == LogDebug) { // for debug messages, check if this matches any of our regexes for repeated log messages + QMutexLocker locker(&_repeatedMessageLock); foreach(const QString& regexString, getInstance()._repeatedMessageRegexes) { QRegExp repeatRegex(regexString); if (repeatRegex.indexIn(message) != -1) { - + if (!_repeatMessageCountHash.contains(regexString)) { // we have a match but didn't have this yet - output the first one _repeatMessageCountHash[regexString] = 0; - + // break the foreach so we output the first match break; } else { // we have a match - add 1 to the count of repeats for this message and set this as the last repeated message _repeatMessageCountHash[regexString] += 1; _lastRepeatedMessage[regexString] = message; - + // return out, we're not printing this one return QString(); } } } - + } + if (type == LogDebug) { + QMutexLocker locker(&_onlyOnceMessageLock); // see if this message is one we should only print once foreach(const QString& regexString, getInstance()._onlyOnceMessageRegexes) { QRegExp onlyOnceRegex(regexString); @@ -118,23 +124,27 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont } } } - + // log prefix is in the following format - // [TIMESTAMP] [DEBUG] [PID] [TARGET] logged string - + // [TIMESTAMP] [DEBUG] [PID] [TID] [TARGET] logged string + QString prefixString = QString("[%1]").arg(QDateTime::currentDateTime().toString(DATE_STRING_FORMAT)); - + prefixString.append(QString(" [%1]").arg(stringForLogType(type))); - - if (_shouldOutputPID) { + + if (_shouldOutputProcessID) { prefixString.append(QString(" [%1]").arg(QCoreApplication::instance()->applicationPid())); - } - + + if (_shouldOutputThreadID) { + size_t threadID = (size_t)QThread::currentThreadId(); + prefixString.append(QString(" [%1]").arg(threadID)); + } + if (!_targetName.isEmpty()) { prefixString.append(QString(" [%1]").arg(_targetName)); } - + QString logMessage = QString("%1 %2").arg(prefixString, message.split("\n").join("\n" + prefixString + " ")); fprintf(stdout, "%s\n", qPrintable(logMessage)); return logMessage; @@ -143,3 +153,13 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont void LogHandler::verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { getInstance().printMessage((LogMsgType) type, context, message); } + +const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) { + QMutexLocker locker(&_repeatedMessageLock); + return *_repeatedMessageRegexes.insert(regexString); +} + +const QString& LogHandler::addOnlyOnceMessageRegex(const QString& regexString) { + QMutexLocker locker(&_onlyOnceMessageLock); + return *_onlyOnceMessageRegexes.insert(regexString); +} diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 6af721f96c..fff6ca43d6 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -34,34 +34,38 @@ class LogHandler : public QObject { Q_OBJECT public: static LogHandler& getInstance(); - + /// sets the target name to output via the verboseMessageHandler, called once before logging begins /// \param targetName the desired target name to output in logs void setTargetName(const QString& targetName) { _targetName = targetName; } - - void setShouldOutputPID(bool shouldOutputPID) { _shouldOutputPID = shouldOutputPID; } - + + void setShouldOutputProcessID(bool shouldOutputProcessID) { _shouldOutputProcessID = shouldOutputProcessID; } + void setShouldOutputThreadID(bool shouldOutputThreadID) { _shouldOutputThreadID = shouldOutputThreadID; } + QString printMessage(LogMsgType type, const QMessageLogContext& context, const QString &message); - + /// a qtMessageHandler that can be hooked up to a target that links to Qt /// prints various process, message type, and time information static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message); - - const QString& addRepeatedMessageRegex(const QString& regexString) { return *_repeatedMessageRegexes.insert(regexString); } - const QString& addOnlyOnceMessageRegex(const QString& regexString) { return *_onlyOnceMessageRegexes.insert(regexString); } + + const QString& addRepeatedMessageRegex(const QString& regexString); + const QString& addOnlyOnceMessageRegex(const QString& regexString); private: LogHandler(); - + void flushRepeatedMessages(); - + QString _targetName; - bool _shouldOutputPID; + bool _shouldOutputProcessID; + bool _shouldOutputThreadID; QSet _repeatedMessageRegexes; QHash _repeatMessageCountHash; QHash _lastRepeatedMessage; + QMutex _repeatedMessageLock; QSet _onlyOnceMessageRegexes; QHash _onlyOnceMessageCountHash; + QMutex _onlyOnceMessageLock; }; #endif // hifi_LogHandler_h From 2eb62f2fd89fb9c49107a72bdab9106dc00a8efa Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 30 Oct 2015 17:44:06 -0700 Subject: [PATCH 17/23] LogHandler: fix for linux build --- libraries/shared/src/LogHandler.cpp | 2 ++ libraries/shared/src/LogHandler.h | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index 0e05df277b..7dd1aceb3d 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "LogHandler.h" diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index fff6ca43d6..a74a6287d7 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -13,11 +13,11 @@ #ifndef hifi_LogHandler_h #define hifi_LogHandler_h -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include const int VERBOSE_LOG_INTERVAL_SECONDS = 5; From 46d87dda5a8d4f77e74718da6e43cd635a153903 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 30 Oct 2015 19:00:01 -0700 Subject: [PATCH 18/23] Fixing paths for SDL2 and Sixense libs --- cmake/externals/sdl2/CMakeLists.txt | 42 ++++++++++++++++++-------- cmake/externals/sixense/CMakeLists.txt | 12 ++++++++ libraries/entities/CMakeLists.txt | 2 +- libraries/procedural/CMakeLists.txt | 2 +- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index 0f44f28610..abd436d571 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -2,6 +2,8 @@ set(EXTERNAL_NAME sdl2) include(ExternalProject) +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} @@ -13,15 +15,33 @@ if (WIN32) LOG_DOWNLOAD 1 ) elseif (APPLE) - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/SDL2-2.0.3-OSX.tar.gz - URL_MD5 64f888886268bdf1656ef1b4b7d7756d - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 - ) + + ExternalProject_Add( + ${EXTERNAL_NAME} + URL https://hifi-public.s3.amazonaws.com/dependencies/SDL2-2.0.3.zip + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DVIDEO_OPENGL=OFF + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + ) + + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/SDL2 CACHE PATH "Location of SDL2 include directory") + set(${EXTERNAL_NAME_UPPER}_LIBRARY "${INSTALL_DIR}/lib/libSDL2-2.0.dylib" CACHE STRING "Path to SDL2 library") + + set(_SDL2_LIB_DIR "${INSTALL_DIR}/lib") + + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-install-name + COMMENT "Calling install_name_tool on SDL2 libraries to fix install name for dylib linking" + COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_SDL2_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake + DEPENDEES install + WORKING_DIRECTORY + LOG 1 + ) + else () if (ANDROID) set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") @@ -41,12 +61,8 @@ endif () # Hide this external target (for ide users) set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") -string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (APPLE) - ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/SDL2.framework/Headers CACHE PATH "Location of SDL2 include directory") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${SOURCE_DIR}/SDL2.framework/SDL2 CACHE STRING "Path to SDL2 library") elseif (WIN32) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/include CACHE PATH "Location of SDL2 include directory") diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index 72de4a7e15..dea15485dc 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -37,6 +37,18 @@ elseif(APPLE) set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx_x64/release_dll/libsixense_x64.dylib CACHE TYPE INTERNAL) + set(_SIXENSE_LIB_DIR "${SOURCE_DIR}/lib/osx_x64/release_dll") + + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-install-name-release + COMMENT "Calling install_name_tool on libraries to fix install name for dylib linking" + COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_SIXENSE_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake + DEPENDEES install + WORKING_DIRECTORY + LOG 1 + ) + elseif(NOT ANDROID) # FIXME need to account for different architectures diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index f6b2e0e280..26e90f5d41 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) -link_hifi_libraries(avatars shared octree gpu model fbx networking animation environment) +link_hifi_libraries(avatars shared audio octree gpu model fbx networking animation environment) target_bullet() diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index 0483b8d3a8..37c4fbfbe8 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME procedural) AUTOSCRIBE_SHADER_LIB(gpu model) setup_hifi_library() -link_hifi_libraries(shared gpu model model-networking) +link_hifi_libraries(shared gpu networking model model-networking) From 9b9e35d3963e556842c243da6bd8a33f2f9a4a26 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 30 Oct 2015 22:01:43 -0700 Subject: [PATCH 19/23] Limit sixense to mavericks and below --- cmake/externals/sixense/CMakeLists.txt | 21 ++++++++++++++----- cmake/modules/FindSixense.cmake | 4 ++++ .../src/input-plugins/SixenseManager.cpp | 8 +++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index dea15485dc..5edccb2c88 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -35,20 +35,31 @@ if (WIN32) elseif(APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx_x64/release_dll/libsixense_x64.dylib CACHE TYPE INTERNAL) - - set(_SIXENSE_LIB_DIR "${SOURCE_DIR}/lib/osx_x64/release_dll") - + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/lib/osx_x64/release_dll/libsixense_x64.dylib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/lib/osx_x64/debug_dll/libsixensed_x64.dylib CACHE TYPE INTERNAL) + + set(_SIXENSE_LIB_DIR "${SOURCE_DIR}/lib/osx_x64") ExternalProject_Add_Step( ${EXTERNAL_NAME} change-install-name-release COMMENT "Calling install_name_tool on libraries to fix install name for dylib linking" - COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_SIXENSE_LIB_DIR} -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake + COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_SIXENSE_LIB_DIR}/release_dll -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake DEPENDEES install WORKING_DIRECTORY LOG 1 ) + set(_SIXENSE_LIB_DIR "${SOURCE_DIR}/lib/osx_x64") + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-install-name-debug + COMMENT "Calling install_name_tool on libraries to fix install name for dylib linking" + COMMAND ${CMAKE_COMMAND} -DINSTALL_NAME_LIBRARY_DIR=${_SIXENSE_LIB_DIR}/debug_dll -P ${EXTERNAL_PROJECT_DIR}/OSXInstallNameChange.cmake + DEPENDEES install + WORKING_DIRECTORY + LOG 1 + ) + elseif(NOT ANDROID) # FIXME need to account for different architectures diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index 9abacac136..5a94d592d4 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -18,6 +18,10 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # +include(SelectLibraryConfigurations) +select_library_configurations(SIXENSE) + +set(SIXENSE_REQUIREMENTS SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Sixense DEFAULT_MSG SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES) mark_as_advanced(SIXENSE_LIBRARIES SIXENSE_INCLUDE_DIRS SIXENSE_SEARCH_DIRS) diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 2527da9e03..6cb58ced82 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -12,6 +12,8 @@ #include #include +#include +#include #include #include @@ -74,7 +76,13 @@ SixenseManager::SixenseManager() : bool SixenseManager::isSupported() const { #ifdef HAVE_SIXENSE + +#if defined(Q_OS_OSX) + return QSysInfo::macVersion() <= QSysInfo::MV_MAVERICKS; +#else return true; +#endif + #else return false; #endif From 0355a37fb147d8bc7b4dcc3a28129d4343edd3d8 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 30 Oct 2015 22:19:44 -0700 Subject: [PATCH 20/23] Fixing SDL2 active/inactive value --- libraries/input-plugins/src/input-plugins/SDL2Manager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp index 600dc5c56f..48864beedc 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp @@ -82,6 +82,7 @@ void SDL2Manager::activate() { emit joystickAdded(joystick.get()); } #endif + InputPlugin::activate(); } void SDL2Manager::deactivate() { @@ -92,6 +93,7 @@ void SDL2Manager::deactivate() { emit joystickRemoved(joystick.get()); } #endif + InputPlugin::deactivate(); } From aee03e79f390a6b60a474eedb9bcf4ecfd3a5e50 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 30 Oct 2015 22:37:00 -0700 Subject: [PATCH 21/23] Fix win32 and linux Sixense config --- cmake/externals/sixense/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index 5edccb2c88..07cf1c1163 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -30,7 +30,7 @@ if (WIN32) set(ARCH_SUFFIX "") endif() - set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${SOURCE_DIR}/lib/${ARCH_DIR}/VS2013/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${SOURCE_DIR}/lib/${ARCH_DIR}/VS2013/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL) add_paths_to_fixup_libs("${SOURCE_DIR}/bin/${ARCH_DIR}/VS2013/release_dll") elseif(APPLE) @@ -63,7 +63,7 @@ elseif(APPLE) elseif(NOT ANDROID) # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux_x64/release/libsixense_x64.so CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/lib/linux_x64/release/libsixense_x64.so CACHE TYPE INTERNAL) endif() From 224aeea04406d56ae901e14d7d1216c34ff592b6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 31 Oct 2015 08:11:43 -0700 Subject: [PATCH 22/23] quiet compiler --- libraries/animation/src/AnimVariant.cpp | 2 +- libraries/controllers/src/controllers/UserInputMapper.cpp | 4 ++-- libraries/controllers/src/controllers/impl/Endpoint.h | 3 ++- .../src/controllers/impl/conditionals/EndpointConditional.h | 2 +- .../controllers/src/controllers/impl/endpoints/AnyEndpoint.h | 1 + .../src/controllers/impl/endpoints/ArrayEndpoint.h | 1 + .../src/controllers/impl/endpoints/CompositeEndpoint.h | 1 + .../controllers/src/controllers/impl/endpoints/JSEndpoint.h | 1 + .../src/controllers/impl/endpoints/ScriptEndpoint.h | 1 + .../src/controllers/impl/endpoints/StandardEndpoint.h | 2 +- 10 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 8d320195dd..234e9cef09 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -44,7 +44,7 @@ QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine, break; default: // Note that we don't do mat4 in Javascript currently, and there's not yet a reason to start now. - assert("AnimVariant::Type" == "valid"); + assert(QString("AnimVariant::Type") == QString("valid")); } }; if (useNames) { // copy only the requested names diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index d33e215797..8e121de7fb 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -74,7 +74,7 @@ void UserInputMapper::registerDevice(InputDevice::Pointer device) { } const auto& deviceID = device->_deviceID; - int numberOfType = recordDeviceOfType(device->getName()); + recordDeviceOfType(device->getName()); qCDebug(controllers) << "Registered input device <" << device->getName() << "> deviceID = " << deviceID; for (const auto& inputMapping : device->getAvailableInputs()) { @@ -266,7 +266,7 @@ void UserInputMapper::update(float deltaTime) { } auto standardInputs = getStandardInputs(); - if (_lastStandardStates.size() != standardInputs.size()) { + if ((int)_lastStandardStates.size() != standardInputs.size()) { _lastStandardStates.resize(standardInputs.size()); for (auto& lastValue : _lastStandardStates) { lastValue = 0; diff --git a/libraries/controllers/src/controllers/impl/Endpoint.h b/libraries/controllers/src/controllers/impl/Endpoint.h index 5dd3f6adb4..bc604da2c5 100644 --- a/libraries/controllers/src/controllers/impl/Endpoint.h +++ b/libraries/controllers/src/controllers/impl/Endpoint.h @@ -40,7 +40,7 @@ namespace controller { virtual void apply(float value, const Pointer& source) = 0; virtual Pose pose() { return Pose(); } virtual void apply(const Pose& value, const Pointer& source) {} - virtual const bool isPose() { return _input.isPose(); } + virtual bool isPose() { return _input.isPose(); } virtual bool writeable() const { return true; } virtual bool readable() const { return true; } @@ -54,6 +54,7 @@ namespace controller { class LambdaEndpoint : public Endpoint { public: + using Endpoint::apply; LambdaEndpoint(ReadLambda readLambda, WriteLambda writeLambda = [](float) {}) : Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) { } diff --git a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h index 1e4205afc7..54ed57e871 100644 --- a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h +++ b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h @@ -18,7 +18,7 @@ namespace controller { class EndpointConditional : public Conditional { public: EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {} - virtual bool satisfied() override { return _endpoint && _endpoint->value() != 0.0; } + virtual bool satisfied() override { return _endpoint && _endpoint->value() != 0.0f; } private: Endpoint::Pointer _endpoint; }; diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h index 86dd057414..24834ce223 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h @@ -17,6 +17,7 @@ namespace controller { class AnyEndpoint : public Endpoint { friend class UserInputMapper; public: + using Endpoint::apply; AnyEndpoint(Endpoint::List children); virtual float value() override; virtual void apply(float newValue, const Endpoint::Pointer& source) override; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h index 79bb604ec0..899fa46de0 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h @@ -17,6 +17,7 @@ namespace controller { class ArrayEndpoint : public Endpoint { friend class UserInputMapper; public: + using Endpoint::apply; using Pointer = std::shared_ptr; ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { } diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h index c6ec90b7c8..b29266464c 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h @@ -15,6 +15,7 @@ namespace controller { class CompositeEndpoint : public Endpoint, Endpoint::Pair { public: + using Endpoint::apply; CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second); virtual float value() override; diff --git a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h index 27f17b5cd3..5113fef657 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h @@ -19,6 +19,7 @@ namespace controller { class JSEndpoint : public Endpoint { public: + using Endpoint::apply; JSEndpoint(const QJSValue& callable) : Endpoint(Input::INVALID_INPUT), _callable(callable) { } diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h index 23f77892c6..37160fcb48 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h @@ -19,6 +19,7 @@ namespace controller { class ScriptEndpoint : public Endpoint { Q_OBJECT; public: + using Endpoint::apply; ScriptEndpoint(const QScriptValue& callable) : Endpoint(Input::INVALID_INPUT), _callable(callable) { } diff --git a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h index 74adaf825d..7fe1a5467e 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h @@ -32,7 +32,7 @@ public: virtual void apply(float value, const Pointer& source) override { // For standard endpoints, the first NON-ZERO write counts. - if (value != 0.0) { + if (value != 0.0f) { _written = true; } VirtualEndpoint::apply(value, source); From 5916875345dcd51d16cfc484c5762295f40feac2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 31 Oct 2015 08:20:24 -0700 Subject: [PATCH 23/23] one more --- .../controllers/src/controllers/impl/filters/InvertFilter.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/controllers/src/controllers/impl/filters/InvertFilter.h b/libraries/controllers/src/controllers/impl/filters/InvertFilter.h index 889cd0140c..8acc9d56d6 100644 --- a/libraries/controllers/src/controllers/impl/filters/InvertFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/InvertFilter.h @@ -17,6 +17,7 @@ namespace controller { class InvertFilter : public ScaleFilter { REGISTER_FILTER_CLASS(InvertFilter); public: + using ScaleFilter::parseParameters; InvertFilter() : ScaleFilter(-1.0f) {} virtual bool parseParameters(const QJsonArray& parameters) { return true; }