From 0b867713cb416d11f4480e9f2e6376d0c7043674 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 2 May 2016 16:26:05 -0700 Subject: [PATCH 01/26] dressing room updates --- .../Home/dressingRoom/transformer.js | 35 ++++++++++++------- .../Home/dressingRoom/wrapper.js | 2 +- .../DomainContent/Home/reset.js | 25 ++++++++++--- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js b/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js index 404658cf6c..7b94120370 100644 --- a/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js +++ b/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js @@ -39,6 +39,20 @@ z: 0.2606 }; + var PRISCILLA_DIMENSIONS = { + //priscilla + x: 1.6448, + y: 1.6657, + z: 0.3078 + }; + + var MATTHEW_DIMENSIONS = { + //matthew + x: 1.8722, + y: 1.8197, + z: 0.3666 + } + var _this; function Transformer() { @@ -54,7 +68,6 @@ print('PRELOAD TRANSFORMER SCRIPT') this.entityID = entityID; this.initialProperties = Entities.getEntityProperties(entityID); - // this.transformationSound = SoundCache.getSound(TRANSFORMATION_SOUND_URL); }, collisionWithEntity: function(myID, otherID, collisionInfo) { @@ -69,14 +82,6 @@ } }, - // playTransformationSound: function(position) { - // print('transformer should play a sound') - // Audio.playSound(_this.transformationSound, { - // position: position, - // volume: 0.5 - // }); - // }, - findRotatorBlock: function() { print('transformer should find rotator block') var myProps = Entities.getEntityProperties(_this.entityID); @@ -89,7 +94,6 @@ return; } }); - }, removeCurrentBigVersion: function(rotatorBlock) { @@ -125,7 +129,6 @@ dimensions = WILL_DIMENSIONS; } else if (smallProps.modelURL.indexOf('being_of_light') > -1) { print('TRANSFORMER IS BEING OF LIGHT') - dimensions = BEING_OF_LIGHT_DIMENSIONS; } else if (smallProps.modelURL.indexOf('stylized_female') > -1) { print('TRANSFORMER IS ARTEMIS') @@ -133,6 +136,12 @@ } else if (smallProps.modelURL.indexOf('simple_robot') > -1) { print('TRANSFORMER IS A ROBOT') dimensions = ROBOT_DIMENSIONS; + } else if (smallProps.modelURL.indexOf('priscilla') > -1) { + print('TRANSFORMER IS PRISCILLA') + dimensions = PRISCILLA_DIMENSIONS; + } else if (smallProps.modelURL.indexOf('matthew') > -1) { + print('TRANSFORMER IS MATTHEW') + dimensions = MATTHEW_DIMENSIONS; } else { print('TRANSFORMER IS SOME OTHER'); dimensions = smallProps.naturalDimensions; @@ -156,8 +165,8 @@ }), } - if(bigVersionProps.modelURL.indexOf('simple_robot') > -1){ - bigVersionProps.position.y+=0.5; + if (bigVersionProps.modelURL.indexOf('simple_robot') > -1) { + bigVersionProps.position.y += 0.5; } var bigVersion = Entities.addEntity(bigVersionProps); diff --git a/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js b/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js index c1fe53e49b..458d5997f5 100644 --- a/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js +++ b/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js @@ -11,7 +11,7 @@ var TRANSFORMER_SCRIPT = Script.resolvePath('transformer.js'); - var AVATAR_COLLISION_HULL = 'atp:/dressingRoom/Avatar-Hull-4.obj'; + var AVATAR_COLLISION_HULL = 'atp:/dressingRoom/Avatar-Hull-5.obj'; TransformerDoll = function(modelURL, spawnPosition, spawnRotation, dimensions) { print('SCRIPT REF AT TRANSFORMER CREATE::' + TRANSFORMER_SCRIPT); diff --git a/unpublishedScripts/DomainContent/Home/reset.js b/unpublishedScripts/DomainContent/Home/reset.js index 5f548cfd19..a12b7101f9 100644 --- a/unpublishedScripts/DomainContent/Home/reset.js +++ b/unpublishedScripts/DomainContent/Home/reset.js @@ -68,9 +68,9 @@ var TRANSFORMER_URL_STYLIZED_FEMALE = 'atp:/dressingRoom/stylized_female.fbx'; - var TRANSFORMER_URL_REALISTIC_MALE = ''; + var TRANSFORMER_URL_PRISCILLA = 'atp:/dressingRoom/priscilla.fbx'; - var TRANSFORMER_URL_REALISTIC_FEMALE = ''; + var TRANSFORMER_URL_MATTHEW = 'atp:/dressingRoom/matthew.fbx'; Reset.prototype = { tidying: false, @@ -414,7 +414,6 @@ }; var dais = Entities.addEntity(daisProperties); - print('HOME created dais : ' + dais) }, createTransformers: function() { @@ -436,7 +435,9 @@ TRANSFORMER_URL_STYLIZED_FEMALE, TRANSFORMER_URL_ROBOT, TRANSFORMER_URL_BEING_OF_LIGHT, - TRANSFORMER_URL_WILL + TRANSFORMER_URL_WILL, + TRANSFORMER_URL_PRISCILLA, + TRANSFORMER_URL_MATTHEW ]; var dollDimensions = [{ @@ -459,6 +460,16 @@ x: 1.6326, y: 1.6764, z: 0.2606 + }, { + //priscilla + x: 1.6448, + y: 1.6657, + z: 0.3078 + }, { + //matthew + x: 1.8722, + y: 1.8197, + z: 0.3666 }]; var TRANSFORMER_SCALE = 0.25; @@ -474,7 +485,11 @@ var separation = index * dollLateralSeparation; var left = Quat.getRight(rotationAsQuat); var distanceToLeft = Vec3.multiply(separation, left); - var dollPosition = Vec3.sum(firstDollPosition, distanceToLeft) + var dollPosition = Vec3.sum(firstDollPosition, distanceToLeft); + if (index === 1) { + //special case for robot + dollPosition.y += 0.15; + } var transformer = new TransformerDoll(doll, dollPosition, dollRotation, dollDimensions[index]); }); From eb21b9c5d778675bbc431f1377d2b03ff7bf9072 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 2 May 2016 17:18:57 -0700 Subject: [PATCH 02/26] OSX warnings --- libraries/avatars/src/AvatarData.cpp | 1 - libraries/gl/src/gl/OglplusHelpers.cpp | 6 +++--- libraries/gl/src/gl/OglplusHelpers.h | 6 ++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 290aaff820..7db55d50e0 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -45,7 +45,6 @@ const glm::vec3 DEFAULT_LOCAL_AABOX_CORNER(-0.5f); const glm::vec3 DEFAULT_LOCAL_AABOX_SCALE(1.0f); const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData"; -static std::once_flag frameTypeRegistration; AvatarData::AvatarData() : SpatiallyNestable(NestableType::Avatar, QUuid()), diff --git a/libraries/gl/src/gl/OglplusHelpers.cpp b/libraries/gl/src/gl/OglplusHelpers.cpp index 220ea86646..5bf0298593 100644 --- a/libraries/gl/src/gl/OglplusHelpers.cpp +++ b/libraries/gl/src/gl/OglplusHelpers.cpp @@ -334,7 +334,7 @@ public: /// Returns the instructions for rendering of faces DrawingInstructions Instructions(PrimitiveType primitive) const { - DrawingInstructions instr = this->MakeInstructions(); + DrawingInstructions instr = MakeInstructions(); DrawOperation operation; operation.method = DrawOperation::Method::DrawElements; operation.mode = primitive; @@ -342,8 +342,8 @@ public: operation.count = _prim_count * 3; operation.restart_index = DrawOperation::NoRestartIndex(); operation.phase = 0; - this->AddInstruction(instr, operation); - return std::move(instr); + AddInstruction(instr, operation); + return instr; } /// Returns the instructions for rendering of faces diff --git a/libraries/gl/src/gl/OglplusHelpers.h b/libraries/gl/src/gl/OglplusHelpers.h index b599e8270d..afb06069b8 100644 --- a/libraries/gl/src/gl/OglplusHelpers.h +++ b/libraries/gl/src/gl/OglplusHelpers.h @@ -28,7 +28,11 @@ #ifdef _WIN32 #pragma warning(push) #pragma warning( disable : 4068 ) +#elif defined(Q_OS_MAC) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpessimizing-move" #endif + #include #include @@ -40,6 +44,8 @@ #ifdef _WIN32 #pragma warning(pop) +#elif defined(Q_OS_MAC) +#pragma clang diagnostic pop #endif #include "NumericalConstants.h" From 0bc89d6b18474a1d6514ecc2b2b42105da81af41 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 28 Apr 2016 10:52:09 -0700 Subject: [PATCH 03/26] Avoid missing pipeline log flood --- libraries/render/src/render/DrawTask.cpp | 4 ++-- libraries/render/src/render/ShapePipeline.cpp | 6 +++++- libraries/render/src/render/ShapePipeline.h | 10 ++++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 58b3a50e54..6d43d169c3 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -46,7 +46,7 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons } else if (key.hasOwnPipeline()) { item.render(args); } else { - qDebug() << "Item could not be rendered: invalid key ?" << key; + qDebug() << "Item could not be rendered with invalid key" << key; } } @@ -96,7 +96,7 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons } else if (key.hasOwnPipeline()) { ownPipelineBucket.push_back(item); } else { - qDebug() << "Item could not be rendered: invalid key ?" << key; + qDebug() << "Item could not be rendered with invalid key" << key; } } } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index b09d4b1356..a4ebdb30b6 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -93,7 +93,11 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke const auto& pipelineIterator = _pipelineMap.find(key); if (pipelineIterator == _pipelineMap.end()) { - qDebug() << "Couldn't find a pipeline from ShapeKey ?" << key; + // The first time we can't find a pipeline, we should log it + if (_missingKeys.find(key) == _missingKeys.end()) { + _missingKeys.insert(key); + qDebug() << "Couldn't find a pipeline for" << key; + } return PipelinePointer(nullptr); } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 22aa22d4c9..cf7d1c7c29 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -12,6 +12,8 @@ #ifndef hifi_render_ShapePipeline_h #define hifi_render_ShapePipeline_h +#include + #include #include @@ -147,7 +149,7 @@ public: bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } bool isValid() const { return !_flags[INVALID]; } - // Hasher for use in unordered_maps + // Comparator for use in stl containers class Hash { public: size_t operator() (const ShapeKey& key) const { @@ -155,7 +157,7 @@ public: } }; - // Comparator for use in unordered_maps + // Comparator for use in stl containers class KeyEqual { public: bool operator()(const ShapeKey& lhs, const ShapeKey& rhs) const { return lhs._flags == rhs._flags; } @@ -264,7 +266,11 @@ public: protected: void addPipelineHelper(const Filter& filter, Key key, int bit, const PipelinePointer& pipeline); PipelineMap _pipelineMap; + +private: + mutable std::unordered_set _missingKeys; }; + using ShapePlumberPointer = std::shared_ptr; } From d98732d5a1839724d2ae63825c664684c7f0d3f1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 3 May 2016 12:08:44 -0700 Subject: [PATCH 04/26] dressing room updates --- .../Home/dressingRoom/transformer.js | 20 +++++ .../Home/dressingRoom/wrapper.js | 88 ++++++++++--------- .../DomainContent/Home/reset.js | 20 ++--- 3 files changed, 77 insertions(+), 51 deletions(-) diff --git a/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js b/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js index 7b94120370..df8fdf0644 100644 --- a/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js +++ b/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js @@ -78,6 +78,26 @@ _this.locked = true; _this.findRotatorBlock(); } else { + var transformerProps = Entities.getEntityProperties(_this.entityID, ["rotation", "position"]); + var eulerRotation = Quat.safeEulerAngles(transformerProps.rotation); + eulerRotation.x = 0; + eulerRotation.z = 0; + var newRotation = Quat.fromVec3Degrees(eulerRotation); + + //we zero out the velocity and angular velocity so the cow doesn't change position or spin + Entities.editEntity(_this.entityID, { + rotation: newRotation, + velocity: { + x: 0, + y: 0, + z: 0 + }, + angularVelocity: { + x: 0, + y: 0, + z: 0 + } + }); return; } }, diff --git a/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js b/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js index 458d5997f5..570b326183 100644 --- a/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js +++ b/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js @@ -9,48 +9,54 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - var TRANSFORMER_SCRIPT = Script.resolvePath('transformer.js'); +var TRANSFORMER_SCRIPT = Script.resolvePath('transformer.js'); - var AVATAR_COLLISION_HULL = 'atp:/dressingRoom/Avatar-Hull-5.obj'; +var AVATAR_COLLISION_HULL = 'atp:/dressingRoom/Avatar-Hull-6.obj'; +var ROBOT_COLLISION_HULL = 'atp:/dressingRoom/robot_hull.obj'; +TransformerDoll = function(modelURL, spawnPosition, spawnRotation, dimensions) { + print('SCRIPT REF AT TRANSFORMER CREATE::' + TRANSFORMER_SCRIPT); + var transformerProps = { + name: 'hifi-home-dressing-room-little-transformer', + type: 'Model', + shapeType: 'compound', + compoundShapeURL: AVATAR_COLLISION_HULL, + position: spawnPosition, + rotation: Quat.fromPitchYawRollDegrees(spawnRotation.x, spawnRotation.y, spawnRotation.z), + modelURL: modelURL, + dynamic: true, + gravity: { + x: 0, + y: -10, + z: 0 + }, + visible: true, + restitution: 0.1, + damping: 0.9, + angularDamping: 0.9, + userData: JSON.stringify({ + 'grabbableKey': { + 'grabbable': true + }, + 'hifiHomeTransformerKey': { + 'basePosition': spawnPosition, + 'baseRotation': Quat.fromPitchYawRollDegrees(spawnRotation.x, spawnRotation.y, spawnRotation.z), + }, + 'hifiHomeKey': { + 'reset': true + } + }), + density: 7500, + dimensions: dimensions, + script: TRANSFORMER_SCRIPT + } - TransformerDoll = function(modelURL, spawnPosition, spawnRotation, dimensions) { - print('SCRIPT REF AT TRANSFORMER CREATE::' + TRANSFORMER_SCRIPT); - var transformerProps = { - name: 'hifi-home-dressing-room-little-transformer', - type: 'Model', - shapeType: 'compound', - compoundShapeURL: AVATAR_COLLISION_HULL, - position: spawnPosition, - rotation: Quat.fromPitchYawRollDegrees(spawnRotation.x, spawnRotation.y, spawnRotation.z), - modelURL: modelURL, - dynamic: true, - gravity: { - x: 0, - y: -10, - z: 0 - }, - visible: true, - damping: 0.8, - angularDamping: 0.8, - userData: JSON.stringify({ - 'grabbableKey': { - 'grabbable': true - }, - 'hifiHomeTransformerKey': { - 'basePosition': spawnPosition, - 'baseRotation': Quat.fromPitchYawRollDegrees(spawnRotation.x, spawnRotation.y, spawnRotation.z), - }, - 'hifiHomeKey': { - 'reset': true - } - }), - density: 5000, - dimensions: dimensions, - script: TRANSFORMER_SCRIPT - } - var transformer = Entities.addEntity(transformerProps); + if (modelURL.indexOf('robot') > -1) { + print('THIS IS A ROBOT, GIVE IT A DIFFERENT SHAPE TYPE') + transformerProps.compoundShapeURL =ROBOT_COLLISION_HULL; + } + var transformer = Entities.addEntity(transformerProps); - print('CREATED TRANSFORMER' + transformer); + print('CREATED TRANSFORMER' + transformer); - return this; - } \ No newline at end of file + return this; +} \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/reset.js b/unpublishedScripts/DomainContent/Home/reset.js index a12b7101f9..6f8dde1212 100644 --- a/unpublishedScripts/DomainContent/Home/reset.js +++ b/unpublishedScripts/DomainContent/Home/reset.js @@ -418,9 +418,9 @@ createTransformers: function() { var firstDollPosition = { - x: 1107.61, - y: 460.6, - z: -77.34 + x: 1107.6, + y: 460.575, + z: -77.37 } var dollRotation = { @@ -432,20 +432,15 @@ var rotationAsQuat = Quat.fromPitchYawRollDegrees(dollRotation.x, dollRotation.y, dollRotation.z); var dolls = [ - TRANSFORMER_URL_STYLIZED_FEMALE, TRANSFORMER_URL_ROBOT, TRANSFORMER_URL_BEING_OF_LIGHT, + TRANSFORMER_URL_STYLIZED_FEMALE, TRANSFORMER_URL_WILL, TRANSFORMER_URL_PRISCILLA, TRANSFORMER_URL_MATTHEW ]; var dollDimensions = [{ - //stylized female artemis - x: 1.6323, - y: 1.7705, - z: 0.2851 - }, { //robot x: 1.4439, y: 0.6224, @@ -455,6 +450,11 @@ x: 1.8838, y: 1.7865, z: 0.2955 + }, { + //stylized female artemis + x: 1.6323, + y: 1.7705, + z: 0.2851 }, { //will x: 1.6326, @@ -486,7 +486,7 @@ var left = Quat.getRight(rotationAsQuat); var distanceToLeft = Vec3.multiply(separation, left); var dollPosition = Vec3.sum(firstDollPosition, distanceToLeft); - if (index === 1) { + if (index === 0) { //special case for robot dollPosition.y += 0.15; } From ba226b9cb4ada063cbfd1d2b4a8fc9f26f878854 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 3 May 2016 13:40:05 -0700 Subject: [PATCH 05/26] promote priority immediately when already owned --- libraries/entities/src/EntityItem.cpp | 21 ++++++++++++++++++++- libraries/entities/src/EntityItem.h | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index dc017f81e6..efe01d3d82 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -655,7 +655,10 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (wantTerseEditLogging() && _simulationOwner != newSimOwner) { qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; } - if (_simulationOwner.set(newSimOwner)) { + if (weOwnSimulation && newSimOwner.getID().isNull() && _simulationOwner.getPriority() != 0) { + // entity-server is trying to clear our ownership, probably at our own request, but we've + // changed our minds since we sent it, therefore we ignore the ownerhip part of this update. + } else if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; somethingChanged = true; // recompute weOwnSimulation so that if this is the packet that tells use we are the owner, @@ -1112,6 +1115,22 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c properties._accelerationChanged = true; } +void EntityItem::pokeSimulationOwnership() { + _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE; + auto nodeList = DependencyManager::get(); + if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { + _simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY); + } +} + +void EntityItem::grabSimulationOwnership() { + _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB; + auto nodeList = DependencyManager::get(); + if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { + _simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY); + } +} + bool EntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 742ab337d0..661b25bbe8 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -373,8 +373,8 @@ public: void getAllTerseUpdateProperties(EntityItemProperties& properties) const; - void pokeSimulationOwnership() { _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE; } - void grabSimulationOwnership() { _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB; } + void pokeSimulationOwnership(); + void grabSimulationOwnership(); void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; } bool addAction(EntitySimulation* simulation, EntityActionPointer action); From bc04d1b4779ce391381fd3c864b22644f9be749a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 4 May 2016 09:01:26 +1200 Subject: [PATCH 06/26] Increase maximum friction value from 0.99 to 0.9999 --- libraries/entities/src/EntityItemPropertiesDefaults.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index aa4fb5c619..cfdc39dfd8 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -65,7 +65,7 @@ const float ENTITY_ITEM_MAX_RESTITUTION = 0.99f; const float ENTITY_ITEM_DEFAULT_RESTITUTION = 0.5f; const float ENTITY_ITEM_MIN_FRICTION = 0.0f; -const float ENTITY_ITEM_MAX_FRICTION = 0.99f; +const float ENTITY_ITEM_MAX_FRICTION = 0.9999f; const float ENTITY_ITEM_DEFAULT_FRICTION = 0.5f; const bool ENTITY_ITEM_DEFAULT_COLLISIONLESS = false; From d1064bf5ea7a84ce9c086c80d2811964675adc8a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 4 May 2016 10:58:33 +1200 Subject: [PATCH 07/26] Increase maximum friction to 1.0 - bullet can handle it --- libraries/entities/src/EntityItemPropertiesDefaults.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index cfdc39dfd8..ce5826af0d 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -65,7 +65,7 @@ const float ENTITY_ITEM_MAX_RESTITUTION = 0.99f; const float ENTITY_ITEM_DEFAULT_RESTITUTION = 0.5f; const float ENTITY_ITEM_MIN_FRICTION = 0.0f; -const float ENTITY_ITEM_MAX_FRICTION = 0.9999f; +const float ENTITY_ITEM_MAX_FRICTION = 1.0f; const float ENTITY_ITEM_DEFAULT_FRICTION = 0.5f; const bool ENTITY_ITEM_DEFAULT_COLLISIONLESS = false; From 284feaf5d437c2c7084f147581204fe8de000de3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 May 2016 20:29:31 -0700 Subject: [PATCH 08/26] Properly shut down scripting thread --- libraries/script-engine/src/ScriptEngine.cpp | 50 ++++++++++---------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 6d4747df2d..ec7bf89548 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -146,12 +146,15 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam ScriptEngine::~ScriptEngine() { qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename(); + auto scriptEngines = DependencyManager::get(); if (scriptEngines) { scriptEngines->removeScriptEngine(this); } else { qCWarning(scriptengine) << "Script destroyed after ScriptEngines!"; } + + waitTillDoneRunning(); } void ScriptEngine::disconnectNonEssentialSignals() { @@ -172,7 +175,7 @@ void ScriptEngine::runInThread() { } _isThreaded = true; - QThread* workerThread = new QThread(this); // thread is not owned, so we need to manage the delete + QThread* workerThread = new QThread(); QString scriptEngineName = QString("Script Thread:") + getFilename(); workerThread->setObjectName(scriptEngineName); @@ -194,35 +197,34 @@ void ScriptEngine::runInThread() { void ScriptEngine::waitTillDoneRunning() { // If the script never started running or finished running before we got here, we don't need to wait for it - if (_isRunning && _isThreaded) { - - // NOTE: waitTillDoneRunning() will be called on the main Application thread, inside of stopAllScripts() - // we want the application thread to continue to process events, because the scripts will likely need to - // marshall messages across to the main thread. For example if they access Settings or Menu in any of their - // shutdown code. + auto workerThread = thread(); + if (_isThreaded && workerThread) { QString scriptName = getFilename(); - auto startedWaiting = usecTimestampNow(); - while (thread()->isRunning()) { - // process events for the main application thread, allowing invokeMethod calls to pass between threads - QCoreApplication::processEvents(); - auto stillWaiting = usecTimestampNow(); - auto elapsedUsecs = stillWaiting - startedWaiting; - - // if we've been waiting a second or more, then tell the script engine to stop evaluating - static const auto MAX_SCRIPT_EVALUATION_TIME = USECS_PER_SECOND; - static const auto WAITING_TOO_LONG = MAX_SCRIPT_EVALUATION_TIME * 5; - // if we've been waiting for more than 5 seconds then we should be more aggessive about stopping - if (elapsedUsecs > WAITING_TOO_LONG) { - qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] quitting."; - thread()->quit(); + while (workerThread->isRunning()) { + // NOTE: This will be called on the main application thread from stopAllScripts. + // The application thread will need to continue to process events, because + // the scripts will likely need to marshall messages across to the main thread, e.g. + // if they access Settings or Menu in any of their shutdown code. So: + // Process events for the main application thread, allowing invokeMethod calls to pass between threads. + QCoreApplication::processEvents(); // thread-safe :) + + // If we've been waiting a second or more, then tell the script engine to stop evaluating + static const auto MAX_SCRIPT_EVALUATION_TIME = USECS_PER_SECOND; + auto elapsedUsecs = usecTimestampNow() - startedWaiting; + if (elapsedUsecs > MAX_SCRIPT_EVALUATION_TIME) { + qCDebug(scriptengine) << + "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] quitting."; + workerThread->quit(); break; - } else if (elapsedUsecs > MAX_SCRIPT_EVALUATION_TIME) { - qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] aborting evaluation."; - QMetaObject::invokeMethod(this, "abortEvaluation"); } + + // Avoid a pure busy wait + QThread::yieldCurrentThread(); } + + workerThread->deleteLater(); } } From 2c9608489f70ec36bdafc86c10ecc051cefc398d Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 4 May 2016 10:01:20 -0700 Subject: [PATCH 09/26] fix recursive mutex in Entites.callEntityMethod() --- libraries/entities/src/EntityScriptingInterface.cpp | 4 ++-- libraries/entities/src/EntityScriptingInterface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 9a4539ea9f..093fa73ace 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -415,12 +415,12 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { } void EntityScriptingInterface::setEntitiesScriptEngine(EntitiesScriptEngineProvider* engine) { - std::lock_guard lock(_entitiesScriptEngineLock); + std::lock_guard lock(_entitiesScriptEngineLock); _entitiesScriptEngine = engine; } void EntityScriptingInterface::callEntityMethod(QUuid id, const QString& method, const QStringList& params) { - std::lock_guard lock(_entitiesScriptEngineLock); + std::lock_guard lock(_entitiesScriptEngineLock); if (_entitiesScriptEngine) { EntityItemID entityID{ id }; _entitiesScriptEngine->callEntityScriptMethod(entityID, method, params); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index ca6e6fd9ac..e5f913dbf8 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -215,7 +215,7 @@ private: EntityTreePointer _entityTree; - std::mutex _entitiesScriptEngineLock; + std::recursive_mutex _entitiesScriptEngineLock; EntitiesScriptEngineProvider* _entitiesScriptEngine { nullptr }; bool _bidOnSimulationOwnership { false }; From 56ec0e5db0f84cc76673bcb4f275f62fed8d6915 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 4 May 2016 12:02:08 -0700 Subject: [PATCH 10/26] Abort infinite JS loops on quit --- libraries/script-engine/src/ScriptEngine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index ec7bf89548..6c7739c784 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -216,6 +216,7 @@ void ScriptEngine::waitTillDoneRunning() { if (elapsedUsecs > MAX_SCRIPT_EVALUATION_TIME) { qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] quitting."; + abortEvaluation(); // to allow the thread to quit workerThread->quit(); break; } From 83a767776698ff78d9b75a3063157eb1d3adb6f7 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 4 May 2016 12:28:09 -0700 Subject: [PATCH 11/26] update button position --- .../DomainContent/CellScience/Scripts/nav_button_cells.js | 4 ++-- .../CellScience/Scripts/nav_button_hexokinase.js | 4 ++-- .../CellScience/Scripts/nav_button_inside_the_cell.js | 4 ++-- .../DomainContent/CellScience/Scripts/nav_button_ribosome.js | 4 ++-- unpublishedScripts/DomainContent/CellScience/importNow.js | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_cells.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_cells.js index 343564c4e4..2253bb8068 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_cells.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_cells.js @@ -7,7 +7,7 @@ (function() { - var version = 12; + var version = 13; var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; var button; @@ -47,7 +47,7 @@ var buttonPadding = 10; var offset = 0; var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); - var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + var buttonPositionY = (windowDimensions.y - buttonHeight) - 150; button = Overlays.addOverlay("image", { x: buttonPositionX, y: buttonPositionY, diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_hexokinase.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_hexokinase.js index 6f704af7bd..7ca8de64a6 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_hexokinase.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_hexokinase.js @@ -13,7 +13,7 @@ (function() { - var version = 12; + var version = 13; var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; var button; @@ -53,7 +53,7 @@ var buttonPadding = 10; var offset = 3; var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); - var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + var buttonPositionY = (windowDimensions.y - buttonHeight) - 150; button = Overlays.addOverlay("image", { x: buttonPositionX, y: buttonPositionY, diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_inside_the_cell.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_inside_the_cell.js index 5e9faf3086..47cffa1a52 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_inside_the_cell.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_inside_the_cell.js @@ -7,7 +7,7 @@ (function() { - var version = 12; + var version = 13; var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; var button; @@ -47,7 +47,7 @@ var buttonPadding = 10; var offset = 1; var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); - var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + var buttonPositionY = (windowDimensions.y - buttonHeight) - 150; button = Overlays.addOverlay("image", { x: buttonPositionX, y: buttonPositionY, diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js index 4cbc375390..bb180371c0 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js @@ -6,7 +6,7 @@ // (function() { - var version = 12; + var version = 13; var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; var button; @@ -46,7 +46,7 @@ var buttonPadding = 10; var offset = 2; var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); - var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + var buttonPositionY = (windowDimensions.y - buttonHeight) - 150; button = Overlays.addOverlay("image", { x: buttonPositionX, y: buttonPositionY, diff --git a/unpublishedScripts/DomainContent/CellScience/importNow.js b/unpublishedScripts/DomainContent/CellScience/importNow.js index eb4c0e4b64..fed0f10124 100644 --- a/unpublishedScripts/DomainContent/CellScience/importNow.js +++ b/unpublishedScripts/DomainContent/CellScience/importNow.js @@ -5,7 +5,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var version = 1217; +var version = 1218; var WORLD_OFFSET = { x: 0, From e5ed5218e3618c570a2dd698bb0c66337f878a53 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 4 May 2016 12:30:07 -0700 Subject: [PATCH 12/26] fix ribsome --- .../CellScience/Scripts/nav_button_ribosome.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js index bb180371c0..95ec29a479 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js @@ -26,9 +26,9 @@ z: 3000 }, target: { - x: 3276.6, - y: 13703.3, - z: 4405.6 + x: 13500, + y: 3000, + z: 3000 }, preload: function(entityId) { print('CELL PRELOAD RIBOSOME 1') From 8d48f54313ad8f464ff6d1fbb163a6d27a495966 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Wed, 4 May 2016 12:41:33 -0700 Subject: [PATCH 13/26] fix ribosome location --- unpublishedScripts/DomainContent/CellScience/importNow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/DomainContent/CellScience/importNow.js b/unpublishedScripts/DomainContent/CellScience/importNow.js index fed0f10124..0d06e60954 100644 --- a/unpublishedScripts/DomainContent/CellScience/importNow.js +++ b/unpublishedScripts/DomainContent/CellScience/importNow.js @@ -5,7 +5,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var version = 1218; +var version = 1219; var WORLD_OFFSET = { x: 0, From 4b05d8ed951373cdf0e49147b1a695dbaa853c7c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 5 May 2016 07:50:15 +1200 Subject: [PATCH 14/26] Increase maximum friction to 10.0 - Bullet's maximum --- libraries/entities/src/EntityItemPropertiesDefaults.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index ce5826af0d..d5d44bb4a8 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -65,7 +65,7 @@ const float ENTITY_ITEM_MAX_RESTITUTION = 0.99f; const float ENTITY_ITEM_DEFAULT_RESTITUTION = 0.5f; const float ENTITY_ITEM_MIN_FRICTION = 0.0f; -const float ENTITY_ITEM_MAX_FRICTION = 1.0f; +const float ENTITY_ITEM_MAX_FRICTION = 10.0f; const float ENTITY_ITEM_DEFAULT_FRICTION = 0.5f; const bool ENTITY_ITEM_DEFAULT_COLLISIONLESS = false; From 0f6162d68389ec29d1c65c4f032938ffd7ecfdf8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 May 2016 15:32:08 -0700 Subject: [PATCH 15/26] Use appropriate units for timing tests --- interface/src/Util.cpp | 74 +++++++++++++---------- libraries/shared/src/NumericalConstants.h | 1 + 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 43c52916fe..073d0a18a8 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -136,66 +136,76 @@ void runTimingTests() { float fTest = 1.0; float* fResults = (float*)malloc(sizeof(float) * numTests); QElapsedTimer startTime; - startTime.start(); - float elapsedUsecs; + float elapsedNSecs; + float elapsedUSecs; - float NSEC_TO_USEC = 1.0f / 1000.0f; - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "QElapsedTimer::nsecElapsed() usecs: %f", (double)elapsedUsecs); + startTime.start(); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "QElapsedTimer::nsecElapsed() ns: %f", (double)elapsedNSecs); // Test sleep functions for accuracy startTime.start(); QThread::msleep(1); - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "QThread::msleep(1) ms: %f", (double)(elapsedUsecs / 1000.0f)); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "QThread::msleep(1) ms: %f", (double)(elapsedNSecs / NSECS_PER_MSEC)); startTime.start(); QThread::sleep(1); - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "QThread::sleep(1) ms: %f", (double)(elapsedUsecs / 1000.0f)); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "QThread::sleep(1) s: %f", (double)(elapsedNSecs / NSECS_PER_MSEC / MSECS_PER_SECOND)); startTime.start(); usleep(1); - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "usleep(1) ms: %f", (double)(elapsedUsecs / 1000.0f)); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(1) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); startTime.start(); usleep(10); - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "usleep(10) ms: %f", (double)(elapsedUsecs / 1000.0f)); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(10) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); startTime.start(); usleep(100); - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "usleep(100) ms: %f", (double)(elapsedUsecs / 1000.0f)); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(100) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); startTime.start(); usleep(1000); - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "usleep(1000) ms: %f", (double)(elapsedUsecs / 1000.0f)); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(1000) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + + startTime.start(); + usleep(1500); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(1500) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + + startTime.start(); + usleep(2500); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(2500) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); startTime.start(); usleep(15000); - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "usleep(15000) ms: %f", (double)(elapsedUsecs / 1000.0f)); + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(15000) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); // Random number generation startTime.start(); for (int i = 0; i < numTests; i++) { iResults[i] = rand(); } - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + elapsedUSecs = (float)startTime.nsecsElapsed() / NSECS_PER_USEC; qCDebug(interfaceapp, "rand() stored in array usecs: %f, first result:%d", - (double)(elapsedUsecs / numTests), iResults[0]); + (double)(elapsedUSecs / numTests), iResults[0]); // Random number generation using randFloat() startTime.start(); for (int i = 0; i < numTests; i++) { fResults[i] = randFloat(); } - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + elapsedUSecs = (float)startTime.nsecsElapsed() / NSECS_PER_USEC; qCDebug(interfaceapp, "randFloat() stored in array usecs: %f, first result: %f", - (double)(elapsedUsecs / numTests), (double)(fResults[0])); + (double)(elapsedUSecs / numTests), (double)(fResults[0])); free(iResults); free(fResults); @@ -206,8 +216,8 @@ void runTimingTests() { for (int i = 0; i < numTests; i++) { fTest = powf(fTest, 0.5f); } - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp, "powf(f, 0.5) usecs: %f", (double)(elapsedUsecs / (float) numTests)); + elapsedUSecs = (float)startTime.nsecsElapsed() / NSECS_PER_USEC; + qCDebug(interfaceapp, "powf(f, 0.5) usecs: %f", (double)(elapsedUSecs / (float) numTests)); // Vector Math float distance; @@ -218,9 +228,9 @@ void runTimingTests() { //float distanceSquared = glm::dot(temp, temp); distance = glm::distance(pointA, pointB); } - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + elapsedUSecs = (float)startTime.nsecsElapsed() / NSECS_PER_USEC; qCDebug(interfaceapp, "vector math usecs: %f [%f usecs total for %d tests], last result:%f", - (double)(elapsedUsecs / (float) numTests), (double)elapsedUsecs, numTests, (double)distance); + (double)(elapsedUSecs / (float) numTests), (double)elapsedUSecs, numTests, (double)distance); // Vec3 test glm::vec3 vecA(randVector()), vecB(randVector()); @@ -231,9 +241,9 @@ void runTimingTests() { glm::vec3 temp = vecA-vecB; result = glm::dot(temp,temp); } - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + elapsedUSecs = (float)startTime.nsecsElapsed() / NSECS_PER_USEC; qCDebug(interfaceapp, "vec3 assign and dot() usecs: %f, last result:%f", - (double)(elapsedUsecs / numTests), (double)result); + (double)(elapsedUSecs / numTests), (double)result); quint64 BYTE_CODE_MAX_TEST_VALUE = 99999999; @@ -265,9 +275,9 @@ void runTimingTests() { } } - elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; - qCDebug(interfaceapp) << "ByteCountCoded usecs: " << elapsedUsecs - << "per test:" << (double) (elapsedUsecs / tests) + elapsedUSecs = (float)startTime.nsecsElapsed() / NSECS_PER_USEC; + qCDebug(interfaceapp) << "ByteCountCoded usecs: " << elapsedUSecs + << "per test:" << (double) (elapsedUSecs / tests) << "tests:" << tests << "failed:" << failed; } diff --git a/libraries/shared/src/NumericalConstants.h b/libraries/shared/src/NumericalConstants.h index cf78f6dbf3..ca18d8ad5e 100644 --- a/libraries/shared/src/NumericalConstants.h +++ b/libraries/shared/src/NumericalConstants.h @@ -35,6 +35,7 @@ const float METERS_PER_CENTIMETER = 0.01f; const float METERS_PER_MILLIMETER = 0.001f; const float MILLIMETERS_PER_METER = 1000.0f; const quint64 NSECS_PER_USEC = 1000; +const quint64 NSECS_PER_MSEC = 1000000; const quint64 USECS_PER_MSEC = 1000; const quint64 MSECS_PER_SECOND = 1000; const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND; From 3619821b826115ae250d890bbc7b4da8ff28ed0e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 4 May 2016 12:44:11 -0700 Subject: [PATCH 16/26] Improve timing tests with averages --- interface/src/Util.cpp | 71 +++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 073d0a18a8..00715bcd69 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -131,63 +131,84 @@ const glm::vec3 randVector() { // Do some basic timing tests and report the results void runTimingTests() { // How long does it take to make a call to get the time? - const int numTests = 1000000; - int* iResults = (int*)malloc(sizeof(int) * numTests); - float fTest = 1.0; - float* fResults = (float*)malloc(sizeof(float) * numTests); + const int numTimingTests = 3; QElapsedTimer startTime; float elapsedNSecs; float elapsedUSecs; + qCDebug(interfaceapp, "numTimingTests: %d", numTimingTests); + startTime.start(); elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "QElapsedTimer::nsecElapsed() ns: %f", (double)elapsedNSecs); + qCDebug(interfaceapp, "QElapsedTimer::nsecElapsed() ns: %f", (double)elapsedNSecs / numTimingTests); // Test sleep functions for accuracy startTime.start(); - QThread::msleep(1); + for (int i = 0; i < numTimingTests; i++) { + QThread::msleep(1); + } elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "QThread::msleep(1) ms: %f", (double)(elapsedNSecs / NSECS_PER_MSEC)); + qCDebug(interfaceapp, "QThread::msleep(1) ms: %f", (double)(elapsedNSecs / NSECS_PER_MSEC / numTimingTests)); startTime.start(); - QThread::sleep(1); + for (int i = 0; i < numTimingTests; i++) { + QThread::sleep(1); + } elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "QThread::sleep(1) s: %f", (double)(elapsedNSecs / NSECS_PER_MSEC / MSECS_PER_SECOND)); + qCDebug(interfaceapp, "QThread::sleep(1) s: %f", (double)(elapsedNSecs / NSECS_PER_MSEC / MSECS_PER_SECOND / numTimingTests)); + + const int numUsecTests = 1000; + startTime.start(); + for (int i = 0; i < numUsecTests; i++) { + usleep(1); + } + elapsedNSecs = (float)startTime.nsecsElapsed(); + qCDebug(interfaceapp, "usleep(1) (1000x) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC / numUsecTests)); startTime.start(); - usleep(1); + for (int i = 0; i < numUsecTests; i++) { + usleep(10); + } elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "usleep(1) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + qCDebug(interfaceapp, "usleep(10) (1000x) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC / numUsecTests)); startTime.start(); - usleep(10); + for (int i = 0; i < numUsecTests; i++) { + usleep(100); + } elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "usleep(10) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + qCDebug(interfaceapp, "usleep(100) (1000x) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC / numUsecTests)); startTime.start(); - usleep(100); + for (int i = 0; i < numTimingTests; i++) { + usleep(1000); + } elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "usleep(100) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + qCDebug(interfaceapp, "usleep(1000) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC / numTimingTests)); startTime.start(); - usleep(1000); + for (int i = 0; i < numTimingTests; i++) { + usleep(1001); + } elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "usleep(1000) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + qCDebug(interfaceapp, "usleep(1001) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC / numTimingTests)); startTime.start(); - usleep(1500); + for (int i = 0; i < numTimingTests; i++) { + usleep(1500); + } elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "usleep(1500) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); - - startTime.start(); - usleep(2500); - elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "usleep(2500) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + qCDebug(interfaceapp, "usleep(1500) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC / numTimingTests)); startTime.start(); usleep(15000); elapsedNSecs = (float)startTime.nsecsElapsed(); - qCDebug(interfaceapp, "usleep(15000) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + qCDebug(interfaceapp, "usleep(15000) (1x) us: %f", (double)(elapsedNSecs / NSECS_PER_USEC)); + + const int numTests = 1000000; + int* iResults = (int*)malloc(sizeof(int) * numTests); + float fTest = 1.0; + float* fResults = (float*)malloc(sizeof(float) * numTests); // Random number generation startTime.start(); From 526143b097039dad5bee78f86b3c6018cef899cd Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 May 2016 16:25:09 -0700 Subject: [PATCH 17/26] Improve perf of Win32 usleep --- libraries/shared/src/SharedUtil.cpp | 32 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 7925c8ad4e..615ba26812 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -455,19 +455,29 @@ void printVoxelCode(unsigned char* voxelCode) { } #ifdef _WIN32 - void usleep(int waitTime) { - const quint64 BUSY_LOOP_USECS = 2000; - quint64 compTime = waitTime + usecTimestampNow(); - quint64 compTimeSleep = compTime - BUSY_LOOP_USECS; - while (true) { - if (usecTimestampNow() < compTimeSleep) { - QThread::msleep(1); - } - if (usecTimestampNow() >= compTime) { - break; - } +void usleep(int waitTime) { + quint64 sleepUntil = waitTime + usecTimestampNow(); + + // Busy wait with sleep/yield where possible + while (true) { + quint64 now = usecTimestampNow(); + if (now >= sleepUntil) { + break; + } + + // Sleep if we have at least 1ms to spare + const int MIN_SLEEP_USECS = 1000; + // msleep is allowed to overshoot, so give it a 100us berth + const int MIN_SLEEP_USECS_BERTH = 100; + if (sleepUntil - now > (MIN_SLEEP_USECS + MIN_SLEEP_USECS_BERTH)) { + unsigned long sleepFor = (sleepUntil - now - MIN_SLEEP_USECS_BERTH) / USECS_PER_MSEC; + QThread::msleep(sleepFor); + // Yield otherwise + } else { + QThread::yieldCurrentThread(); } } +} #endif // Inserts the value and key into three arrays sorted by the key array, the first array is the value, From 1553f532ba11c34da25829166f38e23585c5ccbf Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 4 May 2016 15:40:53 -0700 Subject: [PATCH 18/26] Specialize usleep for Win32 --- libraries/shared/src/SharedUtil.cpp | 31 +++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 615ba26812..b80fac637c 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -456,24 +456,39 @@ void printVoxelCode(unsigned char* voxelCode) { #ifdef _WIN32 void usleep(int waitTime) { - quint64 sleepUntil = waitTime + usecTimestampNow(); + // Use QueryPerformanceCounter for least overhead + LARGE_INTEGER now; // ticks + QueryPerformanceCounter(&now); + + static int64_t ticksPerSec = 0; + if (ticksPerSec == 0) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + ticksPerSec = frequency.QuadPart; + } + + // order ops to avoid loss in precision + int64_t waitTicks = (ticksPerSec * waitTime) / USECS_PER_SECOND; + int64_t sleepTicks = now.QuadPart + waitTicks; // Busy wait with sleep/yield where possible while (true) { - quint64 now = usecTimestampNow(); - if (now >= sleepUntil) { + QueryPerformanceCounter(&now); + if (now.QuadPart >= sleepTicks) { break; } // Sleep if we have at least 1ms to spare - const int MIN_SLEEP_USECS = 1000; + const int64_t MIN_SLEEP_USECS = 1000; // msleep is allowed to overshoot, so give it a 100us berth - const int MIN_SLEEP_USECS_BERTH = 100; - if (sleepUntil - now > (MIN_SLEEP_USECS + MIN_SLEEP_USECS_BERTH)) { - unsigned long sleepFor = (sleepUntil - now - MIN_SLEEP_USECS_BERTH) / USECS_PER_MSEC; - QThread::msleep(sleepFor); + const int64_t MIN_SLEEP_USECS_BERTH = 100; + // order ops to avoid loss in precision + int64_t sleepFor = ((sleepTicks - now.QuadPart) * USECS_PER_SECOND) / ticksPerSec - MIN_SLEEP_USECS_BERTH; + if (sleepFor > MIN_SLEEP_USECS) { + Sleep((DWORD)(sleepFor / USECS_PER_MSEC)); // Yield otherwise } else { + // Use Qt to delegate, as SwitchToThread is only supported starting with XP QThread::yieldCurrentThread(); } } From 7192ad301f1726c7de64f62e9aa5d2afc478ddf3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 4 May 2016 16:22:57 -0700 Subject: [PATCH 19/26] add debug for socket errors and state changes --- libraries/networking/src/udt/Socket.cpp | 15 +++++++++++++++ libraries/networking/src/udt/Socket.h | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index cf66847b6c..f51c3762ea 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -36,6 +36,11 @@ Socket::Socket(QObject* parent) : // start our timer for the synchronization time interval _synTimer->start(_synInterval); + + // make sure we hear about errors and state chagnes from the underlying socket + connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(handleSocketError(QAbstractSocket::SocketError))); + connect(&_udpSocket, &QAbstractSocket::stateChanged, this, &Socket::handleStateChanged); } void Socket::bind(const QHostAddress& address, quint16 port) { @@ -406,3 +411,13 @@ std::vector Socket::getConnectionSockAddrs() { } return addr; } + +void Socket::handleSocketError(QAbstractSocket::SocketError socketError) { + qWarning() << "udt::Socket error -" << socketError; +} + +void Socket::handleStateChanged(QAbstractSocket::SocketState socketState) { + if (socketState != QAbstractSocket::BoundState) { + qWarning() << "udt::Socket state changed - state is now" << socketState; + } +} diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index 35a32a034f..6b8ccf1fa8 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -86,7 +86,10 @@ public slots: private slots: void readPendingDatagrams(); void rateControlSync(); - + + void handleSocketError(QAbstractSocket::SocketError socketError); + void handleStateChanged(QAbstractSocket::SocketState socketState); + private: void setSystemBufferSizes(); Connection& findOrCreateConnection(const HifiSockAddr& sockAddr); From effa2fc23551748eb19a4146a2dac0e04ced4f27 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 4 May 2016 16:28:26 -0700 Subject: [PATCH 20/26] typo fix for comment --- libraries/networking/src/udt/Socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index f51c3762ea..4591f0d6b2 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -37,7 +37,7 @@ Socket::Socket(QObject* parent) : // start our timer for the synchronization time interval _synTimer->start(_synInterval); - // make sure we hear about errors and state chagnes from the underlying socket + // make sure we hear about errors and state changes from the underlying socket connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(handleSocketError(QAbstractSocket::SocketError))); connect(&_udpSocket, &QAbstractSocket::stateChanged, this, &Socket::handleStateChanged); From 8a3336ae95004e1225b4a2a7fb5a27e974ec84b3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 4 May 2016 16:31:12 -0700 Subject: [PATCH 21/26] use the networking logging category --- libraries/networking/src/udt/Socket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 4591f0d6b2..b3ddc24914 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -413,11 +413,11 @@ std::vector Socket::getConnectionSockAddrs() { } void Socket::handleSocketError(QAbstractSocket::SocketError socketError) { - qWarning() << "udt::Socket error -" << socketError; + qCWarning(networking) << "udt::Socket error -" << socketError; } void Socket::handleStateChanged(QAbstractSocket::SocketState socketState) { if (socketState != QAbstractSocket::BoundState) { - qWarning() << "udt::Socket state changed - state is now" << socketState; + qCWarning(networking) << "udt::Socket state changed - state is now" << socketState; } } From be9a572fb0fca6944600ca976eb5fc12a9f382af Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 4 May 2016 16:50:42 -0700 Subject: [PATCH 22/26] fix grab motion glitch on long-ping connections --- libraries/entities/src/EntityItem.cpp | 41 +++++++++++++++--- libraries/entities/src/EntityItem.h | 1 + libraries/entities/src/SimulationOwner.cpp | 48 +++++++++++++++++++-- libraries/entities/src/SimulationOwner.h | 21 ++++++--- libraries/physics/src/EntityMotionState.cpp | 8 +++- 5 files changed, 101 insertions(+), 18 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index efe01d3d82..bdedbbce77 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -655,14 +655,32 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (wantTerseEditLogging() && _simulationOwner != newSimOwner) { qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; } - if (weOwnSimulation && newSimOwner.getID().isNull() && _simulationOwner.getPriority() != 0) { - // entity-server is trying to clear our ownership, probably at our own request, but we've - // changed our minds since we sent it, therefore we ignore the ownerhip part of this update. + if (weOwnSimulation) { + if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) { + // entity-server is trying to clear our ownership (probably at our own request) + // but we actually want to own it, therefore we ignore this clear event + // and pretend that we own it (we assume we'll recover it soon) + } else if (_simulationOwner.set(newSimOwner)) { + _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + somethingChanged = true; + // recompute weOwnSimulation for later + weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); + } + } else if (newSimOwner.getID().isNull() && _simulationOwner.pendingTake(lastEditedFromBufferAdjusted)) { + // entity-server is trying to clear someone else's ownership + // but we want to own it, therefore we ignore this clear event + // and pretend that we own it (we assume we'll get it soon) + weOwnSimulation = true; + if (!_simulationOwner.isNull()) { + // someone else really did own it + _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + somethingChanged = true; + _simulationOwner.clearCurrentOwner(); + } } else if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; somethingChanged = true; - // recompute weOwnSimulation so that if this is the packet that tells use we are the owner, - // we ignore the physics changes from this packet. + // recompute weOwnSimulation for later weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); } } @@ -1119,7 +1137,11 @@ void EntityItem::pokeSimulationOwnership() { _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE; auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { + // we already own it _simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY); + } else { + // we don't own it yet + _simulationOwner.setPendingPriority(SCRIPT_POKE_SIMULATION_PRIORITY, usecTimestampNow()); } } @@ -1127,7 +1149,11 @@ void EntityItem::grabSimulationOwnership() { _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB; auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { + // we already own it _simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY); + } else { + // we don't own it yet + _simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow()); } } @@ -1665,11 +1691,14 @@ void EntityItem::clearSimulationOwnership() { _simulationOwner.clear(); // don't bother setting the DIRTY_SIMULATOR_ID flag because clearSimulationOwnership() - // is only ever called entity-server-side and the flags are only used client-side + // is only ever called on the entity-server and the flags are only used client-side //_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; } +void EntityItem::setPendingOwnershipPriority(quint8 priority, const quint64& timestamp) { + _simulationOwner.setPendingPriority(priority, timestamp); +} bool EntityItem::addAction(EntitySimulation* simulation, EntityActionPointer action) { bool result; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 661b25bbe8..ecb9800e70 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -302,6 +302,7 @@ public: QUuid getSimulatorID() const { return _simulationOwner.getID(); } void updateSimulationOwner(const SimulationOwner& owner); void clearSimulationOwnership(); + void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp); const QString& getMarketplaceID() const { return _marketplaceID; } void setMarketplaceID(const QString& value) { _marketplaceID = value; } diff --git a/libraries/entities/src/SimulationOwner.cpp b/libraries/entities/src/SimulationOwner.cpp index 2db9f2a122..43bece93ae 100644 --- a/libraries/entities/src/SimulationOwner.cpp +++ b/libraries/entities/src/SimulationOwner.cpp @@ -16,12 +16,30 @@ #include +const quint8 PENDING_STATE_NOTHING = 0; +const quint8 PENDING_STATE_TAKE = 1; +const quint8 PENDING_STATE_RELEASE = 2; + // static const int SimulationOwner::NUM_BYTES_ENCODED = NUM_BYTES_RFC4122_UUID + 1; +SimulationOwner::SimulationOwner() : + _id(), + _expiry(0), + _pendingTimestamp(0), + _priority(0), + _pendingPriority(0), + _pendingState(PENDING_STATE_NOTHING) +{ +} -SimulationOwner::SimulationOwner(const SimulationOwner& other) - : _id(other._id), _priority(other._priority), _expiry(other._expiry) { +SimulationOwner::SimulationOwner(const QUuid& id, quint8 priority) : + _id(id), + _expiry(0), + _pendingTimestamp(0), + _priority(priority), + _pendingPriority(0) +{ } QByteArray SimulationOwner::toByteArray() const { @@ -42,8 +60,11 @@ bool SimulationOwner::fromByteArray(const QByteArray& data) { void SimulationOwner::clear() { _id = QUuid(); - _priority = 0; _expiry = 0; + _pendingTimestamp = 0; + _priority = 0; + _pendingPriority = 0; + _pendingState = PENDING_STATE_NOTHING; } void SimulationOwner::setPriority(quint8 priority) { @@ -53,7 +74,6 @@ void SimulationOwner::setPriority(quint8 priority) { void SimulationOwner::promotePriority(quint8 priority) { if (priority > _priority) { _priority = priority; - updateExpiry(); } } @@ -81,11 +101,31 @@ bool SimulationOwner::set(const SimulationOwner& owner) { return setID(owner._id) || oldPriority != _priority; } +void SimulationOwner::setPendingPriority(quint8 priority, const quint64& timestamp) { + _pendingPriority = priority; + _pendingTimestamp = timestamp; + _pendingState = (_pendingPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE; +} + void SimulationOwner::updateExpiry() { const quint64 OWNERSHIP_LOCKOUT_EXPIRY = USECS_PER_SECOND / 5; _expiry = usecTimestampNow() + OWNERSHIP_LOCKOUT_EXPIRY; } +bool SimulationOwner::pendingRelease(const quint64& timestamp) { + return _pendingPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingTimestamp > timestamp; +} + +bool SimulationOwner::pendingTake(const quint64& timestamp) { + return _pendingPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingTimestamp > timestamp; +} + +void SimulationOwner::clearCurrentOwner() { + _id = QUuid(); + _expiry = 0; + _priority = 0; +} + // NOTE: eventually this code will be moved into unit tests // static debug void SimulationOwner::test() { diff --git a/libraries/entities/src/SimulationOwner.h b/libraries/entities/src/SimulationOwner.h index 242d0eb272..1afec426d7 100644 --- a/libraries/entities/src/SimulationOwner.h +++ b/libraries/entities/src/SimulationOwner.h @@ -37,13 +37,12 @@ class SimulationOwner { public: static const int NUM_BYTES_ENCODED; - SimulationOwner() : _id(), _priority(0), _expiry(0) {} - SimulationOwner(const QUuid& id, quint8 priority) : _id(id), _priority(priority), _expiry(0) {} - SimulationOwner(const SimulationOwner& other); + SimulationOwner(); + SimulationOwner(const QUuid& id, quint8 priority); const QUuid& getID() const { return _id; } - quint8 getPriority() const { return _priority; } const quint64& getExpiry() const { return _expiry; } + quint8 getPriority() const { return _priority; } QByteArray toByteArray() const; bool fromByteArray(const QByteArray& data); @@ -57,6 +56,7 @@ public: bool setID(const QUuid& id); bool set(const QUuid& id, quint8 priority); bool set(const SimulationOwner& owner); + void setPendingPriority(quint8 priority, const quint64& timestamp); bool isNull() const { return _id.isNull(); } bool matchesValidID(const QUuid& id) const { return _id == id && !_id.isNull(); } @@ -65,6 +65,10 @@ public: bool hasExpired() const { return usecTimestampNow() > _expiry; } + bool pendingRelease(const quint64& timestamp); // return true if valid pending RELEASE + bool pendingTake(const quint64& timestamp); // return true if valid pending TAKE + void clearCurrentOwner(); + bool operator>=(quint8 priority) const { return _priority >= priority; } bool operator==(const SimulationOwner& other) { return (_id == other._id && _priority == other._priority); } @@ -77,9 +81,12 @@ public: static void test(); private: - QUuid _id; - quint8 _priority; - quint64 _expiry; + QUuid _id; // owner + quint64 _expiry; // time when ownership can transition at equal priority + quint64 _pendingTimestamp; // time when pending update was set + quint8 _priority; // priority of current owner + quint8 _pendingPriority; // priority of pendingTake + quint8 _pendingState; // NOTHING, TAKE, or RELEASE }; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index fbec7cd3e0..db76b1727c 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -519,12 +519,17 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ // but we remember we do still own it... and rely on the server to tell us we don't properties.clearSimulationOwner(); _outgoingPriority = 0; + _entity->setPendingOwnershipPriority(_outgoingPriority, now); } else if (Physics::getSessionUUID() != _entity->getSimulatorID()) { // we don't own the simulation for this entity yet, but we're sending a bid for it + quint8 bidPriority = glm::max(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY); properties.setSimulationOwner(Physics::getSessionUUID(), glm::max(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY)); _nextOwnershipBid = now + USECS_BETWEEN_OWNERSHIP_BIDS; - _outgoingPriority = 0; // reset outgoing priority whenever we bid + // copy _outgoingPriority into pendingPriority... + _entity->setPendingOwnershipPriority(_outgoingPriority, now); + // ...then reset _outgoingPriority in preparation for the next frame + _outgoingPriority = 0; } else if (_outgoingPriority != _entity->getSimulationPriority()) { // we own the simulation but our desired priority has changed if (_outgoingPriority == 0) { @@ -534,6 +539,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ // we just need to change the priority properties.setSimulationOwner(Physics::getSessionUUID(), _outgoingPriority); } + _entity->setPendingOwnershipPriority(_outgoingPriority, now); } EntityItemID id(_entity->getID()); From 3202a723b8e4d091ce425d0da685bee5569cefe8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 May 2016 08:54:09 -0700 Subject: [PATCH 23/26] remove warning about unused variable --- libraries/physics/src/EntityMotionState.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index db76b1727c..f0539110d3 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -523,8 +523,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ } else if (Physics::getSessionUUID() != _entity->getSimulatorID()) { // we don't own the simulation for this entity yet, but we're sending a bid for it quint8 bidPriority = glm::max(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY); - properties.setSimulationOwner(Physics::getSessionUUID(), - glm::max(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY)); + properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority); _nextOwnershipBid = now + USECS_BETWEEN_OWNERSHIP_BIDS; // copy _outgoingPriority into pendingPriority... _entity->setPendingOwnershipPriority(_outgoingPriority, now); From 6d3a3b0cc5c0039fa0ca1fbb569b557c0c7b89df Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 5 May 2016 10:37:32 -0700 Subject: [PATCH 24/26] cleanup comments, semicolons --- .../Home/dressingRoom/transformer.js | 45 +++++++++---------- .../Home/dressingRoom/wrapper.js | 11 +++-- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js b/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js index df8fdf0644..78caec3d80 100644 --- a/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js +++ b/unpublishedScripts/DomainContent/Home/dressingRoom/transformer.js @@ -25,14 +25,15 @@ x: 1.8838, y: 1.7865, z: 0.2955 - } + }; var ROBOT_DIMENSIONS = { //robot x: 1.4439, y: 0.6224, z: 0.4998 - } + }; + var WILL_DIMENSIONS = { x: 1.6326, y: 1.6764, @@ -51,14 +52,14 @@ x: 1.8722, y: 1.8197, z: 0.3666 - } + }; var _this; function Transformer() { _this = this; return this; - } + }; Transformer.prototype = { locked: false, @@ -74,11 +75,11 @@ var otherProps = Entities.getEntityProperties(otherID); if (otherProps.name === "hifi-home-dressing-room-transformer-collider" && _this.locked === false) { - print('UNLOCKED TRANSFORMER COLLIDED WITH BASE!! THE AVATAR WHO SIMULATED THIS COLLISION IS:: ' + MyAvatar.sessionUUID); _this.locked = true; _this.findRotatorBlock(); } else { var transformerProps = Entities.getEntityProperties(_this.entityID, ["rotation", "position"]); + var eulerRotation = Quat.safeEulerAngles(transformerProps.rotation); eulerRotation.x = 0; eulerRotation.z = 0; @@ -98,14 +99,15 @@ z: 0 } }); + return; } }, findRotatorBlock: function() { - print('transformer should find rotator block') var myProps = Entities.getEntityProperties(_this.entityID); var results = Entities.findEntities(myProps.position, 10); + results.forEach(function(result) { var resultProps = Entities.getEntityProperties(result); if (resultProps.name === "hifi-home-dressing-room-rotator-block") { @@ -117,10 +119,10 @@ }, removeCurrentBigVersion: function(rotatorBlock) { - print('transformer should remove big version') var blacklistKey = 'Hifi-Hand-RayPick-Blacklist'; var myProps = Entities.getEntityProperties(_this.entityID); var results = Entities.findEntities(myProps.position, 10); + results.forEach(function(result) { var resultProps = Entities.getEntityProperties(result); if (resultProps.name === "hifi-home-dressing-room-big-transformer") { @@ -134,36 +136,35 @@ return; } }); + _this.createBigVersion(); }, createBigVersion: function() { var smallProps = Entities.getEntityProperties(_this.entityID); - print('transformer should create big version!!' + smallProps.modelURL); - print('transformer has rotatorBlock??' + _this.rotatorBlock); var rotatorProps = Entities.getEntityProperties(_this.rotatorBlock); var dimensions; if (smallProps.modelURL.indexOf('will') > -1) { - print('TRANSFORMER IS WILL') + // print('TRANSFORMER IS WILL'); dimensions = WILL_DIMENSIONS; } else if (smallProps.modelURL.indexOf('being_of_light') > -1) { - print('TRANSFORMER IS BEING OF LIGHT') + // print('TRANSFORMER IS BEING OF LIGHT'); dimensions = BEING_OF_LIGHT_DIMENSIONS; } else if (smallProps.modelURL.indexOf('stylized_female') > -1) { - print('TRANSFORMER IS ARTEMIS') + // print('TRANSFORMER IS ARTEMIS'); dimensions = STYLIZED_FEMALE_DIMENSIONS; } else if (smallProps.modelURL.indexOf('simple_robot') > -1) { - print('TRANSFORMER IS A ROBOT') + // print('TRANSFORMER IS A ROBOT'); dimensions = ROBOT_DIMENSIONS; } else if (smallProps.modelURL.indexOf('priscilla') > -1) { - print('TRANSFORMER IS PRISCILLA') + // print('TRANSFORMER IS PRISCILLA'); dimensions = PRISCILLA_DIMENSIONS; } else if (smallProps.modelURL.indexOf('matthew') > -1) { - print('TRANSFORMER IS MATTHEW') + // print('TRANSFORMER IS MATTHEW'); dimensions = MATTHEW_DIMENSIONS; } else { - print('TRANSFORMER IS SOME OTHER'); + // print('TRANSFORMER IS SOME OTHER'); dimensions = smallProps.naturalDimensions; } @@ -183,14 +184,13 @@ 'reset': true } }), - } + }; if (bigVersionProps.modelURL.indexOf('simple_robot') > -1) { bigVersionProps.position.y += 0.5; } var bigVersion = Entities.addEntity(bigVersionProps); - print('transformer created big version: ' + bigVersion); var blacklistKey = 'Hifi-Hand-RayPick-Blacklist'; Messages.sendMessage(blacklistKey, JSON.stringify({ @@ -202,12 +202,10 @@ }, putTransformerOnRotatorBlock: function(blockPosition) { - print('transformer should get set on rotator block') - return blockPosition + return blockPosition; }, putNewVersionOnShelf: function() { - print('transformer should out a new version of itself on the shelf') var littleVersionProps = Entities.getEntityProperties(_this.entityID); delete littleVersionProps.id; delete littleVersionProps.created; @@ -218,23 +216,24 @@ delete littleVersionProps.localPosition; delete littleVersionProps.localRotation; delete littleVersionProps.naturalPosition; - // delete littleVersionProps.script; littleVersionProps.gravity = { x: 0, y: -10, z: 0 }; var userData = JSON.parse(littleVersionProps.userData); + var basePosition = userData["hifiHomeTransformerKey"].basePosition; var baseRotation = userData["hifiHomeTransformerKey"].baseRotation; + littleVersionProps.position = basePosition; littleVersionProps.rotation = baseRotation; var littleTransformer = Entities.addEntity(littleVersionProps); + _this.removeSelf(); }, removeSelf: function() { - print('transformer should remove itself') var success = Entities.deleteEntity(_this.entityID); }, }; diff --git a/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js b/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js index 570b326183..4b2793966a 100644 --- a/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js +++ b/unpublishedScripts/DomainContent/Home/dressingRoom/wrapper.js @@ -13,8 +13,9 @@ var TRANSFORMER_SCRIPT = Script.resolvePath('transformer.js'); var AVATAR_COLLISION_HULL = 'atp:/dressingRoom/Avatar-Hull-6.obj'; var ROBOT_COLLISION_HULL = 'atp:/dressingRoom/robot_hull.obj'; + TransformerDoll = function(modelURL, spawnPosition, spawnRotation, dimensions) { - print('SCRIPT REF AT TRANSFORMER CREATE::' + TRANSFORMER_SCRIPT); + var transformerProps = { name: 'hifi-home-dressing-room-little-transformer', type: 'Model', @@ -48,15 +49,13 @@ TransformerDoll = function(modelURL, spawnPosition, spawnRotation, dimensions) { density: 7500, dimensions: dimensions, script: TRANSFORMER_SCRIPT - } + }; if (modelURL.indexOf('robot') > -1) { - print('THIS IS A ROBOT, GIVE IT A DIFFERENT SHAPE TYPE') - transformerProps.compoundShapeURL =ROBOT_COLLISION_HULL; + transformerProps.compoundShapeURL = ROBOT_COLLISION_HULL; } - var transformer = Entities.addEntity(transformerProps); - print('CREATED TRANSFORMER' + transformer); + var transformer = Entities.addEntity(transformerProps); return this; } \ No newline at end of file From 967a67256e9cf7bcf2c8b4f0acebeaf0698201e8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 May 2016 10:52:53 -0700 Subject: [PATCH 25/26] fix bug preventing sim ownership release --- libraries/entities/src/SimulationOwner.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/SimulationOwner.cpp b/libraries/entities/src/SimulationOwner.cpp index 43bece93ae..77645a9e62 100644 --- a/libraries/entities/src/SimulationOwner.cpp +++ b/libraries/entities/src/SimulationOwner.cpp @@ -113,11 +113,11 @@ void SimulationOwner::updateExpiry() { } bool SimulationOwner::pendingRelease(const quint64& timestamp) { - return _pendingPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingTimestamp > timestamp; + return _pendingPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingTimestamp >= timestamp; } bool SimulationOwner::pendingTake(const quint64& timestamp) { - return _pendingPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingTimestamp > timestamp; + return _pendingPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingTimestamp >= timestamp; } void SimulationOwner::clearCurrentOwner() { From f65b15803a48335e847d52233fdae71e2c7650de Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 May 2016 15:04:39 -0700 Subject: [PATCH 26/26] Fix potential iterator invalidation --- libraries/physics/src/PhysicsEngine.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 5523abf4e2..d3247ec62c 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -225,9 +225,7 @@ void PhysicsEngine::removeContacts(ObjectMotionState* motionState) { ContactMap::iterator contactItr = _contactMap.begin(); while (contactItr != _contactMap.end()) { if (contactItr->first._a == motionState || contactItr->first._b == motionState) { - ContactMap::iterator iterToDelete = contactItr; - ++contactItr; - _contactMap.erase(iterToDelete); + contactItr = _contactMap.erase(contactItr); } else { ++contactItr; } @@ -386,9 +384,7 @@ const CollisionEvents& PhysicsEngine::getCollisionEvents() { } if (type == CONTACT_EVENT_TYPE_END) { - ContactMap::iterator iterToDelete = contactItr; - ++contactItr; - _contactMap.erase(iterToDelete); + contactItr = _contactMap.erase(contactItr); } else { ++contactItr; }