From 47f7d55e2c5481f5c158beec2e91cdb7b211a27e Mon Sep 17 00:00:00 2001 From: "Babiuch, Ryan Nicholas" Date: Mon, 1 Feb 2016 08:32:52 -0600 Subject: [PATCH 1/5] Working energy usage for entity manipulation. - Working example in examples/example/ui/MyEnergyBar.js --- examples/example/ui/MyEnergyBar.js | 67 +++++++++++++++++++ examples/example/ui/energyBar.js | 44 ++---------- interface/src/avatar/MyAvatar.cpp | 44 +++++++++++- interface/src/avatar/MyAvatar.h | 16 +++++ .../entities/src/EntityScriptingInterface.cpp | 59 +++++++++++++++- .../entities/src/EntityScriptingInterface.h | 14 +++- 6 files changed, 202 insertions(+), 42 deletions(-) create mode 100644 examples/example/ui/MyEnergyBar.js diff --git a/examples/example/ui/MyEnergyBar.js b/examples/example/ui/MyEnergyBar.js new file mode 100644 index 0000000000..ac7ef0d39c --- /dev/null +++ b/examples/example/ui/MyEnergyBar.js @@ -0,0 +1,67 @@ +Script.include("../../libraries/utils.js"); +var energyColor = {red: 0, green: 200, blue: 0}; +var lowEnergyColor = {red: 255, green: 0, blue: 0}; +var totalWidth = 200; +var paddingRight = 50; +var xPosition = Window.innerWidth - totalWidth - paddingRight; +var lowEnergyThreshold = 0.3; +var currentEnergy = 1.0; +var energyLossRate = 0.003; +var energyChargeRate = 0.003; +var isGrabbing = false; +var refractoryPeriod = 2000; + +var lastAvatarVelocity = MyAvatar.getVelocity(); +var lastAvatarPosition = MyAvatar.position; + +var background = Overlays.addOverlay("text", { + x: xPosition, + y: 20, + width: totalWidth, + height: 10, + backgroundColor: {red: 255, green: 0, blue: 0} +}) + +var bar = Overlays.addOverlay("text", { + x: xPosition, + y: 20, + width: totalWidth, + height: 10, + backgroundColor: energyColor +}); + + +// Takes an energy value between 0 and 1 and sets energy bar width appropriately +function setEnergy(energy) { + energy = clamp(energy, 0, 1); + var barWidth = totalWidth * energy; + var color = energy <= lowEnergyThreshold ? lowEnergyColor: energyColor; + Overlays.editOverlay(bar, { width: barWidth, backgroundColor: color}); +} + +function update() { + currentEnergy = clamp(MyAvatar.energy, 0, 1); + setEnergy(currentEnergy); +} + +function cleanup() { + Overlays.deleteOverlay(background); + Overlays.deleteOverlay(bar); +} + +function energyChanged(newValue) { + Entities.currentAvatarEnergy = newValue; +} + +function debitAvatarEnergy(value) { + MyAvatar.energy = MyAvatar.energy - value; +} +function calculateCost(mass, oldVelocity, newVelocity) { + return mass * (newVelocity - oldVelocity); +} + +Entities.addCostFunction(calculateCost); +Entities.debitEnergySource.connect(debitAvatarEnergy); +MyAvatar.energyChanged.connect(energyChanged); +Script.update.connect(update); +Script.scriptEnding.connect(cleanup); diff --git a/examples/example/ui/energyBar.js b/examples/example/ui/energyBar.js index a45b09f6d4..498eef2751 100644 --- a/examples/example/ui/energyBar.js +++ b/examples/example/ui/energyBar.js @@ -51,45 +51,8 @@ function setEnergy(energy) { Overlays.editOverlay(bar, { width: barWidth, backgroundColor: color}); } -function avatarAccelerationEnergy() { - var AVATAR_MOVEMENT_ENERGY_CONSTANT = 0.001; - var velocity = MyAvatar.getVelocity(); - var dV = Math.abs(Vec3.length(velocity) - Vec3.length(lastAvatarVelocity)); - var dE = Vec3.length(lastAvatarVelocity) * dV * AVATAR_MOVEMENT_ENERGY_CONSTANT; - lastAvatarVelocity = velocity; - return dE; -} - -function teleported() { - var MAX_AVATAR_MOVEMENT_PER_FRAME = 30.0; - var position = MyAvatar.position; - var dP = Vec3.length(Vec3.subtract(position, lastAvatarPosition)); - lastAvatarPosition = position; - return (dP > MAX_AVATAR_MOVEMENT_PER_FRAME); -} - -function audioEnergy() { - var AUDIO_ENERGY_CONSTANT = 0.000001; - return MyAvatar.audioLoudness * AUDIO_ENERGY_CONSTANT; -} - function update() { - // refill energy - currentEnergy += energyChargeRate; - - // Avatar acceleration - currentEnergy -= avatarAccelerationEnergy(); - - // Teleport cost - if (teleported()) { - currentEnergy = 0; - } - - // Making sounds - currentEnergy -= audioEnergy(); - - - currentEnergy = clamp(currentEnergy, 0, 1); + currentEnergy = clamp(MyAvatar.energy, 0, 1); setEnergy(currentEnergy); } @@ -98,5 +61,10 @@ function cleanup() { Overlays.deleteOverlay(bar); } +function energyChanged(newValue) { + Entities.currentAvatarEnergy = newValue; +} + +MyAvatar.energyChanged.connect(energyChanged); Script.update.connect(update); Script.scriptEnding.connect(cleanup); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3e54ba99b9..8ab55d450c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -295,8 +295,20 @@ void MyAvatar::update(float deltaTime) { auto audio = DependencyManager::get(); head->setAudioLoudness(audio->getLastInputLoudness()); head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); - - simulate(deltaTime); + + simulate(deltaTime); + + currentEnergy += energyChargeRate; + currentEnergy -= getAccelerationEnergy(); + currentEnergy -= getAudioEnergy(); + + if(didTeleport()) { + currentEnergy = 0.0f; + } + currentEnergy = max(0.0f, min(currentEnergy,1.0f)); + emit energyChanged(currentEnergy); + + } extern QByteArray avatarStateToFrame(const AvatarData* _avatar); @@ -1883,3 +1895,31 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co } } +float MyAvatar::getAccelerationEnergy() { + glm::vec3 velocity = getVelocity(); + int changeInVelocity = abs(velocity.length() - priorVelocity.length()); + float changeInEnergy = priorVelocity.length()*changeInVelocity*AVATAR_MOVEMENT_ENERGY_CONSTANT; + priorVelocity = velocity; + + return changeInEnergy; +} + +float MyAvatar::getEnergy() { + return currentEnergy; +} + +void MyAvatar::setEnergy(float value) { + currentEnergy = value; +} + +float MyAvatar::getAudioEnergy() { + return getAudioLoudness()*AUDIO_ENERGY_CONSTANT; +} + +bool MyAvatar::didTeleport() { + glm::vec3 pos = getPosition(); + glm::vec3 changeInPosition = pos - lastPosition; + lastPosition = pos; + return (changeInPosition.length() > MAX_AVATAR_MOVEMENT_PER_FRAME); +} + diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ed6c3cb883..a596d9c7cd 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -78,6 +78,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(controller::Pose rightHandPose READ getRightHandPose) Q_PROPERTY(controller::Pose leftHandTipPose READ getLeftHandTipPose) Q_PROPERTY(controller::Pose rightHandTipPose READ getRightHandTipPose) + Q_PROPERTY(float energy READ getEnergy WRITE setEnergy) public: MyAvatar(RigPointer rig); @@ -272,6 +273,7 @@ signals: void transformChanged(); void newCollisionSoundURL(const QUrl& url); void collisionWithEntity(const Collision& collision); + void energyChanged(float newEnergy); private: @@ -408,6 +410,20 @@ private: AtRestDetector _hmdAtRestDetector; bool _lastIsMoving { false }; + + float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f }; + float AUDIO_ENERGY_CONSTANT { 0.000001f }; + float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f }; + float currentEnergy { 0.0f }; + float energyChargeRate { 0.003f }; + glm::vec3 priorVelocity; + glm::vec3 lastPosition; + float getAudioEnergy(); + float getAccelerationEnergy(); + float getEnergy(); + void setEnergy(float value); + bool didTeleport(); + }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 8fd7be912e..9c61d7c297 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -8,7 +8,6 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - #include "EntityScriptingInterface.h" #include "EntityItemID.h" @@ -122,6 +121,21 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties EntityItemProperties propertiesWithSimID = convertLocationFromScriptSemantics(properties); propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); + auto dimensions = propertiesWithSimID.getDimensions(); + float volume = dimensions.x*dimensions.y*dimensions.z; + auto density = propertiesWithSimID.getDensity(); + auto newVelocity = propertiesWithSimID.getVelocity().length(); + double cost = calculateCost(density*volume, 0, newVelocity); + cost *= ENTITY_MANIPULATION_MULTIPLIER; //try this as a constant for now + + if(cost > _currentAvatarEnergy) { + return QUuid(); + } else { + //debit the avatar energy and continue + emit debitEnergySource(cost); + } + + EntityItemID id = EntityItemID(QUuid::createUuid()); // If we have a local entity tree set, then also update it. @@ -211,6 +225,21 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { EntityItemProperties properties = scriptSideProperties; + + auto dimensions = properties.getDimensions(); + float volume = dimensions.x*dimensions.y*dimensions.z; + auto density = properties.getDensity(); + auto newVelocity = properties.getVelocity().length(); + double cost = calculateCost(density*volume, 0, newVelocity); + cost *= ENTITY_MANIPULATION_MULTIPLIER; + + if(cost > _currentAvatarEnergy) { + return QUuid(); + } else { + //debit the avatar energy and continue + emit debitEnergySource(cost); + } + EntityItemID entityID(id); if (!_entityTree) { queueEntityMessage(PacketType::EntityEdit, entityID, properties); @@ -316,6 +345,21 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { _entityTree->withWriteLock([&] { EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); if (entity) { + + auto dimensions = entity->getDimensions(); + float volume = dimensions.x*dimensions.y*dimensions.z; + auto density = entity->getDensity(); + auto velocity = entity->getVelocity().length(); + double cost = calculateCost(density*volume, velocity, 0); + cost *= ENTITY_MANIPULATION_MULTIPLIER; + + if(cost > _currentAvatarEnergy) { + return; + } else { + //debit the avatar energy and continue + emit debitEnergySource(cost); + } + if (entity->getLocked()) { shouldDelete = false; } else { @@ -992,3 +1036,16 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) { Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID)); return result; } + +void EntityScriptingInterface::addCostFunction(QScriptValue costFunction) { + _costFunction = &costFunction; +} + +double EntityScriptingInterface::calculateCost(float mass, float oldVelocity,float newVelocity) { + return std::abs(mass * (newVelocity - oldVelocity)); +} + +void EntityScriptingInterface::setCurrentAvatarEnergy(float energy) { + // qCDebug(entities) << "NEW AVATAR ENERGY IN ENTITY SCRIPTING INTERFACE: " << energy; + _currentAvatarEnergy = energy; +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 641da7518e..ff98ab4eb7 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include @@ -57,6 +59,8 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra /// handles scripting of Entity commands from JS passed to assigned clients class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency { Q_OBJECT + + Q_PROPERTY(float currentAvatarEnergy READ getCurrentAvatarEnergy WRITE setCurrentAvatarEnergy) public: EntityScriptingInterface(); @@ -67,7 +71,8 @@ public: void setEntityTree(EntityTreePointer modelTree); EntityTreePointer getEntityTree() { return _entityTree; } void setEntitiesScriptEngine(EntitiesScriptEngineProvider* engine) { _entitiesScriptEngine = engine; } - + double calculateCost(float mass, float oldVelocity, float newVelocity); + Q_INVOKABLE void addCostFunction(QScriptValue costFunction); public slots: // returns true if the DomainServer will allow this Node/Avatar to make changes @@ -163,6 +168,7 @@ public slots: Q_INVOKABLE int getJointIndex(const QUuid& entityID, const QString& name); Q_INVOKABLE QStringList getJointNames(const QUuid& entityID); + signals: void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); @@ -188,6 +194,7 @@ signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); void clearingEntities(); + void debitEnergySource(double value); private: bool actionWorker(const QUuid& entityID, std::function actor); @@ -205,6 +212,11 @@ private: EntityTreePointer _entityTree; EntitiesScriptEngineProvider* _entitiesScriptEngine = nullptr; + QScriptValue* _costFunction = nullptr; + float _currentAvatarEnergy; + float getCurrentAvatarEnergy() { return _currentAvatarEnergy; } + void setCurrentAvatarEnergy(float energy); + float ENTITY_MANIPULATION_MULTIPLIER = { 0.01f }; }; #endif // hifi_EntityScriptingInterface_h From 7dd5bca17fad848eac97056fffa2e68a3ff61795 Mon Sep 17 00:00:00 2001 From: "Babiuch, Ryan Nicholas" Date: Wed, 3 Feb 2016 10:46:28 -0600 Subject: [PATCH 2/5] Bug fixes and debt reductions on energy calculations. - removed superfluous code interfacing with scripts - favor floats over doubles in cost calculations - default avatar energy is maximum float value for cases where energy script is not loaded in order to still manipulate entities. --- examples/example/ui/MyEnergyBar.js | 4 ---- libraries/entities/src/EntityScriptingInterface.cpp | 6 +----- libraries/entities/src/EntityScriptingInterface.h | 8 +++----- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/examples/example/ui/MyEnergyBar.js b/examples/example/ui/MyEnergyBar.js index ac7ef0d39c..4c263b9843 100644 --- a/examples/example/ui/MyEnergyBar.js +++ b/examples/example/ui/MyEnergyBar.js @@ -56,11 +56,7 @@ function energyChanged(newValue) { function debitAvatarEnergy(value) { MyAvatar.energy = MyAvatar.energy - value; } -function calculateCost(mass, oldVelocity, newVelocity) { - return mass * (newVelocity - oldVelocity); -} -Entities.addCostFunction(calculateCost); Entities.debitEnergySource.connect(debitAvatarEnergy); MyAvatar.energyChanged.connect(energyChanged); Script.update.connect(update); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 9c61d7c297..3ba2ef0465 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1037,11 +1037,7 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) { return result; } -void EntityScriptingInterface::addCostFunction(QScriptValue costFunction) { - _costFunction = &costFunction; -} - -double EntityScriptingInterface::calculateCost(float mass, float oldVelocity,float newVelocity) { +float EntityScriptingInterface::calculateCost(float mass, float oldVelocity,float newVelocity) { return std::abs(mass * (newVelocity - oldVelocity)); } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index ff98ab4eb7..ac56dd3739 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -71,8 +71,7 @@ public: void setEntityTree(EntityTreePointer modelTree); EntityTreePointer getEntityTree() { return _entityTree; } void setEntitiesScriptEngine(EntitiesScriptEngineProvider* engine) { _entitiesScriptEngine = engine; } - double calculateCost(float mass, float oldVelocity, float newVelocity); - Q_INVOKABLE void addCostFunction(QScriptValue costFunction); + float calculateCost(float mass, float oldVelocity, float newVelocity); public slots: // returns true if the DomainServer will allow this Node/Avatar to make changes @@ -194,7 +193,7 @@ signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); void clearingEntities(); - void debitEnergySource(double value); + void debitEnergySource(float value); private: bool actionWorker(const QUuid& entityID, std::function actor); @@ -212,8 +211,7 @@ private: EntityTreePointer _entityTree; EntitiesScriptEngineProvider* _entitiesScriptEngine = nullptr; - QScriptValue* _costFunction = nullptr; - float _currentAvatarEnergy; + float _currentAvatarEnergy = { FLT_MAX }; float getCurrentAvatarEnergy() { return _currentAvatarEnergy; } void setCurrentAvatarEnergy(float energy); float ENTITY_MANIPULATION_MULTIPLIER = { 0.01f }; From 3cb2f9c4b7ae96dcb12826087f510d14348926c1 Mon Sep 17 00:00:00 2001 From: "Babiuch, Ryan Nicholas" Date: Wed, 3 Feb 2016 13:29:42 -0600 Subject: [PATCH 3/5] Exposed energy cost multiplier to scripting. - field: costMultiplier --- examples/example/ui/MyEnergyBar.js | 2 +- .../entities/src/EntityScriptingInterface.cpp | 14 +++++++++++--- libraries/entities/src/EntityScriptingInterface.h | 6 +++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/examples/example/ui/MyEnergyBar.js b/examples/example/ui/MyEnergyBar.js index 4c263b9843..c24f998e1a 100644 --- a/examples/example/ui/MyEnergyBar.js +++ b/examples/example/ui/MyEnergyBar.js @@ -56,7 +56,7 @@ function energyChanged(newValue) { function debitAvatarEnergy(value) { MyAvatar.energy = MyAvatar.energy - value; } - +Entities.costMultiplier = 0.002; Entities.debitEnergySource.connect(debitAvatarEnergy); MyAvatar.energyChanged.connect(energyChanged); Script.update.connect(update); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 3ba2ef0465..5ae6f99622 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -126,7 +126,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties auto density = propertiesWithSimID.getDensity(); auto newVelocity = propertiesWithSimID.getVelocity().length(); double cost = calculateCost(density*volume, 0, newVelocity); - cost *= ENTITY_MANIPULATION_MULTIPLIER; //try this as a constant for now + cost *= costMultiplier; if(cost > _currentAvatarEnergy) { return QUuid(); @@ -231,7 +231,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& auto density = properties.getDensity(); auto newVelocity = properties.getVelocity().length(); double cost = calculateCost(density*volume, 0, newVelocity); - cost *= ENTITY_MANIPULATION_MULTIPLIER; + cost *= costMultiplier; if(cost > _currentAvatarEnergy) { return QUuid(); @@ -351,7 +351,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { auto density = entity->getDensity(); auto velocity = entity->getVelocity().length(); double cost = calculateCost(density*volume, velocity, 0); - cost *= ENTITY_MANIPULATION_MULTIPLIER; + cost *= costMultiplier; if(cost > _currentAvatarEnergy) { return; @@ -1045,3 +1045,11 @@ void EntityScriptingInterface::setCurrentAvatarEnergy(float energy) { // qCDebug(entities) << "NEW AVATAR ENERGY IN ENTITY SCRIPTING INTERFACE: " << energy; _currentAvatarEnergy = energy; } + +float EntityScriptingInterface::getCostMultiplier() { + return costMultiplier; +} + +void EntityScriptingInterface::setCostMultiplier(float value) { + costMultiplier = value; +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index ac56dd3739..3bb86fba53 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -61,6 +61,7 @@ class EntityScriptingInterface : public OctreeScriptingInterface, public Depende Q_OBJECT Q_PROPERTY(float currentAvatarEnergy READ getCurrentAvatarEnergy WRITE setCurrentAvatarEnergy) + Q_PROPERTY(float costMultiplier READ getCostMultiplier WRITE setCostMultiplier) public: EntityScriptingInterface(); @@ -214,7 +215,10 @@ private: float _currentAvatarEnergy = { FLT_MAX }; float getCurrentAvatarEnergy() { return _currentAvatarEnergy; } void setCurrentAvatarEnergy(float energy); - float ENTITY_MANIPULATION_MULTIPLIER = { 0.01f }; + + float costMultiplier = { 0.01f }; + float getCostMultiplier(); + void setCostMultiplier(float value); }; #endif // hifi_EntityScriptingInterface_h From dca7ff967cdfa9b0fdcbde2d7b7e4871fced78a6 Mon Sep 17 00:00:00 2001 From: "Babiuch, Ryan Nicholas" Date: Thu, 4 Feb 2016 08:26:56 -0600 Subject: [PATCH 4/5] Conform to coding standard. --- interface/src/avatar/MyAvatar.cpp | 4 ++-- .../entities/src/EntityScriptingInterface.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9d5c39ffc9..e906bf2485 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1866,7 +1866,7 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co float MyAvatar::getAccelerationEnergy() { glm::vec3 velocity = getVelocity(); int changeInVelocity = abs(velocity.length() - priorVelocity.length()); - float changeInEnergy = priorVelocity.length()*changeInVelocity*AVATAR_MOVEMENT_ENERGY_CONSTANT; + float changeInEnergy = priorVelocity.length() * changeInVelocity * AVATAR_MOVEMENT_ENERGY_CONSTANT; priorVelocity = velocity; return changeInEnergy; @@ -1881,7 +1881,7 @@ void MyAvatar::setEnergy(float value) { } float MyAvatar::getAudioEnergy() { - return getAudioLoudness()*AUDIO_ENERGY_CONSTANT; + return getAudioLoudness() * AUDIO_ENERGY_CONSTANT; } bool MyAvatar::didTeleport() { diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 44044f0231..790a1e1919 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -123,10 +123,10 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); auto dimensions = propertiesWithSimID.getDimensions(); - float volume = dimensions.x*dimensions.y*dimensions.z; + float volume = dimensions.x * dimensions.y * dimensions.z; auto density = propertiesWithSimID.getDensity(); auto newVelocity = propertiesWithSimID.getVelocity().length(); - double cost = calculateCost(density*volume, 0, newVelocity); + double cost = calculateCost(density * volume, 0, newVelocity); cost *= costMultiplier; if(cost > _currentAvatarEnergy) { @@ -231,10 +231,10 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& EntityItemProperties properties = scriptSideProperties; auto dimensions = properties.getDimensions(); - float volume = dimensions.x*dimensions.y*dimensions.z; + float volume = dimensions.x * dimensions.y * dimensions.z; auto density = properties.getDensity(); auto newVelocity = properties.getVelocity().length(); - double cost = calculateCost(density*volume, 0, newVelocity); + double cost = calculateCost(density * volume, 0, newVelocity); cost *= costMultiplier; if(cost > _currentAvatarEnergy) { @@ -351,10 +351,10 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { if (entity) { auto dimensions = entity->getDimensions(); - float volume = dimensions.x*dimensions.y*dimensions.z; + float volume = dimensions.x * dimensions.y * dimensions.z; auto density = entity->getDensity(); auto velocity = entity->getVelocity().length(); - double cost = calculateCost(density*volume, velocity, 0); + double cost = calculateCost(density * volume, velocity, 0); cost *= costMultiplier; if(cost > _currentAvatarEnergy) { @@ -1041,7 +1041,7 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) { return result; } -float EntityScriptingInterface::calculateCost(float mass, float oldVelocity,float newVelocity) { +float EntityScriptingInterface::calculateCost(float mass, float oldVelocity, float newVelocity) { return std::abs(mass * (newVelocity - oldVelocity)); } From 0069849da3f310b5427abfed1a8cdedf1ef15618 Mon Sep 17 00:00:00 2001 From: "Babiuch, Ryan Nicholas" Date: Thu, 4 Feb 2016 08:55:23 -0600 Subject: [PATCH 5/5] Consider existing velocity in calculating energy costs when editing entities. --- .../entities/src/EntityScriptingInterface.cpp | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 790a1e1919..3d252abc11 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -126,7 +126,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties float volume = dimensions.x * dimensions.y * dimensions.z; auto density = propertiesWithSimID.getDensity(); auto newVelocity = propertiesWithSimID.getVelocity().length(); - double cost = calculateCost(density * volume, 0, newVelocity); + float cost = calculateCost(density * volume, 0, newVelocity); cost *= costMultiplier; if(cost > _currentAvatarEnergy) { @@ -136,7 +136,6 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties emit debitEnergySource(cost); } - EntityItemID id = EntityItemID(QUuid::createUuid()); // If we have a local entity tree set, then also update it. @@ -234,19 +233,23 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& float volume = dimensions.x * dimensions.y * dimensions.z; auto density = properties.getDensity(); auto newVelocity = properties.getVelocity().length(); - double cost = calculateCost(density * volume, 0, newVelocity); - cost *= costMultiplier; - - if(cost > _currentAvatarEnergy) { - return QUuid(); - } else { - //debit the avatar energy and continue - emit debitEnergySource(cost); - } + float oldVelocity = { 0.0f }; EntityItemID entityID(id); if (!_entityTree) { queueEntityMessage(PacketType::EntityEdit, entityID, properties); + + //if there is no local entity entity tree, no existing velocity, use 0. + float cost = calculateCost(density * volume, oldVelocity, newVelocity); + cost *= costMultiplier; + + if(cost > _currentAvatarEnergy) { + return QUuid(); + } else { + //debit the avatar energy and continue + emit debitEnergySource(cost); + } + return id; } // If we have a local entity tree set, then also update it. @@ -260,6 +263,9 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& if (!entity) { return; } + //existing entity, retrieve old velocity for check down below + oldVelocity = entity->getVelocity().length(); + if (!scriptSideProperties.parentIDChanged()) { properties.setParentID(entity->getParentID()); } @@ -275,6 +281,16 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } properties = convertLocationFromScriptSemantics(properties); updatedEntity = _entityTree->updateEntity(entityID, properties); + + float cost = calculateCost(density * volume, oldVelocity, newVelocity); + cost *= costMultiplier; + + if(cost > _currentAvatarEnergy) { + updatedEntity = false; + } else { + //debit the avatar energy and continue + emit debitEnergySource(cost); + } }); if (!updatedEntity) { @@ -354,7 +370,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { float volume = dimensions.x * dimensions.y * dimensions.z; auto density = entity->getDensity(); auto velocity = entity->getVelocity().length(); - double cost = calculateCost(density * volume, velocity, 0); + float cost = calculateCost(density * volume, velocity, 0); cost *= costMultiplier; if(cost > _currentAvatarEnergy) {