From 2ffb19a0ed1a7dad5a82ad776198017f323996e1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 25 Feb 2015 14:35:04 -0800 Subject: [PATCH 01/56] getPosition() --> getPositionInDomainUnits() and friends --- interface/src/avatar/ModelReferential.cpp | 30 ++++++++------- interface/src/avatar/ModelReferential.h | 2 +- .../src/EntityTreeRenderer.cpp | 6 +-- .../src/RenderableBoxEntityItem.cpp | 4 +- .../src/RenderableLightEntityItem.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 4 +- .../src/RenderableSphereEntityItem.cpp | 2 +- .../src/RenderableTextEntityItem.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 38 +++++++++---------- libraries/entities/src/EntityItem.h | 34 ++++++++--------- libraries/entities/src/EntityTree.cpp | 2 +- libraries/entities/src/EntityTreeElement.cpp | 12 +++--- libraries/entities/src/ModelEntityItem.cpp | 4 +- libraries/entities/src/SphereEntityItem.cpp | 4 +- libraries/entities/src/TextEntityItem.cpp | 6 +-- libraries/entities/src/TextEntityItem.h | 2 +- .../entities/src/UpdateEntityOperator.cpp | 4 +- 17 files changed, 81 insertions(+), 77 deletions(-) diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index 5b72fddae7..9136e53fa5 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -32,9 +32,9 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); if (item != NULL) { - _refScale = item->getLargestDimension(); + _refScale = item->getLargestDimensionInDomainUnits(); _refRotation = item->getRotation(); - _refPosition = item->getPosition() * (float)TREE_SCALE; + _refPosition = item->getPositionInDomainUnits() * (float)TREE_SCALE; update(); } } @@ -51,9 +51,9 @@ ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, Avat return; } - _refScale = item->getLargestDimension(); + _refScale = item->getLargestDimensionInDomainUnits(); _refRotation = item->getRotation(); - _refPosition = item->getPosition() * (float)TREE_SCALE; + _refPosition = item->getPositionInDomainUnits() * (float)TREE_SCALE; glm::quat refInvRot = glm::inverse(_refRotation); _scale = _avatar->getTargetScale() / _refScale; @@ -68,8 +68,8 @@ void ModelReferential::update() { } bool somethingChanged = false; - if (item->getLargestDimension() != _refScale) { - _refScale = item->getLargestDimension(); + if (item->getLargestDimensionInDomainUnits() != _refScale) { + _refScale = item->getLargestDimensionInDomainUnits(); _avatar->setTargetScale(_refScale * _scale, true); somethingChanged = true; } @@ -78,8 +78,8 @@ void ModelReferential::update() { _avatar->setOrientation(_refRotation * _rotation, true); somethingChanged = true; } - if (item->getPosition() != _refPosition || somethingChanged) { - _refPosition = item->getPosition(); + if (item->getPositionInDomainUnits() != _refPosition || somethingChanged) { + _refPosition = item->getPositionInDomainUnits(); _avatar->setPosition(_refPosition * (float)TREE_SCALE + _refRotation * (_translation * _refScale), true); } } @@ -108,7 +108,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) { - _refScale = item->getLargestDimension(); + _refScale = item->getLargestDimensionInDomainUnits(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); } @@ -119,6 +119,7 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E ModelReferential(entityID, tree, avatar), _jointIndex(jointIndex) { + // TODO: Andrew to fix this using meters _type = JOINT; const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); @@ -128,17 +129,19 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E return; } - _refScale = item->getLargestDimension(); + _refScale = item->getLargestDimensionInDomainUnits(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); glm::quat refInvRot = glm::inverse(_refRotation); _scale = _avatar->getTargetScale() / _refScale; _rotation = refInvRot * _avatar->getOrientation(); + // BUG! _refPosition is in domain units, but avatar is in meters _translation = refInvRot * (avatar->getPosition() - _refPosition) / _refScale; } void JointReferential::update() { + // TODO: Andrew to fix this using meters const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) { @@ -146,8 +149,8 @@ void JointReferential::update() { } bool somethingChanged = false; - if (item->getLargestDimension() != _refScale) { - _refScale = item->getLargestDimension(); + if (item->getLargestDimensionInDomainUnits() != _refScale) { + _refScale = item->getLargestDimensionInDomainUnits(); _avatar->setTargetScale(_refScale * _scale, true); somethingChanged = true; } @@ -156,8 +159,9 @@ void JointReferential::update() { _avatar->setOrientation(_refRotation * _rotation, true); somethingChanged = true; } - if (item->getPosition() != _refPosition || somethingChanged) { + if (item->getPositionInDomainUnits() != _refPosition || somethingChanged) { model->getJointPositionInWorldFrame(_jointIndex, _refPosition); + // BUG! _refPosition is in domain units, but avatar is in meters _avatar->setPosition(_refPosition + _refRotation * (_translation * _refScale), true); } } diff --git a/interface/src/avatar/ModelReferential.h b/interface/src/avatar/ModelReferential.h index adb5783de2..0b66acfac5 100644 --- a/interface/src/avatar/ModelReferential.h +++ b/interface/src/avatar/ModelReferential.h @@ -45,4 +45,4 @@ protected: uint32_t _jointIndex; }; -#endif // hifi_ModelReferential_h \ No newline at end of file +#endif // hifi_ModelReferential_h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 975d0f515d..2710a9ebf4 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -485,9 +485,9 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg glPopMatrix(); - glm::vec3 position = entity->getPosition() * (float) TREE_SCALE; - glm::vec3 center = entity->getCenter() * (float) TREE_SCALE; - glm::vec3 dimensions = entity->getDimensions() * (float) TREE_SCALE; + glm::vec3 position = entity->getPositionInDomainUnits() * (float) TREE_SCALE; + glm::vec3 center = entity->getCenterInDomainUnits() * (float) TREE_SCALE; + glm::vec3 dimensions = entity->getDimensionsInDomainUnits() * (float) TREE_SCALE; glm::quat rotation = entity->getRotation(); glPushMatrix(); diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index 7f2ba410d8..fe3375c274 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -26,8 +26,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); assert(getType() == EntityTypes::Box); glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenter() * (float)TREE_SCALE; - glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; + glm::vec3 center = getCenterInDomainUnits() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; glm::quat rotation = getRotation(); const float MAX_COLOR = 255.0f; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 1e0a9b6fc7..5b1486a6e4 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -27,7 +27,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLightEntityItem::render"); assert(getType() == EntityTypes::Light); glm::vec3 position = getPositionInMeters(); - glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; glm::quat rotation = getRotation(); float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ef6853c43a..cf09d84895 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -114,9 +114,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { bool drawAsModel = hasModel(); - glm::vec3 position = getPosition() * (float)TREE_SCALE; + glm::vec3 position = getPositionInDomainUnits() * (float)TREE_SCALE; float size = getSize() * (float)TREE_SCALE; - glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; if (drawAsModel) { remapTextures(); diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index 427ed20a8b..fd0137812d 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -28,7 +28,7 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { assert(getType() == EntityTypes::Sphere); glm::vec3 position = getPositionInMeters(); glm::vec3 center = getCenterInMeters(); - glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; glm::quat rotation = getRotation(); const float MAX_COLOR = 255.0f; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 4dc2a07249..d752ff7906 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -30,7 +30,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableTextEntityItem::render"); assert(getType() == EntityTypes::Text); glm::vec3 position = getPositionInMeters(); - glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; glm::vec3 halfDimensions = dimensions / 2.0f; glm::quat rotation = getRotation(); float leftMargin = 0.1f; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 15d46603b5..8020dac639 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -221,12 +221,12 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet // PROP_PAGED_PROPERTY, // PROP_CUSTOM_PROPERTIES_INCLUDED, - APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition()); - APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete + APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPositionInDomainUnits()); + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensionsInDomainUnits()); // NOTE: PROP_RADIUS obsolete APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation()); APPEND_ENTITY_PROPERTY(PROP_DENSITY, appendValue, getDensity()); - APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity()); - APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); + APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocityInDomainUnits()); + APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravityInDomainUnits()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); @@ -502,7 +502,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef dataAt += propertyFlags.getEncodedLength(); bytesRead += propertyFlags.getEncodedLength(); - READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePosition); + READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePositionInDomainUnits); // Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) { @@ -516,13 +516,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } } } else { - READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensions); + READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensionsInDomainUnits); } READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation); READ_ENTITY_PROPERTY_SETTER(PROP_DENSITY, float, updateDensity); - READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocity); - READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravity); + READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits); + READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits); READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping); READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT, setScript); @@ -717,7 +717,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { if (hasVelocity()) { // linear damping - glm::vec3 velocity = getVelocity(); + glm::vec3 velocity = getVelocityInDomainUnits(); if (_damping > 0.0f) { velocity *= powf(1.0f - _damping, timeElapsed); #ifdef WANT_DEBUG @@ -729,7 +729,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { } // integrate position forward - glm::vec3 position = getPosition(); + glm::vec3 position = getPositionInDomainUnits(); glm::vec3 newPosition = position + (velocity * timeElapsed); #ifdef WANT_DEBUG @@ -749,19 +749,19 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { if (hasGravity()) { // handle resting on surface case, this is definitely a bit of a hack, and it only works on the // "ground" plane of the domain, but for now it's what we've got - velocity += getGravity() * timeElapsed; + velocity += getGravityInDomainUnits() * timeElapsed; } float speed = glm::length(velocity); const float EPSILON_LINEAR_VELOCITY_LENGTH = 0.001f / (float)TREE_SCALE; // 1mm/sec if (speed < EPSILON_LINEAR_VELOCITY_LENGTH) { - setVelocity(ENTITY_ITEM_ZERO_VEC3); + setVelocityInDomainUnits(ENTITY_ITEM_ZERO_VEC3); if (speed > 0.0f) { _dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE; } } else { - setPosition(position); - setVelocity(velocity); + setPositionInDomainUnits(position); + setVelocityInDomainUnits(velocity); } #ifdef WANT_DEBUG @@ -894,7 +894,7 @@ float EntityItem::getSize() const { } // TODO: doesn't this need to handle rotation? -glm::vec3 EntityItem::getCenter() const { +glm::vec3 EntityItem::getCenterInDomainUnits() const { return _position + (_dimensions * (glm::vec3(0.5f,0.5f,0.5f) - _registrationPoint)); } @@ -1008,7 +1008,7 @@ const float MIN_DAMPING_DELTA = 0.001f; const float MIN_GRAVITY_DELTA = 0.001f; const float MIN_SPIN_DELTA = 0.0003f; -void EntityItem::updatePosition(const glm::vec3& value) { +void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) { if (glm::distance(_position, value) * (float)TREE_SCALE > MIN_POSITION_DELTA) { _position = value; _dirtyFlags |= EntityItem::DIRTY_POSITION; @@ -1023,7 +1023,7 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) { } } -void EntityItem::updateDimensions(const glm::vec3& value) { +void EntityItem::updateDimensionsInDomainUnits(const glm::vec3& value) { if (_dimensions != value) { _dimensions = glm::abs(value); _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); @@ -1072,7 +1072,7 @@ void EntityItem::updateMass(float mass) { } } -void EntityItem::updateVelocity(const glm::vec3& value) { +void EntityItem::updateVelocityInDomainUnits(const glm::vec3& value) { if (glm::distance(_velocity, value) * (float)TREE_SCALE > MIN_VELOCITY_DELTA) { if (glm::length(value) * (float)TREE_SCALE < MIN_VELOCITY_DELTA) { _velocity = ENTITY_ITEM_ZERO_VEC3; @@ -1102,7 +1102,7 @@ void EntityItem::updateDamping(float value) { } } -void EntityItem::updateGravity(const glm::vec3& value) { +void EntityItem::updateGravityInDomainUnits(const glm::vec3& value) { if (glm::distance(_gravity, value) * (float)TREE_SCALE > MIN_GRAVITY_DELTA) { _gravity = value; _dirtyFlags |= EntityItem::DIRTY_VELOCITY; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 99fafa3343..12189bf56b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -145,26 +145,26 @@ public: // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } - const glm::vec3& getPosition() const { return _position; } /// get position in domain scale units (0.0 - 1.0) + const glm::vec3& getPositionInDomainUnits() const { return _position; } /// get position in domain scale units (0.0 - 1.0) glm::vec3 getPositionInMeters() const { return _position * (float) TREE_SCALE; } /// get position in meters /// set position in domain scale units (0.0 - 1.0) - void setPosition(const glm::vec3& value) { _position = value; } + void setPositionInDomainUnits(const glm::vec3& value) { _position = value; } void setPositionInMeters(const glm::vec3& value) /// set position in meter units (0.0 - TREE_SCALE) - { setPosition(glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f)); } + { setPositionInDomainUnits(glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f)); } - glm::vec3 getCenter() const; /// calculates center of the entity in domain scale units (0.0 - 1.0) - glm::vec3 getCenterInMeters() const { return getCenter() * (float) TREE_SCALE; } + glm::vec3 getCenterInDomainUnits() const; /// calculates center of the entity in domain scale units (0.0 - 1.0) + glm::vec3 getCenterInMeters() const { return getCenterInDomainUnits() * (float) TREE_SCALE; } - const glm::vec3& getDimensions() const { return _dimensions; } /// get dimensions in domain scale units (0.0 - 1.0) + const glm::vec3& getDimensionsInDomainUnits() const { return _dimensions; } /// get dimensions in domain scale units (0.0 - 1.0) glm::vec3 getDimensionsInMeters() const { return _dimensions * (float) TREE_SCALE; } /// get dimensions in meters - float getLargestDimension() const { return glm::length(_dimensions); } /// get the largest possible dimension + float getLargestDimensionInDomainUnits() const { return glm::length(_dimensions); } /// get the largest possible dimension /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value) { _dimensions = value; } + virtual void setDimensionsInDomainUnits(const glm::vec3& value) { _dimensions = value; } /// set dimensions in meter units (0.0 - TREE_SCALE) this will also reset radius appropriately - void setDimensionsInMeters(const glm::vec3& value) { setDimensions(value / (float) TREE_SCALE); } + void setDimensionsInMeters(const glm::vec3& value) { setDimensionsInDomainUnits(value / (float) TREE_SCALE); } const glm::quat& getRotation() const { return _rotation; } void setRotation(const glm::quat& rotation) { _rotation = rotation; } @@ -181,15 +181,15 @@ public: float getDensity() const { return _density; } - const glm::vec3& getVelocity() const { return _velocity; } /// velocity in domain scale units (0.0-1.0) per second + const glm::vec3& getVelocityInDomainUnits() const { return _velocity; } /// velocity in domain scale units (0.0-1.0) per second glm::vec3 getVelocityInMeters() const { return _velocity * (float) TREE_SCALE; } /// get velocity in meters - void setVelocity(const glm::vec3& value) { _velocity = value; } /// velocity in domain scale units (0.0-1.0) per second + void setVelocityInDomainUnits(const glm::vec3& value) { _velocity = value; } /// velocity in domain scale units (0.0-1.0) per second void setVelocityInMeters(const glm::vec3& value) { _velocity = value / (float) TREE_SCALE; } /// velocity in meters bool hasVelocity() const { return _velocity != ENTITY_ITEM_ZERO_VEC3; } - const glm::vec3& getGravity() const { return _gravity; } /// gravity in domain scale units (0.0-1.0) per second squared + const glm::vec3& getGravityInDomainUnits() const { return _gravity; } /// gravity in domain scale units (0.0-1.0) per second squared glm::vec3 getGravityInMeters() const { return _gravity * (float) TREE_SCALE; } /// get gravity in meters - void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in domain scale units (0.0-1.0) per second squared + void setGravityInDomainUnits(const glm::vec3& value) { _gravity = value; } /// gravity in domain scale units (0.0-1.0) per second squared void setGravityInMeters(const glm::vec3& value) { _gravity = value / (float) TREE_SCALE; } /// gravity in meters bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } @@ -261,17 +261,17 @@ public: virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; } // updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags - void updatePosition(const glm::vec3& value); + void updatePositionInDomainUnits(const glm::vec3& value); void updatePositionInMeters(const glm::vec3& value); - void updateDimensions(const glm::vec3& value); + void updateDimensionsInDomainUnits(const glm::vec3& value); void updateDimensionsInMeters(const glm::vec3& value); void updateRotation(const glm::quat& rotation); void updateDensity(float value); void updateMass(float value); - void updateVelocity(const glm::vec3& value); + void updateVelocityInDomainUnits(const glm::vec3& value); void updateVelocityInMeters(const glm::vec3& value); void updateDamping(float value); - void updateGravity(const glm::vec3& value); + void updateGravityInDomainUnits(const glm::vec3& value); void updateGravityInMeters(const glm::vec3& value); void updateAngularVelocity(const glm::vec3& value); void updateAngularDamping(float value); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 95617b4944..65e665c29e 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -433,7 +433,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) // we may have gotten NULL back, meaning no entity was available if (thisClosestEntity) { - glm::vec3 entityPosition = thisClosestEntity->getPosition(); + glm::vec3 entityPosition = thisClosestEntity->getPositionInDomainUnits(); float distanceFromPointToEntity = glm::distance(entityPosition, args->position); // If we're within our target radius diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index ecd90e5942..4b4bae662a 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -494,11 +494,11 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); - glm::mat4 translation = glm::translate(entity->getPosition()); + glm::mat4 translation = glm::translate(entity->getPositionInDomainUnits()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getDimensions(); + glm::vec3 dimensions = entity->getDimensionsInDomainUnits(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -549,7 +549,7 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad QList<EntityItem*>::const_iterator entityEnd = _entityItems->end(); while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); - glm::vec3 entityCenter = entity->getPosition(); + glm::vec3 entityCenter = entity->getPositionInDomainUnits(); float entityRadius = entity->getRadius(); // don't penetrate yourself @@ -585,7 +585,7 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const float closestEntityDistance = FLT_MAX; uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { - float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPosition()); + float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPositionInDomainUnits()); if (distanceToEntity < closestEntityDistance) { closestEntity = (*_entityItems)[i]; } @@ -598,7 +598,7 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { const EntityItem* entity = (*_entityItems)[i]; - float distance = glm::length(entity->getPosition() - searchPosition); + float distance = glm::length(entity->getPositionInDomainUnits() - searchPosition); if (distance < searchRadius + entity->getRadius()) { foundEntities.push_back(entity); } @@ -616,7 +616,7 @@ void EntityTreeElement::getEntities(const AACube& box, QVector<EntityItem*>& fou // NOTE: we actually do cube-cube collision queries here, which is sloppy but good enough for now // TODO: decide whether to replace entityCube-cube query with sphere-cube (requires a square root // but will be slightly more accurate). - entityCube.setBox(entity->getPosition() - glm::vec3(radius), 2.0f * radius); + entityCube.setBox(entity->getPositionInDomainUnits() - glm::vec3(radius), 2.0f * radius); if (entityCube.touches(box)) { foundEntities.push_back(entity); } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 4d8e741cc6..61a2a294cf 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -265,8 +265,8 @@ void ModelEntityItem::update(const quint64& now) { void ModelEntityItem::debugDump() const { qDebug() << "ModelEntityItem id:" << getEntityItemID(); qDebug() << " edited ago:" << getEditedAgo(); - qDebug() << " position:" << getPosition() * (float)TREE_SCALE; - qDebug() << " dimensions:" << getDimensions() * (float)TREE_SCALE; + qDebug() << " position:" << getPositionInDomainUnits() * (float)TREE_SCALE; + qDebug() << " dimensions:" << getDimensionsInDomainUnits() * (float)TREE_SCALE; qDebug() << " model URL:" << getModelURL(); } diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 7d5fb83a4e..6b773d8189 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -98,9 +98,9 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { // determine the ray in the frame of the entity transformed from a unit sphere - glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 translation = glm::translate(getPositionInDomainUnits()); glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 scale = glm::scale(getDimensions()); + glm::mat4 scale = glm::scale(getDimensionsInDomainUnits()); glm::mat4 registration = glm::translate(glm::vec3(0.5f, 0.5f, 0.5f) - getRegistrationPoint()); glm::mat4 entityToWorldMatrix = translation * rotation * scale * registration; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index ac9a080119..051463929c 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -40,7 +40,7 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityIte setProperties(properties); } -void TextEntityItem::setDimensions(const glm::vec3& value) { +void TextEntityItem::setDimensionsInDomainUnits(const glm::vec3& value) { // NOTE: Text Entities always have a "depth" of 1cm. float fixedDepth = 0.01f / (float)TREE_SCALE; _dimensions = glm::vec3(value.x, value.y, fixedDepth); @@ -145,11 +145,11 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const // now we know the point the ray hit our plane glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 translation = glm::translate(getPositionInDomainUnits()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getDimensionsInDomainUnits(); glm::vec3 registrationPoint = getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); AABox entityFrameBox(corner, dimensions); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 1f0bd7d85e..485cf52d95 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -23,7 +23,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value); + virtual void setDimensionsInDomainUnits(const glm::vec3& value); // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; diff --git a/libraries/entities/src/UpdateEntityOperator.cpp b/libraries/entities/src/UpdateEntityOperator.cpp index 29ed430f7a..43052c6a73 100644 --- a/libraries/entities/src/UpdateEntityOperator.cpp +++ b/libraries/entities/src/UpdateEntityOperator.cpp @@ -59,7 +59,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, // get the old property value and set it in our properties in order for our bounds // calculations to work. if (_properties.containsPositionChange() && !_properties.containsDimensionsChange()) { - glm::vec3 oldDimensionsInMeters = _existingEntity->getDimensions() * (float)TREE_SCALE; + glm::vec3 oldDimensionsInMeters = _existingEntity->getDimensionsInMeters(); _properties.setDimensions(oldDimensionsInMeters); if (_wantDebug) { @@ -68,7 +68,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, } if (!_properties.containsPositionChange() && _properties.containsDimensionsChange()) { - glm::vec3 oldPositionInMeters = _existingEntity->getPosition() * (float)TREE_SCALE; + glm::vec3 oldPositionInMeters = _existingEntity->getPositionInMeters(); _properties.setPosition(oldPositionInMeters); if (_wantDebug) { From 8d4ea143ce34df18cd7f29cd2a855a659f71642a Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 25 Feb 2015 14:48:06 -0800 Subject: [PATCH 02/56] easy conversions of: InDomainUnits --> InMeters --- interface/src/avatar/ModelReferential.cpp | 4 ++-- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 6 +++--- libraries/entities-renderer/src/RenderableBoxEntityItem.cpp | 4 ++-- .../entities-renderer/src/RenderableLightEntityItem.cpp | 2 +- .../entities-renderer/src/RenderableModelEntityItem.cpp | 4 ++-- .../entities-renderer/src/RenderableSphereEntityItem.cpp | 2 +- .../entities-renderer/src/RenderableTextEntityItem.cpp | 2 +- libraries/entities/src/ModelEntityItem.cpp | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index 9136e53fa5..952d6475dc 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -34,7 +34,7 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A if (item != NULL) { _refScale = item->getLargestDimensionInDomainUnits(); _refRotation = item->getRotation(); - _refPosition = item->getPositionInDomainUnits() * (float)TREE_SCALE; + _refPosition = item->getPositionInMeters(); update(); } } @@ -53,7 +53,7 @@ ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, Avat _refScale = item->getLargestDimensionInDomainUnits(); _refRotation = item->getRotation(); - _refPosition = item->getPositionInDomainUnits() * (float)TREE_SCALE; + _refPosition = item->getPositionInMeters(); glm::quat refInvRot = glm::inverse(_refRotation); _scale = _avatar->getTargetScale() / _refScale; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ca69c2255a..d784950267 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -501,9 +501,9 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg glPopMatrix(); - glm::vec3 position = entity->getPositionInDomainUnits() * (float) TREE_SCALE; - glm::vec3 center = entity->getCenterInDomainUnits() * (float) TREE_SCALE; - glm::vec3 dimensions = entity->getDimensionsInDomainUnits() * (float) TREE_SCALE; + glm::vec3 position = entity->getPositionInMeters(); + glm::vec3 center = entity->getCenterInMeters(); + glm::vec3 dimensions = entity->getDimensionsInMeters(); glm::quat rotation = entity->getRotation(); glPushMatrix(); diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index fe3375c274..a80fc91995 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -26,8 +26,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); assert(getType() == EntityTypes::Box); glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInDomainUnits() * (float)TREE_SCALE; - glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; + glm::vec3 center = getCenterInMeters(); + glm::vec3 dimensions = getDimensionsInMeters(); glm::quat rotation = getRotation(); const float MAX_COLOR = 255.0f; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 5b1486a6e4..5a20633044 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -27,7 +27,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLightEntityItem::render"); assert(getType() == EntityTypes::Light); glm::vec3 position = getPositionInMeters(); - glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInMeters(); glm::quat rotation = getRotation(); float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index cf09d84895..b7ea64ebef 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -114,9 +114,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { bool drawAsModel = hasModel(); - glm::vec3 position = getPositionInDomainUnits() * (float)TREE_SCALE; + glm::vec3 position = getPositionInMeters(); float size = getSize() * (float)TREE_SCALE; - glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInMeters(); if (drawAsModel) { remapTextures(); diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index fd0137812d..4688e7cc29 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -28,7 +28,7 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { assert(getType() == EntityTypes::Sphere); glm::vec3 position = getPositionInMeters(); glm::vec3 center = getCenterInMeters(); - glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInMeters(); glm::quat rotation = getRotation(); const float MAX_COLOR = 255.0f; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index c45096358b..097aef3b38 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -31,7 +31,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableTextEntityItem::render"); assert(getType() == EntityTypes::Text); glm::vec3 position = getPositionInMeters(); - glm::vec3 dimensions = getDimensionsInDomainUnits() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensionsInMeters(); glm::vec3 halfDimensions = dimensions / 2.0f; glm::quat rotation = getRotation(); float leftMargin = 0.1f; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 61613a2ec8..5a95fe4e33 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -255,8 +255,8 @@ void ModelEntityItem::update(const quint64& now) { void ModelEntityItem::debugDump() const { qDebug() << "ModelEntityItem id:" << getEntityItemID(); qDebug() << " edited ago:" << getEditedAgo(); - qDebug() << " position:" << getPositionInDomainUnits() * (float)TREE_SCALE; - qDebug() << " dimensions:" << getDimensionsInDomainUnits() * (float)TREE_SCALE; + qDebug() << " position:" << getPositionInMeters(); + qDebug() << " dimensions:" << getDimensionsInMeters(); qDebug() << " model URL:" << getModelURL(); } From 9ad88c379317ec3c517a9c3b3d2224d374a7b9d8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Thu, 26 Feb 2015 13:42:08 -0800 Subject: [PATCH 03/56] Referentials do math using meters --- interface/src/avatar/ModelReferential.cpp | 42 ++++++++++------------- libraries/avatars/src/Referential.cpp | 2 -- libraries/avatars/src/Referential.h | 14 ++++---- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index 952d6475dc..beb378403d 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -21,7 +21,6 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A { _translation = referential->getTranslation(); _rotation = referential->getRotation(); - _scale = referential->getScale(); unpackExtraData(reinterpret_cast<unsigned char*>(referential->getExtraData().data()), referential->getExtraData().size()); @@ -32,7 +31,7 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); if (item != NULL) { - _refScale = item->getLargestDimensionInDomainUnits(); + _lastRefDimension = item->getDimensionsInMeters(); _refRotation = item->getRotation(); _refPosition = item->getPositionInMeters(); update(); @@ -51,14 +50,13 @@ ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, Avat return; } - _refScale = item->getLargestDimensionInDomainUnits(); + _lastRefDimension = item->getDimensionsInMeters(); _refRotation = item->getRotation(); _refPosition = item->getPositionInMeters(); glm::quat refInvRot = glm::inverse(_refRotation); - _scale = _avatar->getTargetScale() / _refScale; _rotation = refInvRot * _avatar->getOrientation(); - _translation = refInvRot * (avatar->getPosition() - _refPosition) / _refScale; + _translation = refInvRot * (avatar->getPosition() - _refPosition); } void ModelReferential::update() { @@ -68,9 +66,10 @@ void ModelReferential::update() { } bool somethingChanged = false; - if (item->getLargestDimensionInDomainUnits() != _refScale) { - _refScale = item->getLargestDimensionInDomainUnits(); - _avatar->setTargetScale(_refScale * _scale, true); + if (item->getDimensionsInMeters() != _lastRefDimension) { + glm::vec3 oldDimension = _lastRefDimension; + _lastRefDimension = item->getDimensionsInMeters(); + _translation *= _lastRefDimension / oldDimension; somethingChanged = true; } if (item->getRotation() != _refRotation) { @@ -78,9 +77,9 @@ void ModelReferential::update() { _avatar->setOrientation(_refRotation * _rotation, true); somethingChanged = true; } - if (item->getPositionInDomainUnits() != _refPosition || somethingChanged) { - _refPosition = item->getPositionInDomainUnits(); - _avatar->setPosition(_refPosition * (float)TREE_SCALE + _refRotation * (_translation * _refScale), true); + if (item->getPositionInMeters() != _refPosition || somethingChanged) { + _refPosition = item->getPositionInMeters(); + _avatar->setPosition(_refPosition + _refRotation * _translation, true); } } @@ -108,7 +107,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) { - _refScale = item->getLargestDimensionInDomainUnits(); + _lastRefDimension = item->getDimensionsInMeters(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); } @@ -119,7 +118,6 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E ModelReferential(entityID, tree, avatar), _jointIndex(jointIndex) { - // TODO: Andrew to fix this using meters _type = JOINT; const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); @@ -129,19 +127,17 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E return; } - _refScale = item->getLargestDimensionInDomainUnits(); + _lastRefDimension = item->getDimensionsInMeters(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); glm::quat refInvRot = glm::inverse(_refRotation); - _scale = _avatar->getTargetScale() / _refScale; _rotation = refInvRot * _avatar->getOrientation(); // BUG! _refPosition is in domain units, but avatar is in meters - _translation = refInvRot * (avatar->getPosition() - _refPosition) / _refScale; + _translation = refInvRot * (avatar->getPosition() - _refPosition); } void JointReferential::update() { - // TODO: Andrew to fix this using meters const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) { @@ -149,9 +145,10 @@ void JointReferential::update() { } bool somethingChanged = false; - if (item->getLargestDimensionInDomainUnits() != _refScale) { - _refScale = item->getLargestDimensionInDomainUnits(); - _avatar->setTargetScale(_refScale * _scale, true); + if (item->getDimensionsInMeters() != _lastRefDimension) { + glm::vec3 oldDimension = _lastRefDimension; + _lastRefDimension = item->getDimensionsInMeters(); + _translation *= _lastRefDimension / oldDimension; somethingChanged = true; } if (item->getRotation() != _refRotation) { @@ -159,10 +156,9 @@ void JointReferential::update() { _avatar->setOrientation(_refRotation * _rotation, true); somethingChanged = true; } - if (item->getPositionInDomainUnits() != _refPosition || somethingChanged) { + if (item->getPositionInMeters() != _refPosition || somethingChanged) { model->getJointPositionInWorldFrame(_jointIndex, _refPosition); - // BUG! _refPosition is in domain units, but avatar is in meters - _avatar->setPosition(_refPosition + _refRotation * (_translation * _refScale), true); + _avatar->setPosition(_refPosition + _refRotation * _translation, true); } } diff --git a/libraries/avatars/src/Referential.cpp b/libraries/avatars/src/Referential.cpp index d5203a0a9d..f5f1d47324 100644 --- a/libraries/avatars/src/Referential.cpp +++ b/libraries/avatars/src/Referential.cpp @@ -76,7 +76,6 @@ int Referential::pack(unsigned char* destinationBuffer) const { destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, _translation, 0); destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _rotation); - destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, _scale, 0); return destinationBuffer - startPosition; } @@ -91,7 +90,6 @@ int Referential::unpack(const unsigned char* sourceBuffer) { sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, _translation, 0); sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _rotation); - sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((const int16_t*) sourceBuffer, &_scale, 0); return sourceBuffer - startPosition; } diff --git a/libraries/avatars/src/Referential.h b/libraries/avatars/src/Referential.h index d824cad42b..70edecda62 100644 --- a/libraries/avatars/src/Referential.h +++ b/libraries/avatars/src/Referential.h @@ -39,7 +39,6 @@ public: glm::vec3 getTranslation() const { return _translation; } glm::quat getRotation() const { return _rotation; } - float getScale() const {return _scale; } QByteArray getExtraData() const { return _extraDataBuffer; } virtual void update() {} @@ -62,14 +61,13 @@ protected: AvatarData* _avatar; QByteArray _extraDataBuffer; - glm::vec3 _refPosition; - glm::quat _refRotation; - float _refScale; + glm::vec3 _refPosition; // position of object in world-frame + glm::quat _refRotation; // rotation of object in world-frame + glm::vec3 _lastRefDimension; // dimension of object when _translation was last computed - glm::vec3 _translation; - glm::quat _rotation; - float _scale; + glm::vec3 _translation; // offset of avatar in object local-frame + glm::quat _rotation; // rotation of avatar in object local-frame }; -#endif // hifi_Referential_h \ No newline at end of file +#endif // hifi_Referential_h From 93c77d557aa995f95972ea36d7e839e60d0fa33e Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Thu, 26 Feb 2015 14:14:17 -0800 Subject: [PATCH 04/56] EntityTree::findClosestEntity() now takes meters --- .../entities/src/EntityScriptingInterface.cpp | 3 +- libraries/entities/src/EntityTree.cpp | 3 +- libraries/entities/src/EntityTree.h | 2 + libraries/octree/src/ViewFrustum.h | 5 +-- tests/octree/src/ModelTests.cpp | 40 ++++++++----------- 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 0ee2e243f9..8e152f375d 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -180,8 +180,7 @@ EntityItemID EntityScriptingInterface::findClosestEntity(const glm::vec3& center EntityItemID result(UNKNOWN_ENTITY_ID, UNKNOWN_ENTITY_TOKEN, false); if (_entityTree) { _entityTree->lockForRead(); - const EntityItem* closestEntity = _entityTree->findClosestEntity(center/(float)TREE_SCALE, - radius/(float)TREE_SCALE); + const EntityItem* closestEntity = _entityTree->findClosestEntity(center, radius); _entityTree->unlock(); if (closestEntity) { result.id = closestEntity->getID(); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 68e220acbe..1e915bdd0f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -456,7 +456,8 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) } const EntityItem* EntityTree::findClosestEntity(glm::vec3 position, float targetRadius) { - FindNearPointArgs args = { position, targetRadius, false, NULL, FLT_MAX }; + // position and targetRadius are in meters, so we need to convert to TreeUnits in FindNearPointArgs + FindNearPointArgs args = { position / (float)TREE_SCALE, targetRadius / (float)TREE_SCALE, false, NULL, FLT_MAX }; lockForRead(); // NOTE: This should use recursion, since this is a spatial operation recurseTreeWithOperation(findNearPointOperation, &args); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index d8b9b9f38f..d85474cb33 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -95,6 +95,8 @@ public: void deleteEntities(QSet<EntityItemID> entityIDs, bool force = false); void removeEntityFromSimulation(EntityItem* entity); + /// \param position point of query in world-frame (meters) + /// \param targetRadius radius of query (meters) const EntityItem* findClosestEntity(glm::vec3 position, float targetRadius); EntityItem* findEntityByID(const QUuid& id); EntityItem* findEntityByEntityItemID(const EntityItemID& entityID); diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index c40bc37652..3f7921f9b7 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -30,7 +30,7 @@ const float DEFAULT_KEYHOLE_RADIUS = 3.0f; const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f; const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f; const float DEFAULT_NEAR_CLIP = 0.08f; -const float DEFAULT_FAR_CLIP = TREE_SCALE; +const float DEFAULT_FAR_CLIP = (float)TREE_SCALE; class ViewFrustum { public: @@ -119,7 +119,6 @@ public: OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const; void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; - // assumes box is in voxel scale, not TREE_SCALE, will scale view frustum's position accordingly void getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const; float distanceToCamera(const glm::vec3& point) const; @@ -134,7 +133,7 @@ private: void calculateOrthographic(); // camera location/orientation attributes - glm::vec3 _position = glm::vec3(0.0f); // the position in TREE_SCALE + glm::vec3 _position = glm::vec3(0.0f); // the position in world-frame glm::vec3 _positionVoxelScale = glm::vec3(0.0f); // the position in voxel scale glm::quat _orientation = glm::quat(); diff --git a/tests/octree/src/ModelTests.cpp b/tests/octree/src/ModelTests.cpp index 00cb3901e5..e46fbc157a 100644 --- a/tests/octree/src/ModelTests.cpp +++ b/tests/octree/src/ModelTests.cpp @@ -45,12 +45,9 @@ void EntityTests::entityTreeTests(bool verbose) { entityID.isKnownID = false; // this is a temporary workaround to allow local tree entities to be added with known IDs EntityItemProperties properties; float oneMeter = 1.0f; - //float halfMeter = oneMeter / 2.0f; float halfOfDomain = TREE_SCALE * 0.5f; - glm::vec3 positionNearOriginInMeters(oneMeter, oneMeter, oneMeter); // when using properties, these are in meter not tree units - glm::vec3 positionAtCenterInMeters(halfOfDomain, halfOfDomain, halfOfDomain); - glm::vec3 positionNearOriginInTreeUnits = positionNearOriginInMeters / (float)TREE_SCALE; - glm::vec3 positionAtCenterInTreeUnits = positionAtCenterInMeters / (float)TREE_SCALE; + glm::vec3 positionNearOrigin(oneMeter, oneMeter, oneMeter); // when using properties, these are in meter not tree units + glm::vec3 positionAtCenter(halfOfDomain, halfOfDomain, halfOfDomain); { testsTaken++; @@ -59,15 +56,14 @@ void EntityTests::entityTreeTests(bool verbose) { qDebug() << "Test" << testsTaken <<":" << qPrintable(testName); } - properties.setPosition(positionAtCenterInMeters); + properties.setPosition(positionAtCenter); // TODO: Fix these unit tests. - //properties.setRadius(halfMeter); //properties.setModelURL("http://s3.amazonaws.com/hifi-public/ozan/theater.fbx"); tree.addEntity(entityID, properties); - float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units - const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius); + float targetRadius = oneMeter * 2.0f; + const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius); const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID); EntityTreeElement* containingElement = tree.getContainingElement(entityID); AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); @@ -103,14 +99,14 @@ void EntityTests::entityTreeTests(bool verbose) { qDebug() << "Test" << testsTaken <<":" << qPrintable(testName); } - glm::vec3 newPosition = positionNearOriginInMeters; + glm::vec3 newPosition = positionNearOrigin; properties.setPosition(newPosition); tree.updateEntity(entityID, properties, true); - float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units - const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOriginInTreeUnits, targetRadius); + float targetRadius = oneMeter * 2.0f; + const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOrigin, targetRadius); const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID); EntityTreeElement* containingElement = tree.getContainingElement(entityID); AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); @@ -143,14 +139,14 @@ void EntityTests::entityTreeTests(bool verbose) { qDebug() << "Test" << testsTaken <<":" << qPrintable(testName); } - glm::vec3 newPosition = positionAtCenterInMeters; + glm::vec3 newPosition = positionAtCenter; properties.setPosition(newPosition); tree.updateEntity(entityID, properties, true); - float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units - const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius); + float targetRadius = oneMeter * 2.0f; + const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius); const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID); EntityTreeElement* containingElement = tree.getContainingElement(entityID); AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); @@ -184,11 +180,11 @@ void EntityTests::entityTreeTests(bool verbose) { qDebug() << "Test" << testsTaken <<":" << qPrintable(testName); } - float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units + float targetRadius = oneMeter * 2.0f; quint64 start = usecTimestampNow(); const EntityItem* foundEntityByRadius = NULL; for (int i = 0; i < TEST_ITERATIONS; i++) { - foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius); + foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius); } quint64 end = usecTimestampNow(); @@ -262,13 +258,11 @@ void EntityTests::entityTreeTests(bool verbose) { float randomX = randFloatInRange(1.0f ,(float)TREE_SCALE - 1.0f); float randomY = randFloatInRange(1.0f ,(float)TREE_SCALE - 1.0f); float randomZ = randFloatInRange(1.0f ,(float)TREE_SCALE - 1.0f); - glm::vec3 randomPositionInMeters(randomX,randomY,randomZ); - glm::vec3 randomPositionInTreeUnits = randomPositionInMeters / (float)TREE_SCALE; + glm::vec3 randomPosition(randomX,randomY,randomZ); - properties.setPosition(randomPositionInMeters); + properties.setPosition(randomPosition); // TODO: fix these unit tests - //properties.setRadius(halfMeter); //properties.setModelURL("http://s3.amazonaws.com/hifi-public/ozan/theater.fbx"); if (extraVerbose) { @@ -287,8 +281,8 @@ void EntityTests::entityTreeTests(bool verbose) { } quint64 startFind = usecTimestampNow(); - float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units - const EntityItem* foundEntityByRadius = tree.findClosestEntity(randomPositionInTreeUnits, targetRadius); + float targetRadius = oneMeter * 2.0f; + const EntityItem* foundEntityByRadius = tree.findClosestEntity(randomPosition, targetRadius); const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID); quint64 endFind = usecTimestampNow(); totalElapsedFind += (endFind - startFind); From 7210c7a88bc6fcfb9f6edc0a9dacc41c130ef5b0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Thu, 26 Feb 2015 15:16:59 -0800 Subject: [PATCH 05/56] added EntityTree::findEntitiesInMeters() progress toward conversion to meters --- .../src/EntityTreeRenderer.cpp | 12 +++---- libraries/entities/src/EntityItem.cpp | 6 ++++ libraries/entities/src/EntityItem.h | 2 ++ .../entities/src/EntityScriptingInterface.cpp | 2 +- libraries/entities/src/EntityTree.cpp | 5 +-- libraries/entities/src/EntityTree.h | 6 ++-- libraries/shared/src/AABox.cpp | 34 +++++++++++-------- libraries/shared/src/AABox.h | 8 +++-- 8 files changed, 46 insertions(+), 29 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index d784950267..c91913f3dd 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -96,7 +96,7 @@ void EntityTreeRenderer::init() { // make sure our "last avatar position" is something other than our current position, so that on our // first chance, we'll check for enter/leave entity events. - _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3(1.0f, 1.0f, 1.0f); + _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity); connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::checkAndCallPreload); @@ -276,19 +276,19 @@ void EntityTreeRenderer::update() { void EntityTreeRenderer::checkEnterLeaveEntities() { if (_tree && !_shuttingDown) { _tree->lockForWrite(); // so that our scripts can do edits if they want - glm::vec3 avatarPosition = _viewState->getAvatarPosition() / (float) TREE_SCALE; + glm::vec3 avatarPosition = _viewState->getAvatarPosition(); if (avatarPosition != _lastAvatarPosition) { - float radius = 1.0f / (float) TREE_SCALE; // for now, assume 1 meter radius + float radius = 1.0f; // for now, assume 1 meter radius QVector<const EntityItem*> foundEntities; QVector<EntityItemID> entitiesContainingAvatar; // find the entities near us - static_cast<EntityTree*>(_tree)->findEntities(avatarPosition, radius, foundEntities); + static_cast<EntityTree*>(_tree)->findEntitiesInMeters(avatarPosition, radius, foundEntities); // create a list of entities that actually contain the avatar's position foreach(const EntityItem* entity, foundEntities) { - if (entity->contains(avatarPosition)) { + if (entity->containsInMeters(avatarPosition)) { entitiesContainingAvatar << entity->getEntityItemID(); } } @@ -341,7 +341,7 @@ void EntityTreeRenderer::leaveAllEntities() { // make sure our "last avatar position" is something other than our current position, so that on our // first chance, we'll check for enter/leave entity events. - _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3(1.0f, 1.0f, 1.0f); + _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); _tree->unlock(); } } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 69b2370264..b24925dd6c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -951,6 +951,12 @@ AACube EntityItem::getMinimumAACube() const { return AACube(cornerOfCube, longestSide); } +AABox EntityItem::getAABoxInMeters() const { + AABox box = getAABox(); + box *= (float)TREE_SCALE; + return box; +} + AABox EntityItem::getAABox() const { // _position represents the position of the registration point. diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 9ed55cc417..1aad9c27e0 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -215,6 +215,7 @@ public: float getSize() const; /// get maximum dimension in domain scale units (0.0 - 1.0) AACube getMaximumAACube() const; AACube getMinimumAACube() const; + AABox getAABoxInMeters() const; /// axis aligned bounding box in world-frame (meters) AABox getAABox() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0) const QString& getScript() const { return _script; } @@ -253,6 +254,7 @@ public: // TODO: We need to get rid of these users of getRadius()... float getRadius() const; + virtual bool containsInMeters(const glm::vec3& point) const { return getAABoxInMeters().contains(point); } virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } virtual void computeShapeInfo(ShapeInfo& info) const; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 8e152f375d..4ee54ca8ca 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -204,7 +204,7 @@ QVector<EntityItemID> EntityScriptingInterface::findEntities(const glm::vec3& ce if (_entityTree) { _entityTree->lockForRead(); QVector<const EntityItem*> entities; - _entityTree->findEntities(center/(float)TREE_SCALE, radius/(float)TREE_SCALE, entities); + _entityTree->findEntitiesInMeters(center, radius, entities); _entityTree->unlock(); foreach (const EntityItem* entity, entities) { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 1e915bdd0f..1c820564f0 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -491,8 +491,9 @@ bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData) } // NOTE: assumes caller has handled locking -void EntityTree::findEntities(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities) { - FindAllNearPointArgs args = { center, radius }; +void EntityTree::findEntitiesInMeters(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities) { + // position and targetRadius are in meters, so we need to convert to TreeUnits in FindNearPointArgs + FindAllNearPointArgs args = { center / (float)TREE_SCALE, radius / (float)TREE_SCALE }; // NOTE: This should use recursion, since this is a spatial operation recurseTreeWithOperation(findInSphereOperation, &args); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index d85474cb33..e748df2548 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -105,11 +105,11 @@ public: /// finds all entities that touch a sphere - /// \param center the center of the sphere - /// \param radius the radius of the sphere + /// \param center the center of the sphere in world-frame (meters) + /// \param radius the radius of the sphere in world-frame (meters) /// \param foundEntities[out] vector of const EntityItem* /// \remark Side effect: any initial contents in foundEntities will be lost - void findEntities(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities); + void findEntitiesInMeters(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities); /// finds all entities that touch a cube /// \param cube the query cube diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index 8823071132..cf02720976 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -471,17 +471,23 @@ AABox AABox::clamp(float min, float max) const { return AABox(clampedCorner, clampedScale); } -AABox& AABox::operator += (const glm::vec3& point) { - _corner = glm::min(_corner, point); - _scale = glm::max(_scale, point - _corner); - - return (*this); -} - -AABox& AABox::operator += (const AABox& box) { - if (!box.isInvalid()) { - (*this) += box._corner; - _scale = glm::max(_scale, box.calcTopFarLeft() - _corner); - } - return (*this); -} +AABox& AABox::operator += (const glm::vec3& point) { + _corner = glm::min(_corner, point); + _scale = glm::max(_scale, point - _corner); + + return (*this); +} + +AABox& AABox::operator += (const AABox& box) { + if (!box.isInvalid()) { + (*this) += box._corner; + _scale = glm::max(_scale, box.calcTopFarLeft() - _corner); + } + return (*this); +} + +AABox& AABox::operator *= (float multiplier) { + _corner *= multiplier; + _scale *= multiplier; + return (*this); +} diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index d862957642..71c1cf0650 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -72,9 +72,11 @@ public: AABox clamp(const glm::vec3& min, const glm::vec3& max) const; AABox clamp(float min, float max) const; - AABox& operator += (const glm::vec3& point); - AABox& operator += (const AABox& box); - + AABox& operator += (const glm::vec3& point); + AABox& operator += (const AABox& box); + + AABox& operator *= (float multiplier); + bool isInvalid() const { return _corner == glm::vec3(std::numeric_limits<float>::infinity()); } private: From 64c28fe925061a924da6d3258e4c4088e67fa15d Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Thu, 26 Feb 2015 15:36:59 -0800 Subject: [PATCH 06/56] remove EntityItem::getSize() --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 5 ----- libraries/entities/src/EntityItem.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b7ea64ebef..5f2c0baa5f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -115,8 +115,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) { bool drawAsModel = hasModel(); glm::vec3 position = getPositionInMeters(); - float size = getSize() * (float)TREE_SCALE; glm::vec3 dimensions = getDimensionsInMeters(); + float size = glm::length(dimensions); if (drawAsModel) { remapTextures(); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index b24925dd6c..ee314d514f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -888,11 +888,6 @@ void EntityItem::recordCreationTime() { } -// TODO: is this really correct? how do we use size, does it need to handle rotation? -float EntityItem::getSize() const { - return glm::length(_dimensions); -} - // TODO: doesn't this need to handle rotation? glm::vec3 EntityItem::getCenterInDomainUnits() const { return _position + (_dimensions * (glm::vec3(0.5f,0.5f,0.5f) - _registrationPoint)); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 1aad9c27e0..09a2c7bc6b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -212,7 +212,6 @@ public: quint64 getExpiry() const; // position, size, and bounds related helpers - float getSize() const; /// get maximum dimension in domain scale units (0.0 - 1.0) AACube getMaximumAACube() const; AACube getMinimumAACube() const; AABox getAABoxInMeters() const; /// axis aligned bounding box in world-frame (meters) From 7836bb4dcd8ca0436a108b8de6b419b383a5f87d Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Thu, 26 Feb 2015 17:42:17 -0800 Subject: [PATCH 07/56] rayIntersection uses meters instead of tree units --- .../src/RenderableLightEntityItem.cpp | 2 +- .../src/RenderableLightEntityItem.h | 2 +- .../src/RenderableModelEntityItem.cpp | 19 +++---------------- .../src/RenderableModelEntityItem.h | 2 +- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 10 +++++----- libraries/entities/src/EntityTreeElement.h | 2 +- libraries/entities/src/SphereEntityItem.cpp | 6 +++--- libraries/entities/src/SphereEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 8 ++++---- libraries/entities/src/TextEntityItem.h | 2 +- libraries/octree/src/Octree.cpp | 6 +----- libraries/octree/src/OctreeElement.cpp | 4 +--- libraries/shared/src/AACube.h | 8 ++++++++ 14 files changed, 32 insertions(+), 43 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 5a20633044..ab6445cc6e 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -80,7 +80,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { #endif }; -bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +bool RenderableLightEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index cfafb85983..1ea3e7e884 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -24,7 +24,7 @@ public: virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5f2c0baa5f..6c1d24b845 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -254,29 +254,16 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { return properties; } -bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +bool RenderableModelEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { if (!_model) { return true; } + //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersectionInMeters() precisionPicking:" << precisionPicking; - glm::vec3 originInMeters = origin * (float)TREE_SCALE; QString extraInfo; - float localDistance; - - //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; - - bool intersectsModel = _model->findRayIntersectionAgainstSubMeshes(originInMeters, direction, - localDistance, face, extraInfo, precisionPicking); - - if (intersectsModel) { - // NOTE: findRayIntersectionAgainstSubMeshes() does work in meters, but we're expected to return - // results in tree scale. - distance = localDistance / (float)TREE_SCALE; - } - - return intersectsModel; // we only got here if we intersected our non-aabox + return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 65cded0207..7e20b0bd15 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -44,7 +44,7 @@ public: virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 09a2c7bc6b..64fe712e43 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -139,7 +139,7 @@ public: virtual void debugDump() const; virtual bool supportsDetailedRayIntersection() const { return false; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return true; } diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 4b4bae662a..abdc7c4768 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -469,7 +469,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 return false; } -bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +bool EntityTreeElement::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube) { @@ -485,7 +485,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); - AABox entityBox = entity->getAABox(); + AABox entityBox = entity->getAABoxInMeters(); float localDistance; BoxFace localFace; @@ -494,11 +494,11 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); - glm::mat4 translation = glm::translate(entity->getPositionInDomainUnits()); + glm::mat4 translation = glm::translate(entity->getPositionInMeters()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getDimensionsInDomainUnits(); + glm::vec3 dimensions = entity->getDimensionsInMeters(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -513,7 +513,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con if (localDistance < distance) { // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { - if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, + if (entity->findDetailedRayIntersectionInMeters(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject, precisionPicking)) { if (localDistance < distance) { diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index 0b28dd30d0..424e3ca520 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -135,7 +135,7 @@ public: virtual bool deleteApproved() const { return !hasEntities(); } virtual bool canRayIntersect() const { return hasEntities(); } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube); diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 6b773d8189..75788c979f 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -94,13 +94,13 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); } -bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +bool SphereEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { // determine the ray in the frame of the entity transformed from a unit sphere - glm::mat4 translation = glm::translate(getPositionInDomainUnits()); + glm::mat4 translation = glm::translate(getPositionInMeters()); glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 scale = glm::scale(getDimensionsInDomainUnits()); + glm::mat4 scale = glm::scale(getDimensionsInMeters()); glm::mat4 registration = glm::translate(glm::vec3(0.5f, 0.5f, 0.5f) - getRegistrationPoint()); glm::mat4 entityToWorldMatrix = translation * rotation * scale * registration; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index f79a2db7ff..f8419e75b9 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -56,7 +56,7 @@ public: virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; } virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 051463929c..a716bba0e2 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -122,7 +122,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits } -bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +bool TextEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { @@ -136,7 +136,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); glm::vec3 normal = _rotation * UNROTATED_NORMAL; plane.setNormal(normal); - plane.setPoint(_position); // the position is definitely a point on our plane + plane.setPoint(getPositionInMeters()); // the position is definitely a point on our plane bool intersects = plane.findRayIntersection(rayInfo); @@ -145,11 +145,11 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const // now we know the point the ray hit our plane glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(getPositionInDomainUnits()); + glm::mat4 translation = glm::translate(getPositionInMeters()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = getDimensionsInDomainUnits(); + glm::vec3 dimensions = getDimensionsInMeters(); glm::vec3 registrationPoint = getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); AABox entityFrameBox(corner, dimensions); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 5804c9af1e..60f82f4936 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -46,7 +46,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData); virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index e925ea5aba..4a57b8047f 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -706,7 +706,7 @@ bool findRayIntersectionOp(OctreeElement* element, void* extraData) { bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, Octree::lockType lockType, bool* accurateResult, bool precisionPicking) { - RayArgs args = { origin / (float)(TREE_SCALE), direction, element, distance, face, + RayArgs args = { origin, direction, element, distance, face, intersectedObject, false, precisionPicking}; distance = FLT_MAX; @@ -726,10 +726,6 @@ bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc recurseTreeWithOperation(findRayIntersectionOp, &args); - if (args.found) { - args.distance *= (float)(TREE_SCALE); // scale back up to meters - } - if (gotLock) { unlock(); } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 93792678e2..b686796b9d 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1338,13 +1338,11 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 keepSearching = true; // assume that we will continue searching after this. AACube cube = getAACube(); + cube *= (float)TREE_SCALE; float distanceToElementCube = std::numeric_limits<float>::max(); float distanceToElementDetails = distance; BoxFace localFace; - AACube debugCube = cube; - debugCube.scale((float)TREE_SCALE); - // if the ray doesn't intersect with our cube, we can stop searching! if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { keepSearching = false; // no point in continuing to search diff --git a/libraries/shared/src/AACube.h b/libraries/shared/src/AACube.h index b29bc49bef..5bcf9527cf 100644 --- a/libraries/shared/src/AACube.h +++ b/libraries/shared/src/AACube.h @@ -63,6 +63,8 @@ public: AABox clamp(const glm::vec3& min, const glm::vec3& max) const; AABox clamp(float min, float max) const; + AACube& operator *= (float scale); + private: glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const; @@ -74,6 +76,12 @@ private: float _scale; }; +inline AACube& AACube::operator *= (float scale) { + _corner *= scale; + _scale *= scale; + return *this; +} + inline bool operator==(const AACube& a, const AACube& b) { return a.getCorner() == b.getCorner() && a.getScale() == b.getScale(); } From e1954d3e1dee87ac29aa52ec24ceab9f5cb1d17e Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Sun, 1 Mar 2015 15:19:26 -0800 Subject: [PATCH 08/56] spherical queries into Octree use meters --- libraries/entities/src/EntityTree.cpp | 7 ++++--- libraries/entities/src/EntityTree.h | 2 +- libraries/octree/src/Octree.cpp | 11 +++++++---- libraries/octree/src/OctreeElement.cpp | 5 ++++- libraries/octree/src/OctreeElement.h | 4 ++++ 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 1c820564f0..4c1963088c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -476,8 +476,9 @@ public: bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData) { FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData); glm::vec3 penetration; - bool sphereIntersection = element->getAACube().findSpherePenetration(args->position, - args->targetRadius, penetration); + AACube cube = element->getAACube(); + cube *= (float)TREE_SCALE; + bool sphereIntersection = cube.findSpherePenetration(args->position, args->targetRadius, penetration); // If this element contains the point, then search it... if (sphereIntersection) { @@ -493,7 +494,7 @@ bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData) // NOTE: assumes caller has handled locking void EntityTree::findEntitiesInMeters(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities) { // position and targetRadius are in meters, so we need to convert to TreeUnits in FindNearPointArgs - FindAllNearPointArgs args = { center / (float)TREE_SCALE, radius / (float)TREE_SCALE }; + FindAllNearPointArgs args = { center, radius }; // NOTE: This should use recursion, since this is a spatial operation recurseTreeWithOperation(findInSphereOperation, &args); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index e748df2548..f8a8262afd 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -169,7 +169,7 @@ private: bool updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties, EntityTreeElement* containingElement, bool allowLockChange); static bool findNearPointOperation(OctreeElement* element, void* extraData); - static bool findInSphereOperation(OctreeElement* element, void* extraData); + static bool findInSphereOperationInMeters(OctreeElement* element, void* extraData); static bool findInCubeOperation(OctreeElement* element, void* extraData); static bool sendEntitiesOperation(OctreeElement* element, void* extraData); diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 4a57b8047f..a1df449135 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -748,8 +748,11 @@ public: bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { SphereArgs* args = static_cast<SphereArgs*>(extraData); + // the details in args is in meters (world-frame) so we have to scale the element cube up + AACube box = element->getAACube(); + box *= (float)TREE_SCALE; + // coarse check against bounds - const AACube& box = element->getAACube(); if (!box.expandedContains(args->center, args->radius)) { return false; } @@ -758,7 +761,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) { // NOTE: it is possible for this penetration accumulation algorithm to produce a // final penetration vector with zero length. - args->penetration = addPenetrations(args->penetration, elementPenetration * (float)(TREE_SCALE)); + args->penetration = addPenetrations(args->penetration, elementPenetration); args->found = true; } } @@ -772,8 +775,8 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v void** penetratedObject, Octree::lockType lockType, bool* accurateResult) { SphereArgs args = { - center / (float)(TREE_SCALE), - radius / (float)(TREE_SCALE), + center, + radius, penetration, false, NULL }; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index b686796b9d..954d0b7847 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1390,7 +1390,10 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const { - return _cube.findSpherePenetration(center, radius, penetration); + // center and radius are in meters, so we have to scale the _cube into world-frame + AACube cube = _cube; + cube *= (float)TREE_SCALE; + return cube.findSpherePenetration(center, radius, penetration); } // TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)... diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 8c83d9976e..e2229b2214 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -125,6 +125,10 @@ public: bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube); + /// \param center center of sphere in meters + /// \param radius radius of sphere in meters + /// \param[out] penetration pointing into cube from sphere + /// \param penetratedObject unused virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; From c2e78931c6c588ef54df09d78489ddb772255058 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Sun, 1 Mar 2015 15:21:01 -0800 Subject: [PATCH 09/56] revert namechange: use compiler find all instances --- libraries/entities/src/EntityTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index f8a8262afd..e748df2548 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -169,7 +169,7 @@ private: bool updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties, EntityTreeElement* containingElement, bool allowLockChange); static bool findNearPointOperation(OctreeElement* element, void* extraData); - static bool findInSphereOperationInMeters(OctreeElement* element, void* extraData); + static bool findInSphereOperation(OctreeElement* element, void* extraData); static bool findInCubeOperation(OctreeElement* element, void* extraData); static bool sendEntitiesOperation(OctreeElement* element, void* extraData); From 90b69b1ee00aa2fd38faf17625bb352b34e213c8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Sun, 1 Mar 2015 15:58:10 -0800 Subject: [PATCH 10/56] replace some "InDomainUnits" calls with "InMeters" --- libraries/entities/src/EntityItem.cpp | 4 ++-- libraries/entities/src/EntityItem.h | 4 ++-- libraries/entities/src/EntityTree.cpp | 9 +++++---- libraries/entities/src/EntityTreeElement.cpp | 14 +++++++------- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ee314d514f..8aed4b5a4d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -992,8 +992,8 @@ void EntityItem::setRadius(float value) { // ... radius = cornerToCornerLength / 2.0f // ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) // ... radius = sqrt(3 x maxDimension ^ 2) / 2.0f; -float EntityItem::getRadius() const { - float length = glm::length(_dimensions); +float EntityItem::getRadiusInMeters() const { + float length = glm::length(_dimensions) * (float)TREE_SCALE; float radius = length / 2.0f; return radius; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 64fe712e43..662bde216a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -250,8 +250,8 @@ public: const QString& getUserData() const { return _userData; } void setUserData(const QString& value) { _userData = value; } - // TODO: We need to get rid of these users of getRadius()... - float getRadius() const; + // TODO: get rid of users of getRadius()... + float getRadiusInMeters() const; virtual bool containsInMeters(const glm::vec3& point) const { return getAABoxInMeters().contains(point); } virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 4c1963088c..aef5b1d2bf 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -424,8 +424,9 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element); glm::vec3 penetration; - bool sphereIntersection = entityTreeElement->getAACube().findSpherePenetration(args->position, - args->targetRadius, penetration); + AACube cube = entityTreeElement->getAACube(); + cube *= (float)TREE_SCALE; + bool sphereIntersection = cube.findSpherePenetration(args->position, args->targetRadius, penetration); // If this entityTreeElement contains the point, then search it... if (sphereIntersection) { @@ -433,7 +434,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) // we may have gotten NULL back, meaning no entity was available if (thisClosestEntity) { - glm::vec3 entityPosition = thisClosestEntity->getPositionInDomainUnits(); + glm::vec3 entityPosition = thisClosestEntity->getPositionInMeters(); float distanceFromPointToEntity = glm::distance(entityPosition, args->position); // If we're within our target radius @@ -457,7 +458,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) const EntityItem* EntityTree::findClosestEntity(glm::vec3 position, float targetRadius) { // position and targetRadius are in meters, so we need to convert to TreeUnits in FindNearPointArgs - FindNearPointArgs args = { position / (float)TREE_SCALE, targetRadius / (float)TREE_SCALE, false, NULL, FLT_MAX }; + FindNearPointArgs args = { position, targetRadius, false, NULL, FLT_MAX }; lockForRead(); // NOTE: This should use recursion, since this is a spatial operation recurseTreeWithOperation(findNearPointOperation, &args); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index abdc7c4768..f746a03054 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -549,8 +549,8 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad QList<EntityItem*>::const_iterator entityEnd = _entityItems->end(); while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); - glm::vec3 entityCenter = entity->getPositionInDomainUnits(); - float entityRadius = entity->getRadius(); + glm::vec3 entityCenter = entity->getPositionInMeters(); + float entityRadius = entity->getRadiusInMeters(); // don't penetrate yourself if (entityCenter == center && entityRadius == radius) { @@ -585,7 +585,7 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const float closestEntityDistance = FLT_MAX; uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { - float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPositionInDomainUnits()); + float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPositionInMeters()); if (distanceToEntity < closestEntityDistance) { closestEntity = (*_entityItems)[i]; } @@ -598,8 +598,8 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { const EntityItem* entity = (*_entityItems)[i]; - float distance = glm::length(entity->getPositionInDomainUnits() - searchPosition); - if (distance < searchRadius + entity->getRadius()) { + float distance = glm::length(entity->getPositionInMeters() - searchPosition); + if (distance < searchRadius + entity->getRadiusInMeters()) { foundEntities.push_back(entity); } } @@ -612,11 +612,11 @@ void EntityTreeElement::getEntities(const AACube& box, QVector<EntityItem*>& fou AACube entityCube; while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); - float radius = entity->getRadius(); + float radius = entity->getRadiusInMeters(); // NOTE: we actually do cube-cube collision queries here, which is sloppy but good enough for now // TODO: decide whether to replace entityCube-cube query with sphere-cube (requires a square root // but will be slightly more accurate). - entityCube.setBox(entity->getPositionInDomainUnits() - glm::vec3(radius), 2.0f * radius); + entityCube.setBox(entity->getPositionInMeters() - glm::vec3(radius), 2.0f * radius); if (entityCube.touches(box)) { foundEntities.push_back(entity); } From 30b77d420022334a5031c544fb9d1963bd79e3ad Mon Sep 17 00:00:00 2001 From: David Rowe <david@ctrlaltstudio.com> Date: Tue, 3 Mar 2015 22:07:12 -0800 Subject: [PATCH 11/56] Don't crash if avatar model at start-up or loaded is skeletonless --- interface/src/avatar/MyAvatar.cpp | 6 ++++++ interface/src/avatar/SkeletonModel.cpp | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9c83942439..9213d7416f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -195,6 +195,12 @@ void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("skeleton"); _skeletonModel.simulate(deltaTime); } + + if (!_skeletonModel.hasSkeleton()) { + // All the simulation that can be done has been done + return; + } + { PerformanceTimer perfTimer("attachments"); simulateAttachments(deltaTime); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index fa9846fd7d..03baa334e5 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -721,7 +721,8 @@ void SkeletonModel::buildShapes() { } const FBXGeometry& geometry = _geometry->getFBXGeometry(); - if (geometry.joints.isEmpty()) { + if (geometry.joints.isEmpty() || geometry.rootJointIndex == -1) { + // rootJointIndex == -1 if the avatar model has no skeleton return; } From aad3f1dfd9c71fb8feb3bb0fd7f5e2a451d97578 Mon Sep 17 00:00:00 2001 From: David Rowe <david@ctrlaltstudio.com> Date: Tue, 3 Mar 2015 22:07:45 -0800 Subject: [PATCH 12/56] Automatically switch to default model if avatar model is skeletonless --- interface/src/Application.cpp | 19 +++++++++++++++++++ interface/src/Application.h | 2 ++ interface/src/avatar/MyAvatar.cpp | 1 - interface/src/avatar/SkeletonModel.cpp | 5 +++++ interface/src/avatar/SkeletonModel.h | 8 +++++++- 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6484e364bc..f1d9dcbef2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -490,6 +490,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)), bandwidthRecorder.data(), SLOT(updateInboundData(const quint8, const int))); + connect(&_myAvatar->getSkeletonModel(), &SkeletonModel::skeletonLoaded, + this, &Application::checkSkeleton, Qt::QueuedConnection); + // check first run... if (_firstRun.get()) { qDebug() << "This is a first run..."; @@ -4006,3 +4009,19 @@ void Application::notifyPacketVersionMismatch() { msgBox.exec(); } } + +void Application::checkSkeleton() { + if (_myAvatar->getSkeletonModel().isActive() && !_myAvatar->getSkeletonModel().hasSkeleton()) { + qDebug() << "MyAvatar model has no skeleton"; + + QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded..."; + QMessageBox msgBox; + msgBox.setText(message); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Warning); + msgBox.exec(); + + _myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL); + _myAvatar->sendIdentityPacket(); + } +} diff --git a/interface/src/Application.h b/interface/src/Application.h index 91a5f7547b..81025245fa 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -584,6 +584,8 @@ private: QTimer _settingsTimer; GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features + + void checkSkeleton(); }; #endif // hifi_Application_h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9213d7416f..c2a957dc72 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -12,7 +12,6 @@ #include <algorithm> #include <vector> -#include <QMessageBox> #include <QBuffer> #include <glm/gtx/norm.hpp> diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 03baa334e5..fbb622b30a 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -81,6 +81,8 @@ void SkeletonModel::setJointStates(QVector<JointState> states) { if (_enableShapes) { buildShapes(); } + + emit skeletonLoaded(); } const float PALM_PRIORITY = DEFAULT_PRIORITY; @@ -1007,3 +1009,6 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glPopMatrix(); } +bool SkeletonModel::hasSkeleton() { + return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false; +} diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index d28d1a8aef..74d0ed0324 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -123,7 +123,13 @@ public: void resetShapePositionsToDefaultPose(); // DEBUG method void renderRagdoll(); - + + bool hasSkeleton(); + +signals: + + void skeletonLoaded(); + protected: void buildShapes(); From 8686e090c9fd32a3aeec629fe7677017012a4989 Mon Sep 17 00:00:00 2001 From: David Rowe <david@ctrlaltstudio.com> Date: Tue, 3 Mar 2015 22:30:45 -0800 Subject: [PATCH 13/56] Don't upload skeletonless avatar model to HiFi servers --- interface/src/ModelUploader.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index ad73d119a3..32973b001d 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -177,6 +177,22 @@ bool ModelUploader::zip() { } QByteArray fbxContents = fbx.readAll(); FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); + + // Make sure that a skeleton model has a skeleton + if (_modelType == SKELETON_MODEL) { + if (geometry.rootJointIndex == -1) { + + QString message = "Your selected skeleton model has no skeleton.\n\nThe upload will be canceled."; + QMessageBox msgBox; + msgBox.setWindowTitle("Model Upload"); + msgBox.setText(message); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Warning); + msgBox.exec(); + + return false; + } + } // make sure we have some basic mappings populateBasicMapping(mapping, filename, geometry); From b9cbd1ea6eb2869680474635ecdff7bd6eb73f5c Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 4 Mar 2015 09:38:37 -0800 Subject: [PATCH 14/56] witch internal EntityItem data to use meters --- .../src/octree/OctreePacketProcessor.cpp | 4 +- .../src/EntityTreeRenderer.cpp | 6 +- libraries/entities/src/EntityItem.cpp | 119 +++++++++--------- libraries/entities/src/EntityItem.h | 57 +++++---- libraries/entities/src/SphereEntityItem.cpp | 3 - libraries/entities/src/TextEntityItem.cpp | 10 +- libraries/entities/src/TextEntityItem.h | 1 + 7 files changed, 103 insertions(+), 97 deletions(-) diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index 65a5c6f1a1..f87e978b66 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -59,7 +59,9 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, PacketVersion expectedVersion = versionForPacketType(voxelPacketType); // check version of piggyback packet against expected version - if (packetVersion != expectedVersion) { + if (packetVersion != expectedVersion + // TODO: remove the temporary exception below when everyone is using meters instead of DomainUnits + && !(PacketTypeEntityData == voxelPacketType && packetVersion < VERSION_ENTITIES_USE_METERS)) { static QMultiMap<QUuid, PacketType> versionDebugSuppressMap; QUuid senderUUID = uuidFromPacketHeader(packet); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c91913f3dd..94b0e68730 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -470,7 +470,7 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg AACube maxCube = entity->getMaximumAACube(); AACube minCube = entity->getMinimumAACube(); - AABox entityBox = entity->getAABox(); + AABox entityBox = entity->getAABoxInMeters(); maxCube.scale((float) TREE_SCALE); minCube.scale((float) TREE_SCALE); @@ -542,9 +542,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) if (entityItem->isVisible()) { // render entityItem - AABox entityBox = entityItem->getAABox(); - - entityBox.scale(TREE_SCALE); + AABox entityBox = entityItem->getAABoxInMeters(); // TODO: some entity types (like lights) might want to be rendered even // when they are outside of the view frustum... diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8aed4b5a4d..12eaeff62f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -221,12 +221,12 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet // PROP_PAGED_PROPERTY, // PROP_CUSTOM_PROPERTIES_INCLUDED, - APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPositionInDomainUnits()); - APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensionsInDomainUnits()); // NOTE: PROP_RADIUS obsolete + APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPositionInMeters()); + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensionsInMeters()); // NOTE: PROP_RADIUS obsolete APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation()); APPEND_ENTITY_PROPERTY(PROP_DENSITY, appendValue, getDensity()); - APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocityInDomainUnits()); - APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravityInDomainUnits()); + APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocityInMeters()); + APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravityInMeters()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); @@ -501,8 +501,12 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef EntityPropertyFlags propertyFlags = encodedPropertyFlags; dataAt += propertyFlags.getEncodedLength(); bytesRead += propertyFlags.getEncodedLength(); - - READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePositionInDomainUnits); + bool useMeters = (args.bitstreamVersion == VERSION_ENTITIES_USE_METERS); + if (useMeters) { + READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePositionInMeters); + } else { + READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePositionInDomainUnits); + } // Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) { @@ -516,13 +520,22 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } } } else { - READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensionsInDomainUnits); + if (useMeters) { + READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensionsInMeters); + } else { + READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensionsInDomainUnits); + } } READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation); READ_ENTITY_PROPERTY_SETTER(PROP_DENSITY, float, updateDensity); - READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits); - READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits); + if (useMeters) { + READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocityInMeters); + READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravityInMeters); + } else { + READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits); + READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits); + } READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping); READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT, setScript); @@ -587,8 +600,7 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s } float EntityItem::computeMass() const { - // NOTE: we group the operations here in and attempt to reduce floating point error. - return ((_density * (_volumeMultiplier * _dimensions.x)) * _dimensions.y) * _dimensions.z; + return _density * _volumeMultiplier * _dimensions.x * _dimensions.y * _dimensions.z; } void EntityItem::setDensity(float density) { @@ -609,10 +621,7 @@ void EntityItem::setMass(float mass) { // we must protect the density range to help maintain stability of physics simulation // therefore this method might not accept the mass that is supplied. - // NOTE: when computing the volume we group the _volumeMultiplier (typically a very large number, due - // to the TREE_SCALE transformation) with the first dimension component (typically a very small number) - // in an attempt to reduce floating point error of the final result. - float volume = (_volumeMultiplier * _dimensions.x) * _dimensions.y * _dimensions.z; + float volume = _volumeMultiplier * _dimensions.x * _dimensions.y * _dimensions.z; // compute new density const float MIN_VOLUME = 1.0e-6f; // 0.001mm^3 @@ -717,7 +726,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { if (hasVelocity()) { // linear damping - glm::vec3 velocity = getVelocityInDomainUnits(); + glm::vec3 velocity = getVelocityInMeters(); if (_damping > 0.0f) { velocity *= powf(1.0f - _damping, timeElapsed); #ifdef WANT_DEBUG @@ -729,7 +738,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { } // integrate position forward - glm::vec3 position = getPositionInDomainUnits(); + glm::vec3 position = getPositionInMeters(); glm::vec3 newPosition = position + (velocity * timeElapsed); #ifdef WANT_DEBUG @@ -749,19 +758,19 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { if (hasGravity()) { // handle resting on surface case, this is definitely a bit of a hack, and it only works on the // "ground" plane of the domain, but for now it's what we've got - velocity += getGravityInDomainUnits() * timeElapsed; + velocity += getGravityInMeters() * timeElapsed; } float speed = glm::length(velocity); - const float EPSILON_LINEAR_VELOCITY_LENGTH = 0.001f / (float)TREE_SCALE; // 1mm/sec + const float EPSILON_LINEAR_VELOCITY_LENGTH = 0.001f; // 1mm/sec if (speed < EPSILON_LINEAR_VELOCITY_LENGTH) { - setVelocityInDomainUnits(ENTITY_ITEM_ZERO_VEC3); + setVelocityInMeters(ENTITY_ITEM_ZERO_VEC3); if (speed > 0.0f) { _dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE; } } else { - setPositionInDomainUnits(position); - setVelocityInDomainUnits(velocity); + setPositionInMeters(position); + setVelocityInMeters(velocity); } #ifdef WANT_DEBUG @@ -889,7 +898,7 @@ void EntityItem::recordCreationTime() { // TODO: doesn't this need to handle rotation? -glm::vec3 EntityItem::getCenterInDomainUnits() const { +glm::vec3 EntityItem::getCenterInMeters() const { return _position + (_dimensions * (glm::vec3(0.5f,0.5f,0.5f) - _registrationPoint)); } @@ -947,13 +956,6 @@ AACube EntityItem::getMinimumAACube() const { } AABox EntityItem::getAABoxInMeters() const { - AABox box = getAABox(); - box *= (float)TREE_SCALE; - return box; -} - -AABox EntityItem::getAABox() const { - // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; @@ -968,6 +970,11 @@ AABox EntityItem::getAABox() const { return AABox(rotatedExtentsRelativeToRegistrationPoint); } +AABox EntityItem::getAABoxInDomainUnits() const { + AABox box = getAABoxInMeters(); + box *= 1.0f / (float)TREE_SCALE; + return box; +} // NOTE: This should only be used in cases of old bitstreams which only contain radius data // 0,0,0 --> maxDimension,maxDimension,maxDimension @@ -993,9 +1000,7 @@ void EntityItem::setRadius(float value) { // ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) // ... radius = sqrt(3 x maxDimension ^ 2) / 2.0f; float EntityItem::getRadiusInMeters() const { - float length = glm::length(_dimensions) * (float)TREE_SCALE; - float radius = length / 2.0f; - return radius; + return 0.5f * glm::length(_dimensions); } void EntityItem::computeShapeInfo(ShapeInfo& info) const { @@ -1003,6 +1008,7 @@ void EntityItem::computeShapeInfo(ShapeInfo& info) const { } const float MIN_POSITION_DELTA = 0.0001f; +const float MIN_DIMENSIONS_DELTA = 0.0005f; const float MIN_ALIGNMENT_DOT = 0.999999f; const float MIN_VELOCITY_DELTA = 0.01f; const float MIN_DAMPING_DELTA = 0.001f; @@ -1010,31 +1016,31 @@ const float MIN_GRAVITY_DELTA = 0.001f; const float MIN_SPIN_DELTA = 0.0003f; void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) { - if (glm::distance(_position, value) * (float)TREE_SCALE > MIN_POSITION_DELTA) { - _position = value; + glm::vec3 position = value * (float)TREE_SCALE; + if (glm::distance(_position, position) > MIN_POSITION_DELTA) { + _position = position; _dirtyFlags |= EntityItem::DIRTY_POSITION; } } void EntityItem::updatePositionInMeters(const glm::vec3& value) { - glm::vec3 position = glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f); - if (glm::distance(_position, position) * (float)TREE_SCALE > MIN_POSITION_DELTA) { - _position = position; + if (glm::distance(_position, value) > MIN_POSITION_DELTA) { + _position = value; _dirtyFlags |= EntityItem::DIRTY_POSITION; } } void EntityItem::updateDimensionsInDomainUnits(const glm::vec3& value) { - if (_dimensions != value) { - _dimensions = glm::abs(value); + glm::vec3 dimensions = value * (float)TREE_SCALE; + if (glm::distance(_dimensions, dimensions) > MIN_DIMENSIONS_DELTA) { + _dimensions = glm::abs(dimensions); _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); } } void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { - glm::vec3 dimensions = glm::abs(value) / (float) TREE_SCALE; - if (_dimensions != dimensions) { - _dimensions = dimensions; + if (glm::distance(_dimensions, value) > MIN_DIMENSIONS_DELTA) { + _dimensions = value; _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); } } @@ -1051,10 +1057,7 @@ void EntityItem::updateMass(float mass) { // we must protect the density range to help maintain stability of physics simulation // therefore this method might not accept the mass that is supplied. - // NOTE: when computing the volume we group the _volumeMultiplier (typically a very large number, due - // to the TREE_SCALE transformation) with the first dimension component (typically a very small number) - // in an attempt to reduce floating point error of the final result. - float volume = (_volumeMultiplier * _dimensions.x) * _dimensions.y * _dimensions.z; + float volume = _volumeMultiplier * _dimensions.x * _dimensions.y * _dimensions.z; // compute new density float newDensity = _density; @@ -1074,23 +1077,23 @@ void EntityItem::updateMass(float mass) { } void EntityItem::updateVelocityInDomainUnits(const glm::vec3& value) { - if (glm::distance(_velocity, value) * (float)TREE_SCALE > MIN_VELOCITY_DELTA) { - if (glm::length(value) * (float)TREE_SCALE < MIN_VELOCITY_DELTA) { + glm::vec3 velocity = value * (float)TREE_SCALE; + if (glm::distance(_velocity, velocity) > MIN_VELOCITY_DELTA) { + if (glm::length(velocity) < MIN_VELOCITY_DELTA) { _velocity = ENTITY_ITEM_ZERO_VEC3; } else { - _velocity = value; + _velocity = velocity; } _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } void EntityItem::updateVelocityInMeters(const glm::vec3& value) { - glm::vec3 velocity = value / (float) TREE_SCALE; - if (glm::distance(_velocity, velocity) * (float)TREE_SCALE > MIN_VELOCITY_DELTA) { + if (glm::distance(_velocity, value) > MIN_VELOCITY_DELTA) { if (glm::length(value) < MIN_VELOCITY_DELTA) { _velocity = ENTITY_ITEM_ZERO_VEC3; } else { - _velocity = velocity; + _velocity = value; } _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } @@ -1104,16 +1107,16 @@ void EntityItem::updateDamping(float value) { } void EntityItem::updateGravityInDomainUnits(const glm::vec3& value) { - if (glm::distance(_gravity, value) * (float)TREE_SCALE > MIN_GRAVITY_DELTA) { - _gravity = value; + glm::vec3 gravity = value * (float) TREE_SCALE; + if (glm::distance(_gravity, gravity) > MIN_GRAVITY_DELTA) { + _gravity = gravity; _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } void EntityItem::updateGravityInMeters(const glm::vec3& value) { - glm::vec3 gravity = value / (float) TREE_SCALE; - if ( glm::distance(_gravity, gravity) * (float)TREE_SCALE > MIN_GRAVITY_DELTA) { - _gravity = gravity; + if ( glm::distance(_gravity, value) > MIN_GRAVITY_DELTA) { + _gravity = value; _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 662bde216a..ad20ca66e4 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -37,7 +37,7 @@ class EntityTreeElementExtraEncodeData; #define debugTime(T, N) qPrintable(QString("%1 [ %2 ago]").arg(T, 16, 10).arg(formatUsecTime(N - T), 15)) #define debugTimeOnly(T) qPrintable(QString("%1").arg(T, 16, 10)) -#define debugTreeVector(V) V << "[" << (V * (float)TREE_SCALE) << " in meters ]" +#define debugTreeVector(V) V << "[" << V << " in meters ]" /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available @@ -145,26 +145,26 @@ public: // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } - const glm::vec3& getPositionInDomainUnits() const { return _position; } /// get position in domain scale units (0.0 - 1.0) - glm::vec3 getPositionInMeters() const { return _position * (float) TREE_SCALE; } /// get position in meters + glm::vec3 getPositionInDomainUnits() const { return _position / (float)TREE_SCALE; } /// get position in domain scale units (0.0 - 1.0) + const glm::vec3& getPositionInMeters() const { return _position; } /// get position in meters /// set position in domain scale units (0.0 - 1.0) - void setPositionInDomainUnits(const glm::vec3& value) { _position = value; } - void setPositionInMeters(const glm::vec3& value) /// set position in meter units (0.0 - TREE_SCALE) - { setPositionInDomainUnits(glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f)); } + void setPositionInDomainUnits(const glm::vec3& value) + { setPositionInMeters(glm::clamp(value, 0.0f, 1.0f) * (float)TREE_SCALE); } + void setPositionInMeters(const glm::vec3& value) { _position = value; } - glm::vec3 getCenterInDomainUnits() const; /// calculates center of the entity in domain scale units (0.0 - 1.0) - glm::vec3 getCenterInMeters() const { return getCenterInDomainUnits() * (float) TREE_SCALE; } + glm::vec3 getCenterInDomainUnits() const { return getCenterInMeters() / (float) TREE_SCALE; } + glm::vec3 getCenterInMeters() const; - const glm::vec3& getDimensionsInDomainUnits() const { return _dimensions; } /// get dimensions in domain scale units (0.0 - 1.0) - glm::vec3 getDimensionsInMeters() const { return _dimensions * (float) TREE_SCALE; } /// get dimensions in meters + glm::vec3 getDimensionsInDomainUnits() const { return _dimensions / (float)TREE_SCALE; } /// get dimensions in domain scale units (0.0 - 1.0) + const glm::vec3& getDimensionsInMeters() const { return _dimensions; } /// get dimensions in meters float getLargestDimensionInDomainUnits() const { return glm::length(_dimensions); } /// get the largest possible dimension - /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensionsInDomainUnits(const glm::vec3& value) { _dimensions = value; } + /// set dimensions in domain scale units (0.0 - 1.0) + virtual void setDimensionsInDomainUnits(const glm::vec3& value) { _dimensions = glm::abs(value) * (float)TREE_SCALE; } - /// set dimensions in meter units (0.0 - TREE_SCALE) this will also reset radius appropriately - void setDimensionsInMeters(const glm::vec3& value) { setDimensionsInDomainUnits(value / (float) TREE_SCALE); } + /// set dimensions in meter units (0.0 - TREE_SCALE) + virtual void setDimensionsInMeters(const glm::vec3& value) { _dimensions = glm::abs(value); } const glm::quat& getRotation() const { return _rotation; } void setRotation(const glm::quat& rotation) { _rotation = rotation; } @@ -181,16 +181,16 @@ public: float getDensity() const { return _density; } - const glm::vec3& getVelocityInDomainUnits() const { return _velocity; } /// velocity in domain scale units (0.0-1.0) per second - glm::vec3 getVelocityInMeters() const { return _velocity * (float) TREE_SCALE; } /// get velocity in meters - void setVelocityInDomainUnits(const glm::vec3& value) { _velocity = value; } /// velocity in domain scale units (0.0-1.0) per second - void setVelocityInMeters(const glm::vec3& value) { _velocity = value / (float) TREE_SCALE; } /// velocity in meters + glm::vec3 getVelocityInDomainUnits() const { return _velocity / (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second + const glm::vec3 getVelocityInMeters() const { return _velocity; } /// get velocity in meters + void setVelocityInDomainUnits(const glm::vec3& value) { _velocity = value * (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second + void setVelocityInMeters(const glm::vec3& value) { _velocity = value; } /// velocity in meters bool hasVelocity() const { return _velocity != ENTITY_ITEM_ZERO_VEC3; } - const glm::vec3& getGravityInDomainUnits() const { return _gravity; } /// gravity in domain scale units (0.0-1.0) per second squared - glm::vec3 getGravityInMeters() const { return _gravity * (float) TREE_SCALE; } /// get gravity in meters - void setGravityInDomainUnits(const glm::vec3& value) { _gravity = value; } /// gravity in domain scale units (0.0-1.0) per second squared - void setGravityInMeters(const glm::vec3& value) { _gravity = value / (float) TREE_SCALE; } /// gravity in meters + glm::vec3 getGravityInDomainUnits() const { return _gravity / (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared + const glm::vec3& getGravityInMeters() const { return _gravity; } /// get gravity in meters + void setGravityInDomainUnits(const glm::vec3& value) { _gravity = value * (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared + void setGravityInMeters(const glm::vec3& value) { _gravity = value; } /// gravity in meters bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } float getDamping() const { return _damping; } @@ -215,7 +215,7 @@ public: AACube getMaximumAACube() const; AACube getMinimumAACube() const; AABox getAABoxInMeters() const; /// axis aligned bounding box in world-frame (meters) - AABox getAABox() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0) + AABox getAABoxInDomainUnits() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0) const QString& getScript() const { return _script; } void setScript(const QString& value) { _script = value; } @@ -254,7 +254,7 @@ public: float getRadiusInMeters() const; virtual bool containsInMeters(const glm::vec3& point) const { return getAABoxInMeters().contains(point); } - virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } + virtual bool containsInDomainUnits(const glm::vec3& point) const { return getAABoxInDomainUnits().contains(point); } virtual void computeShapeInfo(ShapeInfo& info) const; /// return preferred shape type (actual physical shape may differ) @@ -319,11 +319,10 @@ protected: float _glowLevel; float _localRenderAlpha; float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3 - // NOTE: _volumeMultiplier is used to compute volume: - // volume = _volumeMultiplier * _dimensions.x * _dimensions.y * _dimensions.z = m^3 - // DANGER: due to the size of TREE_SCALE the _volumeMultiplier is always a large number, and therefore - // will tend to introduce floating point error. We must keep this in mind when using it. - float _volumeMultiplier = (float)TREE_SCALE * (float)TREE_SCALE * (float)TREE_SCALE; + // NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class + // rather than in all of the derived classes. If we ever collapse these classes to one we could do it a + // different way. + float _volumeMultiplier = 1.0f; glm::vec3 _velocity; glm::vec3 _gravity; float _damping; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 75788c979f..e21a2573a2 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -32,9 +32,6 @@ SphereEntityItem::SphereEntityItem(const EntityItemID& entityItemID, const Entit { _type = EntityTypes::Sphere; setProperties(properties); - // NOTE: _volumeMultiplier is used to compute volume: - // volume = _volumeMultiplier * _dimensions.x * _dimensions.y * _dimensions.z - // The formula below looks funny because _dimension.xyz = diameter rather than radius. _volumeMultiplier *= PI / 6.0f; } diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index a716bba0e2..d008bceccc 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -40,10 +40,16 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityIte setProperties(properties); } +const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f; + +void TextEntityItem::setDimensionsInMeters(const glm::vec3& value) { + // NOTE: Text Entities always have a "depth" of 1cm. + _dimensions = glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH); +} + void TextEntityItem::setDimensionsInDomainUnits(const glm::vec3& value) { // NOTE: Text Entities always have a "depth" of 1cm. - float fixedDepth = 0.01f / (float)TREE_SCALE; - _dimensions = glm::vec3(value.x, value.y, fixedDepth); + _dimensions = glm::vec3(value.x * (float)TREE_SCALE, value.y * (float)TREE_SCALE, TEXT_ENTITY_ITEM_FIXED_DEPTH); } EntityItemProperties TextEntityItem::getProperties() const { diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 60f82f4936..1ee9c2c194 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -23,6 +23,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately + virtual void setDimensionsInMeters(const glm::vec3& value); virtual void setDimensionsInDomainUnits(const glm::vec3& value); virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } From aede107058409ae5edcc1d0265d0c3c70112a7af Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 4 Mar 2015 09:41:07 -0800 Subject: [PATCH 15/56] change version of Entity update packet --- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + libraries/octree/src/Octree.cpp | 52 ---------------------- libraries/octree/src/Octree.h | 3 -- 4 files changed, 2 insertions(+), 56 deletions(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 2eee540fff..489017788a 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; + return VERSION_ENTITIES_USE_METERS; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index e593955b51..42f28e5e97 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -128,6 +128,7 @@ const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5; const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6; const PacketVersion VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME = 7; const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE = 8; +const PacketVersion VERSION_ENTITIES_USE_METERS = 9; const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index a1df449135..2661d85930 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -2083,58 +2083,6 @@ bool Octree::countOctreeElementsOperation(OctreeElement* element, void* extraDat return true; // keep going } -void Octree::copySubTreeIntoNewTree(OctreeElement* startElement, Octree* destinationTree, bool rebaseToRoot) { - OctreeElementBag elementBag; - elementBag.insert(startElement); - int chopLevels = 0; - if (rebaseToRoot) { - chopLevels = numberOfThreeBitSectionsInCode(startElement->getOctalCode()); - } - - EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS, chopLevels); - OctreeElementExtraEncodeData extraEncodeData; - params.extraEncodeData = &extraEncodeData; - - OctreePacketData packetData; - - while (!elementBag.isEmpty()) { - OctreeElement* subTree = elementBag.extract(); - packetData.reset(); // reset the packet between usage - // ask our tree to write a bitsteam - encodeTreeBitstream(subTree, &packetData, elementBag, params); - // ask destination tree to read the bitstream - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); - destinationTree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); - } -} - -void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinationElement) { - OctreeElementBag elementBag; - // If we were given a specific element, start from there, otherwise start from root - elementBag.insert(sourceTree->_rootElement); - - OctreePacketData packetData; - - EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); - OctreeElementExtraEncodeData extraEncodeData; - params.extraEncodeData = &extraEncodeData; - - while (!elementBag.isEmpty()) { - OctreeElement* subTree = elementBag.extract(); - - packetData.reset(); // reset between usage - - // ask our tree to write a bitsteam - sourceTree->encodeTreeBitstream(subTree, &packetData, elementBag, params); - - // ask destination tree to read the bitstream - bool wantImportProgress = true; - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationElement, - 0, SharedNodePointer(), wantImportProgress); - readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); - } -} - void Octree::cancelImport() { _stopImport = true; } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 870e18983e..8774ebe55b 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -323,9 +323,6 @@ public: unsigned long getOctreeElementsCount(); - void copySubTreeIntoNewTree(OctreeElement* startElement, Octree* destinationTree, bool rebaseToRoot); - void copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinationElement); - bool getShouldReaverage() const { return _shouldReaverage; } void recurseElementWithOperation(OctreeElement* element, RecurseOctreeOperation operation, From c88f236d1c212f0856f4b393c344240ada0fc0b4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 4 Mar 2015 09:41:23 -0800 Subject: [PATCH 16/56] get version from packet --- libraries/octree/src/OctreeRenderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 5bcf49a1a4..187f916d35 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -65,7 +65,8 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar unsigned int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); QUuid sourceUUID = uuidFromPacketHeader(dataByteArray); PacketType expectedType = getExpectedPacketType(); - PacketVersion expectedVersion = _tree->expectedVersion(); // TODO: would be better to read this from the packet! + // packetVersion is the second byte + PacketVersion packetVersion = dataByteArray[1]; if(command == expectedType) { PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram expected PacketType", showTimingDetails); @@ -117,7 +118,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar if (sectionLength) { // ask the VoxelTree to read the bitstream into the tree ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, - sourceUUID, sourceNode, false, expectedVersion); + sourceUUID, sourceNode, false, packetVersion); _tree->lockForWrite(); OctreePacketData packetData(packetIsCompressed); packetData.loadFinalizedContent(dataAt, sectionLength); From ca1c9b410511d3e78a31b32e5847fd778d08ff29 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 4 Mar 2015 16:05:29 -0800 Subject: [PATCH 17/56] EntityItem::findEntities() uses meters --- interface/src/Application.cpp | 3 +-- libraries/entities/src/EntityTree.cpp | 3 ++- libraries/entities/src/EntityTree.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d3161ebf51..5e95e7243a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1642,8 +1642,7 @@ void Application::setActiveFaceTracker() { bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { QVector<EntityItem*> entities; - _entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE, - y / (float)TREE_SCALE, z / (float)TREE_SCALE), scale / (float)TREE_SCALE), entities); + _entities.getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities); if (entities.size() > 0) { glm::vec3 root(x, y, z); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index aef5b1d2bf..619ff94048 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -515,7 +515,8 @@ public: bool EntityTree::findInCubeOperation(OctreeElement* element, void* extraData) { FindEntitiesInCubeArgs* args = static_cast<FindEntitiesInCubeArgs*>(extraData); - const AACube& elementCube = element->getAACube(); + AACube elementCube = element->getAACube(); + elementCube *= (float)TREE_SCALE; if (elementCube.touches(args->_cube)) { EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element); entityTreeElement->getEntities(args->_cube, args->_foundEntities); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index e748df2548..852d07d20f 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -112,7 +112,7 @@ public: void findEntitiesInMeters(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities); /// finds all entities that touch a cube - /// \param cube the query cube + /// \param cube the query cube in world-frame (meters) /// \param foundEntities[out] vector of non-const EntityItem* /// \remark Side effect: any initial contents in entities will be lost void findEntities(const AACube& cube, QVector<EntityItem*>& foundEntities); From 3522357c8c10fba5866aaecec408b7db61cda230 Mon Sep 17 00:00:00 2001 From: Jason <2billbrasky@gmail.com> Date: Wed, 4 Mar 2015 16:06:06 -0800 Subject: [PATCH 18/56] High Fidelity interview project -- Jason Rickwald For my project, I decided to add a new entity -- a Particle Effect. This is really rudimentary to start out with, but you could see where it's headed. --- .../src/EntityTreeRenderer.cpp | 2 + .../RenderableParticleEffectEntityItem.cpp | 88 +++ .../src/RenderableParticleEffectEntityItem.h | 29 + .../entities/src/EntityItemProperties.cpp | 57 ++ libraries/entities/src/EntityItemProperties.h | 26 +- libraries/entities/src/EntityTypes.cpp | 2 + libraries/entities/src/EntityTypes.h | 3 +- .../entities/src/ParticleEffectEntityItem.cpp | 522 ++++++++++++++++++ .../entities/src/ParticleEffectEntityItem.h | 181 ++++++ 9 files changed, 908 insertions(+), 2 deletions(-) create mode 100644 libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp create mode 100644 libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h create mode 100644 libraries/entities/src/ParticleEffectEntityItem.cpp create mode 100644 libraries/entities/src/ParticleEffectEntityItem.h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 46f9ff6f55..3db4ffb2ac 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -32,6 +32,7 @@ #include "RenderableModelEntityItem.h" #include "RenderableSphereEntityItem.h" #include "RenderableTextEntityItem.h" +#include "RenderableParticleEffectEntityItem.h" EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, @@ -53,6 +54,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory) + REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory) _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp new file mode 100644 index 0000000000..a10f59287c --- /dev/null +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -0,0 +1,88 @@ +// +// RenderableParticleEffectEntityItem.cpp +// interface/src +// +// Created by Jason Rickwald on 3/2/15. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include <glm/gtx/quaternion.hpp> + +#include <gpu/GPUConfig.h> + +#include <DependencyManager.h> +#include <DeferredLightingEffect.h> +#include <PerfStat.h> + +#include "RenderableParticleEffectEntityItem.h" + +EntityItem* RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + return new RenderableParticleEffectEntityItem(entityID, properties); +} + +void RenderableParticleEffectEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderableParticleEffectEntityItem::render"); + assert(getType() == EntityTypes::ParticleEffect); + glm::vec3 position = getPositionInMeters(); + glm::vec3 center = getCenterInMeters(); + glm::quat rotation = getRotation(); + float pa_rad = getParticleRadius(); + + const float MAX_COLOR = 255.0f; + glm::vec4 sphereColor(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, + getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); + + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + + const int SLICES = 8; + const int STACKS = 5; + + glBegin(GL_QUADS); + glColor4f(sphereColor.r, sphereColor.g, sphereColor.b, sphereColor.a); + + // Right now we're just iterating over particles and rendering as a cross of four quads. + // This is pretty dumb, it was quick enough to code up. Really, there should be many + // rendering modes, including the all-important textured billboards. + + quint32 paiter = pa_head; + while (pa_life[paiter] > 0.0f) + { + int j = paiter * 3; + + glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); + glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); + glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); + glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); + + glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); + glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); + glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); + glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); + + glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] - pa_rad); + glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] + pa_rad); + glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] + pa_rad); + glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] - pa_rad); + + glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] + pa_rad); + glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] - pa_rad); + glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] - pa_rad); + glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] + pa_rad); + + paiter = (paiter + 1) % _maxParticles; + } + + glEnd(); + glPopMatrix(); + glPopMatrix(); +}; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h new file mode 100644 index 0000000000..837c878a45 --- /dev/null +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -0,0 +1,29 @@ +// +// RenderableParticleEffectEntityItem.h +// interface/src/entities +// +// Created by Jason Rickwald on 3/2/15. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderableParticleEffectEntityItem_h +#define hifi_RenderableParticleEffectEntityItem_h + +#include <ParticleEffectEntityItem.h> + +class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + ParticleEffectEntityItem(entityItemID, properties) + { } + + virtual void render(RenderArgs* args); + +}; + + +#endif // hifi_RenderableParticleEffectEntityItem_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f3f84876ba..87b59b0392 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -23,6 +23,7 @@ #include "EntityItemPropertiesDefaults.h" #include "ModelEntityItem.h" #include "TextEntityItem.h" +#include "ParticleEffectEntityItem.h" EntityItemProperties::EntityItemProperties() : @@ -66,6 +67,13 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR), CONSTRUCT_PROPERTY(backgroundColor, TextEntityItem::DEFAULT_BACKGROUND_COLOR), CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE), + CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES), + CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), + CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), + CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), + CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), + CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), + CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -238,6 +246,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_TEXT_COLOR, textColor); CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_COLOR, backgroundColor); CHECK_PROPERTY_CHANGE(PROP_SHAPE_TYPE, shapeType); + CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); + CHECK_PROPERTY_CHANGE(PROP_LIFESPAN, lifespan); + CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); + CHECK_PROPERTY_CHANGE(PROP_EMIT_DIRECTION, emitDirection); + CHECK_PROPERTY_CHANGE(PROP_EMIT_STRENGTH, emitStrength); + CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); + CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); return changedProperties; } @@ -297,6 +312,13 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeAsString()); + COPY_PROPERTY_TO_QSCRIPTVALUE(maxParticles); + COPY_PROPERTY_TO_QSCRIPTVALUE(lifespan); + COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate); + COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(emitDirection); + COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength); + COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); + COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); @@ -375,6 +397,13 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor); COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(maxParticles, setMaxParticles); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lifespan, setLifespan); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitRate, setEmitRate); + COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(emitDirection, setEmitDirection); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitStrength, setEmitStrength); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localGravity, setLocalGravity); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius); _lastEdited = usecTimestampNow(); } @@ -552,6 +581,16 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, properties.getExponent()); APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, properties.getCutoff()); } + + if (properties.getType() == EntityTypes::ParticleEffect) { + APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, properties.getMaxParticles()); + APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, properties.getLifespan()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, properties.getEmitRate()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, properties.getEmitDirection()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, properties.getEmitStrength()); + APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, properties.getLocalGravity()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, properties.getParticleRadius()); + } } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); @@ -774,6 +813,16 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff); } + + if (properties.getType() == EntityTypes::ParticleEffect) { + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_STRENGTH, float, setEmitStrength); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); + } return valid; } @@ -851,6 +900,14 @@ void EntityItemProperties::markAllChanged() { _textColorChanged = true; _backgroundColorChanged = true; _shapeTypeChanged = true; + + _maxParticlesChanged = true; + _lifespanChanged = true; + _emitRateChanged = true; + _emitDirectionChanged = true; + _emitStrengthChanged = true; + _localGravityChanged = true; + _particleRadiusChanged = true; } AACube EntityItemProperties::getMaximumAACubeInTreeUnits() const { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 2391bcde84..d5a3c32809 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -83,9 +83,18 @@ enum EntityPropertyList { PROP_ANIMATION_SETTINGS, PROP_USER_DATA, PROP_SHAPE_TYPE, + + // used by ParticleEffect entities + PROP_MAX_PARTICLES, + PROP_LIFESPAN, + PROP_EMIT_RATE, + PROP_EMIT_DIRECTION, + PROP_EMIT_STRENGTH, + PROP_LOCAL_GRAVITY, + PROP_PARTICLE_RADIUS, // NOTE: add new properties ABOVE this line and then modify PROP_LAST_ITEM below - PROP_LAST_ITEM = PROP_SHAPE_TYPE, + PROP_LAST_ITEM = PROP_PARTICLE_RADIUS, // These properties of TextEntity piggy back off of properties of ModelEntities, the type doesn't matter // since the derived class knows how to interpret it's own properties and knows the types it expects @@ -110,6 +119,7 @@ class EntityItemProperties { friend class SphereEntityItem; // TODO: consider removing this friend relationship and use public methods friend class LightEntityItem; // TODO: consider removing this friend relationship and use public methods friend class TextEntityItem; // TODO: consider removing this friend relationship and use public methods + friend class ParticleEffectEntityItem; // TODO: consider removing this friend relationship and use public methods public: EntityItemProperties(); virtual ~EntityItemProperties(); @@ -182,6 +192,13 @@ public: DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); + DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); + DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); + DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); + DEFINE_PROPERTY_REF(PROP_EMIT_DIRECTION, EmitDirection, emitDirection, glm::vec3); + DEFINE_PROPERTY(PROP_EMIT_STRENGTH, EmitStrength, emitStrength, float); + DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); + DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); public: float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } @@ -304,6 +321,13 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, TextColor, textColor, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundColor, backgroundColor, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ShapeType, shapeType, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, MaxParticles, maxParticles, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitDirection, emitDirection, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); debug << " last edited:" << properties.getLastEdited() << "\n"; debug << " edited ago:" << properties.getEditedAgo() << "\n"; diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index fd9484e0d6..d3ffc4247c 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -23,6 +23,7 @@ #include "ModelEntityItem.h" #include "SphereEntityItem.h" #include "TextEntityItem.h" +#include "ParticleEffectEntityItem.h" QMap<EntityTypes::EntityType, QString> EntityTypes::_typeToNameMap; QMap<QString, EntityTypes::EntityType> EntityTypes::_nameToTypeMap; @@ -37,6 +38,7 @@ REGISTER_ENTITY_TYPE(Box) REGISTER_ENTITY_TYPE(Sphere) REGISTER_ENTITY_TYPE(Light) REGISTER_ENTITY_TYPE(Text) +REGISTER_ENTITY_TYPE(ParticleEffect) const QString& EntityTypes::getEntityTypeName(EntityType entityType) { diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 8ed407f11d..e1f8e876bb 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -35,7 +35,8 @@ public: Sphere, Light, Text, - LAST = Text + ParticleEffect, + LAST = ParticleEffect } EntityType; static const QString& getEntityTypeName(EntityType entityType); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp new file mode 100644 index 0000000000..cf84f7be75 --- /dev/null +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -0,0 +1,522 @@ +// +// ParticleEffectEntityItem.cpp +// libraries/entities/src +// +// Some starter code for a particle simulation entity, which could ideally be used for a variety of effects. +// This is some really early and rough stuff here. It was enough for now to just get it up and running in the interface. +// +// Todo's and other notes: +// - The simulation should restart when the AnimationLoop's max frame is reached (or passed), but there doesn't seem +// to be a good way to set that max frame to something reasonable right now. +// - There seems to be a bug whereby entities on the edge of screen will just pop off or on. This is probably due +// to my lack of understanding of how entities in the octree are picked for rendering. I am updating the entity +// dimensions based on the bounds of the sim, but maybe I need to update a dirty flag or something. +// - This should support some kind of pre-roll of the simulation. +// - Just to get this out the door, I just did forward Euler integration. There are better ways. +// - Gravity always points along the Y axis. Support an actual gravity vector. +// - Add the ability to add arbitrary forces to the simulation. +// - Add controls for spread (which is currently hard-coded) and varying emission strength (not currently implemented). +// - Add drag. +// - Add some kind of support for collisions. +// - For simplicity, I'm currently just rendering each particle as a cross of four axis-aligned quads. Really, we'd +// want multiple render modes, including (the most important) textured billboards (always facing camera). Also, these +// should support animated textures. +// - There's no synchronization of the simulation across clients at all. In fact, it's using rand() under the hood, so +// there's no gaurantee that different clients will see simulations that look anything like the other. +// - MORE? +// +// Created by Jason Rickwald on 3/2/15. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#include <glm/gtx/transform.hpp> +#include <QtCore/QJsonDocument> + +#include <QDebug> + +#include <ByteCountCoding.h> +#include <GeometryUtil.h> + +#include "EntityTree.h" +#include "EntityTreeElement.h" +#include "ParticleEffectEntityItem.h" + +const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f; +const bool ParticleEffectEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false; +const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; +const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; +const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; +const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION(0.0f, 1.0f, 0.0f); +const float ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH = 25.0f; +const float ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY = -9.8f; +const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; + + +EntityItem* ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + return new ParticleEffectEntityItem(entityID, properties); +} + +// our non-pure virtual subclass for now... +ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : +EntityItem(entityItemID, properties) +{ + _type = EntityTypes::ParticleEffect; + _maxParticles = DEFAULT_MAX_PARTICLES; + _lifespan = DEFAULT_LIFESPAN; + _emitRate = DEFAULT_EMIT_RATE; + _emitDirection = DEFAULT_EMIT_DIRECTION; + _emitStrength = DEFAULT_EMIT_STRENGTH; + _localGravity = DEFAULT_LOCAL_GRAVITY; + _particleRadius = DEFAULT_PARTICLE_RADIUS; + setProperties(properties); + // this is a pretty dumb thing to do, and it should probably be changed to use a more dynamic + // data structure in the future. I'm just trying to get some code out the door for now (and it's + // at least time efficient (though not space efficient). + // Also, this being a real-time application, it's doubtful we'll ever have millions of particles + // to keep track of, so this really isn't all that bad. + pa_life = (float*) malloc(sizeof(float) * _maxParticles); + pa_position = (float*)malloc(sizeof(float) * _maxParticles * 3); // x,y,z + pa_velocity = (float*)malloc(sizeof(float) * _maxParticles * 3); // x,y,z + pa_xmax = pa_ymax = pa_zmax = 1.0f; + pa_xmin = pa_ymin = pa_zmin = -1.0f; + resetSim(); + _lastAnimated = usecTimestampNow(); +} + +ParticleEffectEntityItem::~ParticleEffectEntityItem() +{ + free(pa_life); + free(pa_position); + free(pa_velocity); +} + +EntityItemProperties ParticleEffectEntityItem::getProperties() const { + EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class + + COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFPS, getAnimationFPS); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitDirection, getEmitDirection); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitStrength, getEmitStrength); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius); + + return properties; +} + +bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + + SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitDirection, setEmitDirection); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitStrength, setEmitStrength); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); + + if (somethingChanged) { + bool wantDebug = false; + if (wantDebug) { + uint64_t now = usecTimestampNow(); + int elapsed = now - getLastEdited(); + qDebug() << "ParticleEffectEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << + "now=" << now << " getLastEdited()=" << getLastEdited(); + } + setLastEdited(properties.getLastEdited()); + } + return somethingChanged; +} + +int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { + + int bytesRead = 0; + const unsigned char* dataAt = data; + + READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color); + + // Because we're using AnimationLoop which will reset the frame index if you change it's running state + // we want to read these values in the order they appear in the buffer, but call our setters in an + // order that allows AnimationLoop to preserve the correct frame rate. + float animationFPS = getAnimationFPS(); + float animationFrameIndex = getAnimationFrameIndex(); + bool animationIsPlaying = getAnimationIsPlaying(); + READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, animationFPS); + READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, animationFrameIndex); + READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying); + + if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) { + if (animationIsPlaying != getAnimationIsPlaying()) { + setAnimationIsPlaying(animationIsPlaying); + } + } + if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) { + setAnimationFPS(animationFPS); + } + if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) { + setAnimationFrameIndex(animationFrameIndex); + } + + READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings); + READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType); + READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, _maxParticles); + READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, _lifespan); + READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, _emitRate); + READ_ENTITY_PROPERTY_SETTER(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); + READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, _emitStrength); + READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, _localGravity); + READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, _particleRadius); + + return bytesRead; +} + + +// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + + requestedProperties += PROP_COLOR; + requestedProperties += PROP_ANIMATION_FPS; + requestedProperties += PROP_ANIMATION_FRAME_INDEX; + requestedProperties += PROP_ANIMATION_PLAYING; + requestedProperties += PROP_ANIMATION_SETTINGS; + requestedProperties += PROP_SHAPE_TYPE; + requestedProperties += PROP_MAX_PARTICLES; + requestedProperties += PROP_LIFESPAN; + requestedProperties += PROP_EMIT_RATE; + requestedProperties += PROP_EMIT_DIRECTION; + requestedProperties += PROP_EMIT_STRENGTH; + requestedProperties += PROP_LOCAL_GRAVITY; + requestedProperties += PROP_PARTICLE_RADIUS; + + return requestedProperties; +} + +void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings()); + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType()); + APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, getMaxParticles()); + APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, getLifespan()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, getEmitRate()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, getEmitDirection()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, getEmitStrength()); + APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, getLocalGravity()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius()); +} + +bool ParticleEffectEntityItem::isAnimatingSomething() const { + return getAnimationIsPlaying() && + getAnimationFPS() != 0.0f; +} + +bool ParticleEffectEntityItem::needsToCallUpdate() const { + return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate(); +} + +void ParticleEffectEntityItem::update(const quint64& now) { + // only advance the frame index if we're playing + if (getAnimationIsPlaying()) { + float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; + _lastAnimated = now; + float lastFrame = _animationLoop.getFrameIndex(); + _animationLoop.simulate(deltaTime); + float curFrame = _animationLoop.getFrameIndex(); + if (curFrame > lastFrame) + { + stepSim(deltaTime); + } + else if (curFrame < lastFrame) + { + // we looped around, so restart the sim and only sim up to the point + // since the beginning of the frame range. + resetSim(); + stepSim((curFrame - _animationLoop.getFirstFrame()) / _animationLoop.getFPS()); + } + } + else { + _lastAnimated = now; + } + + // update the dimensions + glm::vec3 dims; + dims.x = glm::max(glm::abs(pa_xmin), glm::abs(pa_xmax)); + dims.y = glm::max(glm::abs(pa_xmin), glm::abs(pa_xmax)); + dims.z = glm::max(glm::abs(pa_xmin), glm::abs(pa_xmax)); + setDimensionsInMeters(dims); + + EntityItem::update(now); // let our base class handle it's updates... +} + +void ParticleEffectEntityItem::debugDump() const { + quint64 now = usecTimestampNow(); + qDebug() << "PA EFFECT EntityItem id:" << getEntityItemID() << "---------------------------------------------"; + qDebug() << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; + qDebug() << " position:" << debugTreeVector(_position); + qDebug() << " dimensions:" << debugTreeVector(_dimensions); + qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now); +} + +void ParticleEffectEntityItem::updateShapeType(ShapeType type) { + if (type != _shapeType) { + _shapeType = type; + _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; + } +} + +void ParticleEffectEntityItem::setAnimationFrameIndex(float value) { +#ifdef WANT_DEBUG + if (isAnimatingSomething()) { + qDebug() << "ParticleEffectEntityItem::setAnimationFrameIndex()"; + qDebug() << " value:" << value; + qDebug() << " was:" << _animationLoop.getFrameIndex(); + } +#endif + _animationLoop.setFrameIndex(value); +} + +void ParticleEffectEntityItem::setAnimationSettings(const QString& value) { + // the animations setting is a JSON string that may contain various animation settings. + // if it includes fps, frameIndex, or running, those values will be parsed out and + // will over ride the regular animation settings + + QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); + QJsonObject settingsAsJsonObject = settingsAsJson.object(); + QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); + if (settingsMap.contains("fps")) { + float fps = settingsMap["fps"].toFloat(); + setAnimationFPS(fps); + } + + if (settingsMap.contains("frameIndex")) { + float frameIndex = settingsMap["frameIndex"].toFloat(); +#ifdef WANT_DEBUG + if (isAnimatingSomething()) { + qDebug() << "ParticleEffectEntityItem::setAnimationSettings() calling setAnimationFrameIndex()..."; + qDebug() << " settings:" << value; + qDebug() << " settingsMap[frameIndex]:" << settingsMap["frameIndex"]; + qDebug(" frameIndex: %20.5f", frameIndex); + } +#endif + + setAnimationFrameIndex(frameIndex); + } + + if (settingsMap.contains("running")) { + bool running = settingsMap["running"].toBool(); + if (running != getAnimationIsPlaying()) { + setAnimationIsPlaying(running); + } + } + + if (settingsMap.contains("firstFrame")) { + float firstFrame = settingsMap["firstFrame"].toFloat(); + setAnimationFirstFrame(firstFrame); + } + + if (settingsMap.contains("lastFrame")) { + float lastFrame = settingsMap["lastFrame"].toFloat(); + setAnimationLastFrame(lastFrame); + } + + if (settingsMap.contains("loop")) { + bool loop = settingsMap["loop"].toBool(); + setAnimationLoop(loop); + } + + if (settingsMap.contains("hold")) { + bool hold = settingsMap["hold"].toBool(); + setAnimationHold(hold); + } + + if (settingsMap.contains("startAutomatically")) { + bool startAutomatically = settingsMap["startAutomatically"].toBool(); + setAnimationStartAutomatically(startAutomatically); + } + + _animationSettings = value; + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; +} + +void ParticleEffectEntityItem::setAnimationIsPlaying(bool value) { + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationLoop.setRunning(value); +} + +void ParticleEffectEntityItem::setAnimationFPS(float value) { + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationLoop.setFPS(value); +} + +QString ParticleEffectEntityItem::getAnimationSettings() const { + // the animations setting is a JSON string that may contain various animation settings. + // if it includes fps, frameIndex, or running, those values will be parsed out and + // will over ride the regular animation settings + QString value = _animationSettings; + + QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); + QJsonObject settingsAsJsonObject = settingsAsJson.object(); + QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); + + QVariant fpsValue(getAnimationFPS()); + settingsMap["fps"] = fpsValue; + + QVariant frameIndexValue(getAnimationFrameIndex()); + settingsMap["frameIndex"] = frameIndexValue; + + QVariant runningValue(getAnimationIsPlaying()); + settingsMap["running"] = runningValue; + + QVariant firstFrameValue(getAnimationFirstFrame()); + settingsMap["firstFrame"] = firstFrameValue; + + QVariant lastFrameValue(getAnimationLastFrame()); + settingsMap["lastFrame"] = lastFrameValue; + + QVariant loopValue(getAnimationLoop()); + settingsMap["loop"] = loopValue; + + QVariant holdValue(getAnimationHold()); + settingsMap["hold"] = holdValue; + + QVariant startAutomaticallyValue(getAnimationStartAutomatically()); + settingsMap["startAutomatically"] = startAutomaticallyValue; + + settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap); + QJsonDocument newDocument(settingsAsJsonObject); + QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact); + QString jsonByteString(jsonByteArray); + return jsonByteString; +} + +void ParticleEffectEntityItem::stepSim(float deltaTime) +{ + pa_xmin = pa_ymin = pa_zmin = -1.0; + pa_xmax = pa_ymax = pa_zmax = 1.0; + + // update particles + quint32 updateIter = pa_head; + while (pa_life[updateIter] > 0.0f) + { + pa_life[updateIter] -= deltaTime; + if (pa_life[updateIter] <= 0.0f) + { + pa_life[updateIter] = -1.0f; + pa_head = (pa_head + 1) % _maxParticles; + pa_count--; + } + else + { + // DUMB FORWARD EULER just to get it done + int j = updateIter * 3; + pa_position[j] += pa_velocity[j] * deltaTime; + pa_position[j+1] += pa_velocity[j+1] * deltaTime; + pa_position[j+2] += pa_velocity[j+2] * deltaTime; + + pa_xmin = glm::min(pa_xmin, pa_position[j]); + pa_ymin = glm::min(pa_ymin, pa_position[j+1]); + pa_zmin = glm::min(pa_zmin, pa_position[j+2]); + pa_xmax = glm::max(pa_xmax, pa_position[j]); + pa_ymax = glm::max(pa_ymax, pa_position[j + 1]); + pa_zmax = glm::max(pa_zmax, pa_position[j + 2]); + + // massless particles + pa_velocity[j + 1] += deltaTime * _localGravity; + } + updateIter = (updateIter + 1) % _maxParticles; + } + + // emit new particles + quint32 pa_emit_idx = updateIter; + partial_emit += ((float)_emitRate) * deltaTime; + quint32 birthed = (quint32)partial_emit; + partial_emit -= (float)birthed; + glm::vec3 randOffset; + + for (quint32 i = 0; i < birthed; i++) + { + if (pa_life[pa_emit_idx] < 0.0f) + { + int j = pa_emit_idx * 3; + pa_life[pa_emit_idx] = _lifespan; + randOffset.x = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; + randOffset.y = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; + randOffset.z = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; + pa_velocity[j] = (_emitDirection.x * _emitStrength) + randOffset.x; + pa_velocity[j + 1] = (_emitDirection.y * _emitStrength) + randOffset.y; + pa_velocity[j + 2] = (_emitDirection.z * _emitStrength) + randOffset.z; + + // DUMB FORWARD EULER just to get it done + pa_position[j] += pa_velocity[j] * deltaTime; + pa_position[j + 1] += pa_velocity[j + 1] * deltaTime; + pa_position[j + 2] += pa_velocity[j + 2] * deltaTime; + + pa_xmin = glm::min(pa_xmin, pa_position[j]); + pa_ymin = glm::min(pa_ymin, pa_position[j + 1]); + pa_zmin = glm::min(pa_zmin, pa_position[j + 2]); + pa_xmax = glm::max(pa_xmax, pa_position[j]); + pa_ymax = glm::max(pa_ymax, pa_position[j + 1]); + pa_zmax = glm::max(pa_zmax, pa_position[j + 2]); + + // massless particles + pa_velocity[j + 1] += deltaTime * _localGravity; + + pa_emit_idx = (pa_emit_idx + 1) % _maxParticles; + pa_count++; + } + else + break; + } +} + +void ParticleEffectEntityItem::resetSim() +{ + for (int i = 0; i < _maxParticles; i++) + { + int j = i * 3; + pa_life[i] = -1.0f; + pa_position[j] = 0.0f; + pa_position[j+1] = 0.0f; + pa_position[j+2] = 0.0f; + pa_velocity[j] = 0.0f; + pa_velocity[j+1] = 0.0f; + pa_velocity[j+2] = 0.0f; + } + pa_count = 0; + pa_head = 0; + partial_emit = 0.0f; + + srand((unsigned int) this); +} + diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h new file mode 100644 index 0000000000..1306620bc6 --- /dev/null +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -0,0 +1,181 @@ +// +// ParticleEffectEntityItem.h +// libraries/entities/src +// +// Some starter code for a particle simulation entity, which could ideally be used for a variety of effects. +// This is some really early and rough stuff here. It was enough for now to just get it up and running in the interface. +// +// Todo's and other notes: +// - The simulation should restart when the AnimationLoop's max frame is reached (or passed), but there doesn't seem +// to be a good way to set that max frame to something reasonable right now. +// - There seems to be a bug whereby entities on the edge of screen will just pop off or on. This is probably due +// to my lack of understanding of how entities in the octree are picked for rendering. I am updating the entity +// dimensions based on the bounds of the sim, but maybe I need to update a dirty flag or something. +// - This should support some kind of pre-roll of the simulation. +// - Just to get this out the door, I just did forward Euler integration. There are better ways. +// - Gravity always points along the Y axis. Support an actual gravity vector. +// - Add the ability to add arbitrary forces to the simulation. +// - Add controls for spread (which is currently hard-coded) and varying emission strength (not currently implemented). +// - Add drag. +// - Add some kind of support for collisions. +// - For simplicity, I'm currently just rendering each particle as a cross of four axis-aligned quads. Really, we'd +// want multiple render modes, including (the most important) textured billboards (always facing camera). Also, these +// should support animated textures. +// - There's no synchronization of the simulation across clients at all. In fact, it's using rand() under the hood, so +// there's no gaurantee that different clients will see simulations that look anything like the other. +// - MORE? +// +// Created by Jason Rickwald on 3/2/15. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ParticleEffectEntityItem_h +#define hifi_ParticleEffectEntityItem_h + +#include <AnimationLoop.h> +#include "EntityItem.h" + +class ParticleEffectEntityItem : public EntityItem { +public: + + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); + virtual ~ParticleEffectEntityItem(); + + ALLOW_INSTANTIATION // This class can be instantiated + + // methods for getting/setting all properties of this entity + virtual EntityItemProperties getProperties() const; + virtual bool setProperties(const EntityItemProperties& properties); + + virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; + + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const; + + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + + virtual void update(const quint64& now); + virtual bool needsToCallUpdate() const; + + const rgbColor& getColor() const { return _color; } + xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } + + void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } + void setColor(const xColor& value) { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + } + + void updateShapeType(ShapeType type); + virtual ShapeType getShapeType() const { return _shapeType; } + + virtual void debugDump() const; + + static const float DEFAULT_ANIMATION_FRAME_INDEX; + void setAnimationFrameIndex(float value); + void setAnimationSettings(const QString& value); + + static const bool DEFAULT_ANIMATION_IS_PLAYING; + void setAnimationIsPlaying(bool value); + + static const float DEFAULT_ANIMATION_FPS; + void setAnimationFPS(float value); + + void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); } + bool getAnimationLoop() const { return _animationLoop.getLoop(); } + + void setAnimationHold(bool hold) { _animationLoop.setHold(hold); } + bool getAnimationHold() const { return _animationLoop.getHold(); } + + void setAnimationStartAutomatically(bool startAutomatically) { _animationLoop.setStartAutomatically(startAutomatically); } + bool getAnimationStartAutomatically() const { return _animationLoop.getStartAutomatically(); } + + void setAnimationFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); } + float getAnimationFirstFrame() const { return _animationLoop.getFirstFrame(); } + + void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); } + float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } + + static const quint32 DEFAULT_MAX_PARTICLES; + void setMaxParticles(quint32 maxParticles) { _maxParticles = maxParticles; } + quint32 getMaxParticles() const { return _maxParticles; } + + static const float DEFAULT_LIFESPAN; + void setLifespan(float lifespan) { _lifespan = lifespan; } + float getLifespan() const { return _lifespan; } + + static const float DEFAULT_EMIT_RATE; + void setEmitRate(float emitRate) { _emitRate = emitRate; } + float getEmitRate() const { return _emitRate; } + + static const glm::vec3 DEFAULT_EMIT_DIRECTION; + void setEmitDirection(glm::vec3 emitDirection) { _emitDirection = emitDirection; } + const glm::vec3& getEmitDirection() const { return _emitDirection; } + + static const float DEFAULT_EMIT_STRENGTH; + void setEmitStrength(float emitStrength) { _emitStrength = emitStrength; } + float getEmitStrength() const { return _emitStrength; } + + static const float DEFAULT_LOCAL_GRAVITY; + void setLocalGravity(float localGravity) { _localGravity = localGravity; } + float getLocalGravity() const { return _localGravity; } + + static const float DEFAULT_PARTICLE_RADIUS; + void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } + float getParticleRadius() const { return _particleRadius; } + + bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } + float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); } + float getAnimationFPS() const { return _animationLoop.getFPS(); } + QString getAnimationSettings() const; + +protected: + + bool isAnimatingSomething() const; + void stepSim(float deltaTime); + void resetSim(); + + // the properties of this entity + rgbColor _color; + quint32 _maxParticles; + float _lifespan; + float _emitRate; + glm::vec3 _emitDirection; + float _emitStrength; + float _localGravity; + float _particleRadius; + quint64 _lastAnimated; + AnimationLoop _animationLoop; + QString _animationSettings; + ShapeType _shapeType = SHAPE_TYPE_NONE; + + // all the internals of running the particle sim + float* pa_life; + float* pa_position; + float* pa_velocity; + float partial_emit; + quint32 pa_count; + quint32 pa_head; + float pa_xmin; + float pa_xmax; + float pa_ymin; + float pa_ymax; + float pa_zmin; + float pa_zmax; + +}; + +#endif // hifi_ParticleEffectEntityItem_h + From d7d25a6509707df42e998c85fb3acf9c27a47d15 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 4 Mar 2015 16:16:49 -0800 Subject: [PATCH 19/56] Octree::findCapsulePenetration() uses meters --- libraries/entities/src/EntityTree.cpp | 6 +++--- libraries/octree/src/Octree.cpp | 14 +++++--------- libraries/octree/src/OctreeElement.cpp | 4 ++-- libraries/shared/src/AACube.h | 8 -------- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 619ff94048..850523917d 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -425,7 +425,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) glm::vec3 penetration; AACube cube = entityTreeElement->getAACube(); - cube *= (float)TREE_SCALE; + cube.scale((float)TREE_SCALE); bool sphereIntersection = cube.findSpherePenetration(args->position, args->targetRadius, penetration); // If this entityTreeElement contains the point, then search it... @@ -478,7 +478,7 @@ bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData) FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData); glm::vec3 penetration; AACube cube = element->getAACube(); - cube *= (float)TREE_SCALE; + cube.scale((float)TREE_SCALE); bool sphereIntersection = cube.findSpherePenetration(args->position, args->targetRadius, penetration); // If this element contains the point, then search it... @@ -516,7 +516,7 @@ public: bool EntityTree::findInCubeOperation(OctreeElement* element, void* extraData) { FindEntitiesInCubeArgs* args = static_cast<FindEntitiesInCubeArgs*>(extraData); AACube elementCube = element->getAACube(); - elementCube *= (float)TREE_SCALE; + elementCube.scale((float)TREE_SCALE); if (elementCube.touches(args->_cube)) { EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element); entityTreeElement->getEntities(args->_cube, args->_foundEntities); diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 2661d85930..3b43a4a5d2 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -750,7 +750,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { // the details in args is in meters (world-frame) so we have to scale the element cube up AACube box = element->getAACube(); - box *= (float)TREE_SCALE; + box.scale((float)TREE_SCALE); // coarse check against bounds if (!box.expandedContains(args->center, args->radius)) { @@ -837,14 +837,15 @@ bool findCapsulePenetrationOp(OctreeElement* element, void* extraData) { CapsuleArgs* args = static_cast<CapsuleArgs*>(extraData); // coarse check against bounds - const AACube& box = element->getAACube(); + AACube box = element->getAACube(); + box.scale((float)TREE_SCALE); if (!box.expandedIntersectsSegment(args->start, args->end, args->radius)) { return false; } if (element->hasContent()) { glm::vec3 nodePenetration; if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) { - args->penetration = addPenetrations(args->penetration, nodePenetration * (float)(TREE_SCALE)); + args->penetration = addPenetrations(args->penetration, nodePenetration); args->found = true; } } @@ -891,12 +892,7 @@ bool findContentInCubeOp(OctreeElement* element, void* extraData) { bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration, Octree::lockType lockType, bool* accurateResult) { - CapsuleArgs args = { - start / (float)(TREE_SCALE), - end / (float)(TREE_SCALE), - radius / (float)(TREE_SCALE), - penetration, - false }; + CapsuleArgs args = { start, end, radius, penetration, false }; penetration = glm::vec3(0.0f, 0.0f, 0.0f); bool gotLock = false; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 954d0b7847..bdfe87a653 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1338,7 +1338,7 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 keepSearching = true; // assume that we will continue searching after this. AACube cube = getAACube(); - cube *= (float)TREE_SCALE; + cube.scale((float)TREE_SCALE); float distanceToElementCube = std::numeric_limits<float>::max(); float distanceToElementDetails = distance; BoxFace localFace; @@ -1392,7 +1392,7 @@ bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const { // center and radius are in meters, so we have to scale the _cube into world-frame AACube cube = _cube; - cube *= (float)TREE_SCALE; + cube.scale((float)TREE_SCALE); return cube.findSpherePenetration(center, radius, penetration); } diff --git a/libraries/shared/src/AACube.h b/libraries/shared/src/AACube.h index 5bcf9527cf..b29bc49bef 100644 --- a/libraries/shared/src/AACube.h +++ b/libraries/shared/src/AACube.h @@ -63,8 +63,6 @@ public: AABox clamp(const glm::vec3& min, const glm::vec3& max) const; AABox clamp(float min, float max) const; - AACube& operator *= (float scale); - private: glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const; @@ -76,12 +74,6 @@ private: float _scale; }; -inline AACube& AACube::operator *= (float scale) { - _corner *= scale; - _scale *= scale; - return *this; -} - inline bool operator==(const AACube& a, const AACube& b) { return a.getCorner() == b.getCorner() && a.getScale() == b.getScale(); } From 26bb67784060976cc933f24e484f1fb73e6cc670 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 4 Mar 2015 17:26:52 -0800 Subject: [PATCH 20/56] remove ViewFrustum::*VoxelScale() function calls we do our math in meters now --- libraries/octree/src/OctreeElement.cpp | 8 +++++--- libraries/octree/src/ViewFrustum.cpp | 27 -------------------------- libraries/octree/src/ViewFrustum.h | 6 +----- 3 files changed, 6 insertions(+), 35 deletions(-) diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index bdfe87a653..5e6fd0dde3 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1257,10 +1257,12 @@ bool OctreeElement::calculateShouldRender(const ViewFrustum* viewFrustum, float // does as much math as possible in voxel scale and then scales up to TREE_SCALE at end float OctreeElement::furthestDistanceToCamera(const ViewFrustum& viewFrustum) const { glm::vec3 furthestPoint; - viewFrustum.getFurthestPointFromCameraVoxelScale(getAACube(), furthestPoint); - glm::vec3 temp = viewFrustum.getPositionVoxelScale() - furthestPoint; + AACube cube = getAACube(); + cube.scale((float)TREE_SCALE); + viewFrustum.getFurthestPointFromCamera(cube, furthestPoint); + glm::vec3 temp = viewFrustum.getPosition() - furthestPoint; float distanceToFurthestPoint = sqrtf(glm::dot(temp, temp)); - return distanceToFurthestPoint * (float)TREE_SCALE; + return distanceToFurthestPoint; } float OctreeElement::distanceToCamera(const ViewFrustum& viewFrustum) const { diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 81ce31d767..164f78249b 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -833,33 +833,6 @@ void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furth } } -void ViewFrustum::getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const { - const glm::vec3& bottomNearRight = box.getCorner(); - float scale = box.getScale(); - float halfScale = scale * 0.5f; - - if (_positionVoxelScale.x < bottomNearRight.x + halfScale) { - // we are to the right of the center, so the left edge is furthest - furthestPoint.x = bottomNearRight.x + scale; - } else { - furthestPoint.x = bottomNearRight.x; - } - - if (_positionVoxelScale.y < bottomNearRight.y + halfScale) { - // we are below of the center, so the top edge is furthest - furthestPoint.y = bottomNearRight.y + scale; - } else { - furthestPoint.y = bottomNearRight.y; - } - - if (_positionVoxelScale.z < bottomNearRight.z + halfScale) { - // we are to the near side of the center, so the far side edge is furthest - furthestPoint.z = bottomNearRight.z + scale; - } else { - furthestPoint.z = bottomNearRight.z; - } -} - float ViewFrustum::distanceToCamera(const glm::vec3& point) const { glm::vec3 temp = getPosition() - point; float distanceToPoint = sqrtf(glm::dot(temp, temp)); diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 3f7921f9b7..edef001cdd 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -37,12 +37,11 @@ public: ViewFrustum(); // setters for camera attributes - void setPosition(const glm::vec3& p) { _position = p; _positionVoxelScale = (p / (float)TREE_SCALE); } + void setPosition(const glm::vec3& p) { _position = p; } void setOrientation(const glm::quat& orientationAsQuaternion); // getters for camera attributes const glm::vec3& getPosition() const { return _position; } - const glm::vec3& getPositionVoxelScale() const { return _positionVoxelScale; } const glm::quat& getOrientation() const { return _orientation; } const glm::vec3& getDirection() const { return _direction; } const glm::vec3& getUp() const { return _up; } @@ -119,8 +118,6 @@ public: OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const; void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; - void getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const; - float distanceToCamera(const glm::vec3& point) const; private: @@ -134,7 +131,6 @@ private: // camera location/orientation attributes glm::vec3 _position = glm::vec3(0.0f); // the position in world-frame - glm::vec3 _positionVoxelScale = glm::vec3(0.0f); // the position in voxel scale glm::quat _orientation = glm::quat(); // calculated for orientation From 59a70b5b5f426e9935cd37e7d5970fc633cc4d29 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Wed, 4 Mar 2015 17:32:46 -0800 Subject: [PATCH 21/56] remove cruft and fix default entity dimensions --- libraries/entities/src/EntityItemPropertiesDefaults.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index 22beb3937e..b184d510b3 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -20,8 +20,6 @@ // creating a new one on the stack so we declare the ZERO_VEC3 constant as an optimization. const glm::vec3 ENTITY_ITEM_ZERO_VEC3(0.0f); -const glm::vec3 REGULAR_GRAVITY = glm::vec3(0, -9.8f / (float)TREE_SCALE, 0); - const bool ENTITY_ITEM_DEFAULT_LOCKED = false; const QString ENTITY_ITEM_DEFAULT_USER_DATA = QString(""); @@ -37,7 +35,7 @@ const float ENTITY_ITEM_DEFAULT_LIFETIME = ENTITY_ITEM_IMMORTAL_LIFETIME; const glm::quat ENTITY_ITEM_DEFAULT_ROTATION; const float ENTITY_ITEM_DEFAULT_WIDTH = 0.1f; -const glm::vec3 ENTITY_ITEM_DEFAULT_DIMENSIONS = glm::vec3(ENTITY_ITEM_DEFAULT_WIDTH) / (float)TREE_SCALE; +const glm::vec3 ENTITY_ITEM_DEFAULT_DIMENSIONS = glm::vec3(ENTITY_ITEM_DEFAULT_WIDTH); const float ENTITY_ITEM_DEFAULT_VOLUME = ENTITY_ITEM_DEFAULT_WIDTH * ENTITY_ITEM_DEFAULT_WIDTH * ENTITY_ITEM_DEFAULT_WIDTH; const float ENTITY_ITEM_MAX_DENSITY = 10000.0f; // kg/m^3 density of silver From 1b7fdf5d16b76581ee5e29f688c8b4a8e57a5e6d Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Thu, 5 Mar 2015 18:49:52 +0100 Subject: [PATCH 22/56] Improve disk cache usage Now we always load from the disk cache if the file is in there. Then we check the last modidied date from the network file against the one in the cache. If needed, we redownload. --- libraries/networking/src/ResourceCache.cpp | 43 +++++++++++++++++++++- libraries/networking/src/ResourceCache.h | 6 ++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 7eadb0a3dd..658f32aba1 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -12,9 +12,10 @@ #include <cfloat> #include <cmath> +#include <QDebug> +#include <QNetworkDiskCache> #include <QThread> #include <QTimer> -#include <QtDebug> #include <SharedUtil.h> @@ -314,13 +315,51 @@ void Resource::handleReplyTimeout() { "received" << _bytesReceived << "total" << _bytesTotal); } +void Resource::maybeRefresh() { + if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) { + QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); + QVariant variant = reply->header(QNetworkRequest::LastModifiedHeader); + QNetworkCacheMetaData metaData = NetworkAccessManager::getInstance().cache()->metaData(_url); + if (variant.isValid() && variant.canConvert<QDateTime>() && metaData.isValid()) { + QDateTime lastModified = variant.value<QDateTime>(); + QDateTime lastModifiedOld = metaData.lastModified(); + if (lastModified.isValid() && lastModifiedOld.isValid() && + lastModifiedOld == lastModified) { + // We don't need to update, return + return; + } + } + qDebug() << "Loaded" << _url.fileName() << "from the disk cache but the network version is newer, refreshing."; + refresh(); + } +} + void Resource::makeRequest() { _reply = NetworkAccessManager::getInstance().get(_request); connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64))); connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError())); connect(_reply, SIGNAL(finished()), SLOT(handleReplyFinished())); - + + if (_reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool()) { + // If the file as been updated since it was cached, refresh it + QNetworkRequest request(_request); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); + request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false); + QNetworkReply* reply = NetworkAccessManager::getInstance().head(request); + connect(reply, &QNetworkReply::finished, this, &Resource::maybeRefresh); + } else { + if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) { + QNetworkCacheMetaData metaData = NetworkAccessManager::getInstance().cache()->metaData(_url); + if (metaData.expirationDate().isNull() || metaData.expirationDate() <= QDateTime::currentDateTime()) { + // If the expiration date is NULL or in the past, + // put one far enough away that it won't be an issue. + metaData.setExpirationDate(QDateTime::currentDateTime().addYears(100)); + NetworkAccessManager::getInstance().cache()->updateMetaData(metaData); + } + } + } + _replyTimer = new QTimer(this); connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout())); _replyTimer->setSingleShot(true); diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 62fca71ea5..11b091a9e3 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -149,7 +149,7 @@ public: /// For loading resources, returns the load progress. float getProgress() const { return (_bytesTotal <= 0) ? 0.0f : (float)_bytesReceived / _bytesTotal; } - + /// Refreshes the resource. void refresh(); @@ -169,6 +169,10 @@ signals: protected slots: void attemptRequest(); + + /// Refreshes the resource if the last modified date on the network + /// is greater than the last modified date in the cache. + void maybeRefresh(); protected: From 9d7144dab04921ab7428f4e52ec083485f42dec8 Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Thu, 5 Mar 2015 18:52:48 +0100 Subject: [PATCH 23/56] Bumped disk cache size to 10GB --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6484e364bc..96874f8593 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -141,7 +141,7 @@ using namespace std; static unsigned STARFIELD_NUM_STARS = 50000; static unsigned STARFIELD_SEED = 1; -const qint64 MAXIMUM_CACHE_SIZE = 10737418240; // 10GB +const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES; // 10GB static QTimer* locationUpdateTimer = NULL; static QTimer* balanceUpdateTimer = NULL; From 53f23d8452ed15cd1107d99f6c6632cd361e3e85 Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Thu, 5 Mar 2015 21:08:14 +0100 Subject: [PATCH 24/56] Added disk cache editor --- interface/src/ui/DiskCacheEditor.cpp | 148 +++++++++++++++++++++++++++ interface/src/ui/DiskCacheEditor.h | 46 +++++++++ 2 files changed, 194 insertions(+) create mode 100644 interface/src/ui/DiskCacheEditor.cpp create mode 100644 interface/src/ui/DiskCacheEditor.h diff --git a/interface/src/ui/DiskCacheEditor.cpp b/interface/src/ui/DiskCacheEditor.cpp new file mode 100644 index 0000000000..d1987462e3 --- /dev/null +++ b/interface/src/ui/DiskCacheEditor.cpp @@ -0,0 +1,148 @@ +// +// DiskCacheEditor.cpp +// +// +// Created by Clement on 3/4/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include <QDebug> +#include <QDialog> +#include <QGridLayout> +#include <QPushButton> +#include <QLabel> +#include <QNetworkDiskCache> +#include <QMessageBox> + +#include <NetworkAccessManager.h> + +#include "DiskCacheEditor.h" + +DiskCacheEditor::DiskCacheEditor(QWidget* parent) : QObject(parent) { + +} + +QWindow* DiskCacheEditor::windowHandle() { + return (_dialog) ? _dialog->windowHandle() : nullptr; +} + +void DiskCacheEditor::toggle() { + qDebug() << "DiskCacheEditor::toggle()"; + if (!_dialog) { + makeDialog(); + } + + if (!_dialog->isActiveWindow()) { + _dialog->show(); + _dialog->raise(); + _dialog->activateWindow(); + } else { + _dialog->close(); + } +} + +void DiskCacheEditor::makeDialog() { + _dialog = new QDialog(static_cast<QWidget*>(parent())); + Q_CHECK_PTR(_dialog); + _dialog->setAttribute(Qt::WA_DeleteOnClose); + _dialog->setWindowTitle("Disk Cache Editor"); + + QGridLayout* layout = new QGridLayout(_dialog); + Q_CHECK_PTR(layout); + _dialog->setLayout(layout); + + + QLabel* path = new QLabel("Path : ", _dialog); + Q_CHECK_PTR(path); + path->setAlignment(Qt::AlignRight); + layout->addWidget(path, 0, 0); + + QLabel* size = new QLabel("Max Size : ", _dialog); + Q_CHECK_PTR(size); + size->setAlignment(Qt::AlignRight); + layout->addWidget(size, 1, 0); + + QLabel* maxSize = new QLabel("Current Size : ", _dialog); + Q_CHECK_PTR(maxSize); + maxSize->setAlignment(Qt::AlignRight); + layout->addWidget(maxSize, 2, 0); + + + _path = new QLabel(_dialog); + Q_CHECK_PTR(_path); + _path->setAlignment(Qt::AlignLeft); + layout->addWidget(_path, 0, 1, 1, 3); + + _size = new QLabel(_dialog); + Q_CHECK_PTR(_size); + _size->setAlignment(Qt::AlignLeft); + layout->addWidget(_size, 1, 1, 1, 3); + + _maxSize = new QLabel(_dialog); + Q_CHECK_PTR(_maxSize); + _maxSize->setAlignment(Qt::AlignLeft); + layout->addWidget(_maxSize, 2, 1, 1, 3); + + refresh(); + + + QPushButton* refreshCacheButton = new QPushButton(_dialog); + Q_CHECK_PTR(refreshCacheButton); + refreshCacheButton->setText("Refresh"); + refreshCacheButton->setToolTip("Reload the cache stats."); + connect(refreshCacheButton, SIGNAL(clicked()), SLOT(refresh())); + layout->addWidget(refreshCacheButton, 3, 2); + + QPushButton* clearCacheButton = new QPushButton(_dialog); + Q_CHECK_PTR(clearCacheButton); + clearCacheButton->setText("Clear"); + clearCacheButton->setToolTip("Erases the entire content of the disk cache."); + connect(clearCacheButton, SIGNAL(clicked()), SLOT(clear())); + layout->addWidget(clearCacheButton, 3, 3); +} + +void DiskCacheEditor::refresh() { + static const std::function<QString(qint64)> stringify = [](qint64 number) { + static const QStringList UNITS = QStringList() << "B" << "KB" << "MB" << "GB"; + static const qint64 CHUNK = 1024; + QString unit; + int i = 0; + for (i = 0; i < 4; ++i) { + if (number / CHUNK > 0) { + number /= CHUNK; + } else { + break; + } + } + return QString("%0 %1").arg(number).arg(UNITS[i]); + }; + QNetworkDiskCache* cache = qobject_cast<QNetworkDiskCache*>(NetworkAccessManager::getInstance().cache()); + + if (_path) { + _path->setText(cache->cacheDirectory()); + } + if (_size) { + _size->setText(stringify(cache->cacheSize())); + } + if (_maxSize) { + _maxSize->setText(stringify(cache->maximumCacheSize())); + } +} + +void DiskCacheEditor::clear() { + QMessageBox::StandardButton buttonClicked = + QMessageBox::question(_dialog, "Clearing disk cache", + "You are about to erase all the content of the disk cache," + "are you sure you want to do that?"); + if (buttonClicked == QMessageBox::Yes) { + QNetworkDiskCache* cache = qobject_cast<QNetworkDiskCache*>(NetworkAccessManager::getInstance().cache()); + if (cache) { + qDebug() << "DiskCacheEditor::clear(): Clearing disk cache."; + cache->clear(); + } + } + refresh(); +} diff --git a/interface/src/ui/DiskCacheEditor.h b/interface/src/ui/DiskCacheEditor.h new file mode 100644 index 0000000000..5d673c4285 --- /dev/null +++ b/interface/src/ui/DiskCacheEditor.h @@ -0,0 +1,46 @@ +// +// DiskCacheEditor.h +// +// +// Created by Clement on 3/4/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_DiskCacheEditor_h +#define hifi_DiskCacheEditor_h + +#include <QObject> +#include <QPointer> + +class QDialog; +class QLabel; +class QWindow; + +class DiskCacheEditor : public QObject { + Q_OBJECT + +public: + DiskCacheEditor(QWidget* parent = nullptr); + + QWindow* windowHandle(); + +public slots: + void toggle(); + +private slots: + void refresh(); + void clear(); + +private: + void makeDialog(); + + QPointer<QDialog> _dialog; + QPointer<QLabel> _path; + QPointer<QLabel> _size; + QPointer<QLabel> _maxSize; +}; + +#endif // hifi_DiskCacheEditor_h \ No newline at end of file From 908e946ac5c606929137c17090975898d5faa967 Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Thu, 5 Mar 2015 21:09:23 +0100 Subject: [PATCH 25/56] Hook up disk cache to the dialog manager --- interface/src/ui/DialogsManager.cpp | 7 ++++++- interface/src/ui/DialogsManager.h | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 2452369c18..ad963e8af3 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -20,6 +20,7 @@ #include "AttachmentsDialog.h" #include "BandwidthDialog.h" #include "CachesSizeDialog.h" +#include "DiskCacheEditor.h" #include "HMDToolsDialog.h" #include "LodToolsDialog.h" #include "LoginDialog.h" @@ -37,6 +38,11 @@ void DialogsManager::toggleAddressBar() { } } +void DialogsManager::toggleDiskCacheEditor() { + maybeCreateDialog(_diskCacheEditor); + _diskCacheEditor->toggle(); +} + void DialogsManager::toggleLoginDialog() { maybeCreateDialog(_loginDialog); _loginDialog->toggleQAction(); @@ -61,7 +67,6 @@ void DialogsManager::octreeStatsDetails() { } void DialogsManager::cachesSizeDialog() { - qDebug() << "Caches size:" << _cachesSizeDialog.isNull(); if (!_cachesSizeDialog) { maybeCreateDialog(_cachesSizeDialog); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index e2da71bbd8..897215cbff 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -24,8 +24,9 @@ class QAction; class AddressBarDialog; class AnimationsDialog; class AttachmentsDialog; -class CachesSizeDialog; class BandwidthDialog; +class CachesSizeDialog; +class DiskCacheEditor; class LodToolsDialog; class LoginDialog; class OctreeStatsDialog; @@ -45,6 +46,7 @@ public: public slots: void toggleAddressBar(); + void toggleDiskCacheEditor(); void toggleLoginDialog(); void showLoginDialog(); void octreeStatsDetails(); @@ -73,7 +75,7 @@ private: member = new T(parent); Q_CHECK_PTR(member); - if (_hmdToolsDialog) { + if (_hmdToolsDialog && member->windowHandle()) { _hmdToolsDialog->watchWindow(member->windowHandle()); } } @@ -84,6 +86,7 @@ private: QPointer<AttachmentsDialog> _attachmentsDialog; QPointer<BandwidthDialog> _bandwidthDialog; QPointer<CachesSizeDialog> _cachesSizeDialog; + QPointer<DiskCacheEditor> _diskCacheEditor; QPointer<QMessageBox> _ircInfoBox; QPointer<HMDToolsDialog> _hmdToolsDialog; QPointer<LodToolsDialog> _lodToolsDialog; From f4d8ee39dcae0587138dc48681af3063834c47df Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Thu, 5 Mar 2015 21:10:02 +0100 Subject: [PATCH 26/56] Menu item for cache editor --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 2 ++ interface/src/Menu.h | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 96874f8593..3454557fe9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -445,7 +445,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : cache->setMaximumCacheSize(MAXIMUM_CACHE_SIZE); cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache"); networkAccessManager.setCache(cache); - + ResourceCache::setRequestLimit(3); _window->setCentralWidget(_glWidget); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 59d6734b2a..ea63b9879f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -436,6 +436,8 @@ Menu::Menu() { SLOT(disable(bool))); addActionToQMenuAndActionHash(networkMenu, MenuOption::CachesSize, 0, dialogsManager.data(), SLOT(cachesSizeDialog())); + addActionToQMenuAndActionHash(networkMenu, MenuOption::DiskCacheEditor, 0, + dialogsManager.data(), SLOT(toggleDiskCacheEditor())); QMenu* timingMenu = developerMenu->addMenu("Timing and Stats"); QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fe1035d54b..3166e1fa37 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -125,7 +125,7 @@ namespace MenuOption { const QString BookmarkLocation = "Bookmark Location"; const QString Bookmarks = "Bookmarks"; const QString CascadedShadows = "Cascaded"; - const QString CachesSize = "Caches Size"; + const QString CachesSize = "RAM Caches Size"; const QString Chat = "Chat..."; const QString ChatCircling = "Chat Circling"; const QString CollideAsRagdoll = "Collide With Self (Ragdoll)"; @@ -143,6 +143,7 @@ namespace MenuOption { const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; const QString DisableLightEntities = "Disable Light Entities"; const QString DisableNackPackets = "Disable NACK Packets"; + const QString DiskCacheEditor = "Disk Cache Editor"; const QString DisplayHands = "Show Hand Info"; const QString DisplayHandTargets = "Show Hand Targets"; const QString DisplayModelBounds = "Display Model Bounds"; From 2c68d560594b0b9c8daba51367ca86f4f5d7c16d Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 12:34:05 -0800 Subject: [PATCH 27/56] Update Entity::sendEntities to return new entity ids --- libraries/entities/src/EntityTree.cpp | 7 ++++++- libraries/entities/src/EntityTree.h | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 978ba43960..99095aa251 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1000,13 +1000,17 @@ void EntityTree::pruneTree() { recurseTreeWithOperator(&theOperator); } -void EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z) { +QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z) { SendEntitiesOperationArgs args; args.packetSender = packetSender; args.localTree = localTree; args.root = glm::vec3(x, y, z); + QVector<EntityItemID> newEntityIDs; + args.newEntityIDs = &newEntityIDs; recurseTreeWithOperation(sendEntitiesOperation, &args); packetSender->releaseQueuedMessages(); + + return newEntityIDs; } bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData) { @@ -1016,6 +1020,7 @@ bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData) const QList<EntityItem*>& entities = entityTreeElement->getEntities(); for (int i = 0; i < entities.size(); i++) { EntityItemID newID(NEW_ENTITY, EntityItemID::getNextCreatorTokenID(), false); + args->newEntityIDs->append(newID); EntityItemProperties properties = entities[i]->getProperties(); properties.setPosition(properties.getPosition() + args->root); properties.markAllChanged(); // so the entire property set is considered new, since we're making a new entity diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index d8b9b9f38f..2935cf56d2 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -39,6 +39,7 @@ public: glm::vec3 root; EntityTree* localTree; EntityEditPacketSender* packetSender; + QVector<EntityItemID>* newEntityIDs; }; @@ -144,7 +145,7 @@ public: virtual void dumpTree(); virtual void pruneTree(); - void sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z); + QVector<EntityItemID> sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z); void entityChanged(EntityItem* entity); From a922619ebc2e77db3ff3c99e8728b112bf4b4b34 Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 12:36:10 -0800 Subject: [PATCH 28/56] Add Clipboard.exportEntities that takes a list of entity IDs --- interface/src/Application.h | 1 + interface/src/scripting/ClipboardScriptingInterface.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/interface/src/Application.h b/interface/src/Application.h index 91a5f7547b..9c32f32b8f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -324,6 +324,7 @@ public slots: void packetSent(quint64 length); void pasteEntities(float x, float y, float z); + bool exportEntities(const QString& filename, const QStringList& entityIDs); bool exportEntities(const QString& filename, float x, float y, float z, float scale); bool importEntities(const QString& filename); diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index 2411cc08eb..6002661011 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -14,6 +14,10 @@ ClipboardScriptingInterface::ClipboardScriptingInterface() { } +bool ClipboardScriptingInterface::exportEntities(const QString& filename, QStringList entityIDs) { + return Application::getInstance()->exportEntities(filename, entityIDs); +} + bool ClipboardScriptingInterface::exportEntities(const QString& filename, float x, float y, float z, float s) { return Application::getInstance()->exportEntities(filename, x, y, z, s); } From 71768ef27573bba0a6d0740ece7d4f20dccfb7be Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 12:36:45 -0800 Subject: [PATCH 29/56] Return entity IDs on paste --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 +- interface/src/scripting/ClipboardScriptingInterface.cpp | 4 ++-- interface/src/scripting/ClipboardScriptingInterface.h | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6484e364bc..6f5239a6b2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1683,8 +1683,8 @@ bool Application::importEntities(const QString& filename) { return success; } -void Application::pasteEntities(float x, float y, float z) { - _entityClipboard.sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); +QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) { + return _entityClipboard.sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); } void Application::initDisplay() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 9c32f32b8f..e027f85538 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -323,7 +323,7 @@ public slots: void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); - void pasteEntities(float x, float y, float z); + QVector<EntityItemID> pasteEntities(float x, float y, float z); bool exportEntities(const QString& filename, const QStringList& entityIDs); bool exportEntities(const QString& filename, float x, float y, float z, float scale); bool importEntities(const QString& filename); diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index 6002661011..a06a0500f3 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -26,6 +26,6 @@ bool ClipboardScriptingInterface::importEntities(const QString& filename) { return Application::getInstance()->importEntities(filename); } -void ClipboardScriptingInterface::pasteEntities(float x, float y, float z, float s) { - Application::getInstance()->pasteEntities(x, y, z); +QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(float x, float y, float z, float s) { + return Application::getInstance()->pasteEntities(x, y, z); } diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index bc270210dc..bb993c32a4 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -23,8 +23,9 @@ signals: public slots: bool importEntities(const QString& filename); + bool exportEntities(const QString& filename, QStringList entityIDs); bool exportEntities(const QString& filename, float x, float y, float z, float s); - void pasteEntities(float x, float y, float z, float s); + QVector<EntityItemID> pasteEntities(float x, float y, float z, float s); }; #endif // hifi_ClipboardScriptingInterface_h From 7690301e582ec54d9947fefc86f6294313cdfba6 Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Thu, 5 Mar 2015 21:49:22 +0100 Subject: [PATCH 30/56] Include functional --- interface/src/ui/DiskCacheEditor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/ui/DiskCacheEditor.cpp b/interface/src/ui/DiskCacheEditor.cpp index d1987462e3..38fd1cb383 100644 --- a/interface/src/ui/DiskCacheEditor.cpp +++ b/interface/src/ui/DiskCacheEditor.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include <functional> + #include <QDebug> #include <QDialog> #include <QGridLayout> From 684802550454295528c2fbadb85e6a66c6456e24 Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 13:36:16 -0800 Subject: [PATCH 31/56] Add exporting by entity ID to Application --- interface/src/Application.cpp | 41 +++++++++++++++++++ interface/src/Application.h | 2 +- .../scripting/ClipboardScriptingInterface.cpp | 2 +- .../scripting/ClipboardScriptingInterface.h | 2 +- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6f5239a6b2..e63e9f6de5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1633,6 +1633,47 @@ void Application::setActiveFaceTracker() { #endif } +bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) { + QVector<EntityItem*> entities; + + auto entityTree = _entities.getTree(); + EntityTree exportTree; + + glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE); + for (auto entityID : entityIDs) { + auto entityItem = entityTree->findEntityByEntityItemID(entityID); + if (!entityItem) { + continue; + } + + auto properties = entityItem->getProperties(); + auto position = properties.getPosition(); + + root.x = glm::min(root.x, position.x); + root.y = glm::min(root.y, position.y); + root.z = glm::min(root.z, position.z); + + entities << entityItem; + } + + if (entities.size() == 0) { + return false; + } + + for (auto entityItem : entities) { + auto properties = entityItem->getProperties(); + + properties.setPosition(properties.getPosition() - root); + exportTree.addEntity(entityItem->getEntityItemID(), properties); + } + + exportTree.writeToSVOFile(filename.toLocal8Bit().constData()); + + // restore the main window's active state + _window->activateWindow(); + return true; +} + bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { QVector<EntityItem*> entities; _entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE, diff --git a/interface/src/Application.h b/interface/src/Application.h index e027f85538..73a3f1658b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -324,7 +324,7 @@ public slots: void packetSent(quint64 length); QVector<EntityItemID> pasteEntities(float x, float y, float z); - bool exportEntities(const QString& filename, const QStringList& entityIDs); + bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs); bool exportEntities(const QString& filename, float x, float y, float z, float scale); bool importEntities(const QString& filename); diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index a06a0500f3..5c9370771c 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -14,7 +14,7 @@ ClipboardScriptingInterface::ClipboardScriptingInterface() { } -bool ClipboardScriptingInterface::exportEntities(const QString& filename, QStringList entityIDs) { +bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) { return Application::getInstance()->exportEntities(filename, entityIDs); } diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index bb993c32a4..9fe676ad03 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -23,7 +23,7 @@ signals: public slots: bool importEntities(const QString& filename); - bool exportEntities(const QString& filename, QStringList entityIDs); + bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs); bool exportEntities(const QString& filename, float x, float y, float z, float s); QVector<EntityItemID> pasteEntities(float x, float y, float z, float s); }; From 03c03a20f9866c8a85a3b31e4fb07bb272eb57ef Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 13:52:30 -0800 Subject: [PATCH 32/56] Update pasteEntities to use vec3 --- interface/src/scripting/ClipboardScriptingInterface.cpp | 4 ++-- interface/src/scripting/ClipboardScriptingInterface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index 5c9370771c..616fc5f141 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -26,6 +26,6 @@ bool ClipboardScriptingInterface::importEntities(const QString& filename) { return Application::getInstance()->importEntities(filename); } -QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(float x, float y, float z, float s) { - return Application::getInstance()->pasteEntities(x, y, z); +QVector<EntityItemID> ClipboardScriptingInterface::pasteEntities(glm::vec3 position) { + return Application::getInstance()->pasteEntities(position.x, position.y, position.z); } diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 9fe676ad03..92204af60d 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -25,7 +25,7 @@ public slots: bool importEntities(const QString& filename); bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs); bool exportEntities(const QString& filename, float x, float y, float z, float s); - QVector<EntityItemID> pasteEntities(float x, float y, float z, float s); + QVector<EntityItemID> pasteEntities(glm::vec3 position); }; #endif // hifi_ClipboardScriptingInterface_h From a2617b2c9668f2d7493e7e40a0d2f9f2120a90cb Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 13:52:59 -0800 Subject: [PATCH 33/56] Update editEntities import/export --- examples/editEntities.js | 42 +++++++++++++++++++++++--------- examples/libraries/ExportMenu.js | 1 - 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index a0f3cdc167..c4d814ff43 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -420,8 +420,6 @@ var toolBar = (function () { }()); -var exportMenu = null; - function isLocked(properties) { // special case to lock the ground plane model in hq. if (location.hostname == "hq.highfidelity.io" && @@ -749,9 +747,6 @@ Script.scriptEnding.connect(function() { tooltip.cleanup(); modelImporter.cleanup(); selectionDisplay.cleanup(); - if (exportMenu) { - exportMenu.close(); - } Entities.setLightsArePickable(originalLightsArePickable); }); @@ -796,15 +791,40 @@ function handeMenuEvent(menuItem) { } else if (menuItem == "Paste Models") { modelImporter.paste(); } else if (menuItem == "Export Models") { - if (!exportMenu) { - exportMenu = new ExportMenu({ - onClose: function () { - exportMenu = null; + if (!selectionManager.hasSelection()) { + Window.alert("No entities have been selected."); + } else { + var filename = "models__" + Window.location.hostname + "__.svo"; + filename = Window.save("Select where to save", filename, "*.svo") + if (filename) { + var success = Clipboard.exportEntities(filename, selectionManager.selections); + if (!success) { + Window.alert("Export failed."); } - }); + } } } else if (menuItem == "Import Models") { - modelImporter.doImport(); + var filename = Window.browse("Select models to import", "", "*.svo") + if (filename) { + var success = Clipboard.importEntities(filename); + + if (success) { + var distance = cameraManager.enabled ? cameraManager.zoomDistance : DEFAULT_ENTITY_DRAG_DROP_DISTANCE; + var direction = Quat.getFront(Camera.orientation); + var offset = Vec3.multiply(distance, direction); + var position = Vec3.sum(Camera.position, offset); + + position.x = Math.max(0, position.x); + position.y = Math.max(0, position.y); + position.z = Math.max(0, position.z); + + var pastedEntityIDs = Clipboard.pasteEntities(position); + + selectionManager.setSelections(pastedEntityIDs); + } else { + Window.alert("There was an error importing the entity file."); + } + } } else if (menuItem == "Entity List...") { entityListTool.toggleVisible(); } diff --git a/examples/libraries/ExportMenu.js b/examples/libraries/ExportMenu.js index 247391808f..dd6dcd4324 100644 --- a/examples/libraries/ExportMenu.js +++ b/examples/libraries/ExportMenu.js @@ -219,6 +219,5 @@ ExportMenu = function (opts) { Overlays.deleteOverlay(scaleView); }; - print("CONNECTING!"); Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); }; From 08b905095d50c1c09e5ee7223046f450e4bc5b95 Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 13:54:27 -0800 Subject: [PATCH 34/56] Remove Paste Models and rename Import/Export to Entities --- examples/editEntities.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index c4d814ff43..6d7d0c7cb4 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -692,17 +692,16 @@ function setupModelMenus() { } Menu.addMenuItem({ menuName: "Edit", menuItemName: "Entity List...", shortcutKey: "CTRL+META+L", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Entity List..." }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", - afterItem: "Paste Models", isCheckable: true, isChecked: true }); + afterItem: "Entity List...", isCheckable: true, isChecked: true }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", afterItem: "Allow Selecting of Large Models", isCheckable: true, isChecked: true }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", afterItem: "Allow Selecting of Small Models", isCheckable: true }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); + Menu.addMenuItem({ menuName: "File", menuItemName: "Export Entities", shortcutKey: "CTRL+META+E", afterItem: "Models" }); + Menu.addMenuItem({ menuName: "File", menuItemName: "Import Entities", shortcutKey: "CTRL+META+I", afterItem: "Export Entities" }); Menu.addMenuItem({ menuName: "View", menuItemName: MENU_AUTO_FOCUS_ON_SELECT, afterItem: MENU_INSPECT_TOOL_ENABLED, @@ -723,14 +722,13 @@ function cleanupModelMenus() { } Menu.removeMenuItem("Edit", "Entity List..."); - Menu.removeMenuItem("Edit", "Paste Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); Menu.removeSeparator("File", "Models"); - Menu.removeMenuItem("File", "Export Models"); - Menu.removeMenuItem("File", "Import Models"); + Menu.removeMenuItem("File", "Export Entities"); + Menu.removeMenuItem("File", "Import Entities"); Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED); Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT); @@ -745,7 +743,6 @@ Script.scriptEnding.connect(function() { toolBar.cleanup(); cleanupModelMenus(); tooltip.cleanup(); - modelImporter.cleanup(); selectionDisplay.cleanup(); Entities.setLightsArePickable(originalLightsArePickable); }); @@ -788,9 +785,7 @@ function handeMenuEvent(menuItem) { Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); } else if (menuItem == "Delete") { deleteSelectedEntities(); - } else if (menuItem == "Paste Models") { - modelImporter.paste(); - } else if (menuItem == "Export Models") { + } else if (menuItem == "Export Entities") { if (!selectionManager.hasSelection()) { Window.alert("No entities have been selected."); } else { @@ -803,7 +798,7 @@ function handeMenuEvent(menuItem) { } } } - } else if (menuItem == "Import Models") { + } else if (menuItem == "Import Entities") { var filename = Window.browse("Select models to import", "", "*.svo") if (filename) { var success = Clipboard.importEntities(filename); From 9247ccd7b321d21f1faad788022933923e9b0945 Mon Sep 17 00:00:00 2001 From: Ryan Huffman <ryanhuffman@gmail.com> Date: Thu, 5 Mar 2015 13:55:22 -0800 Subject: [PATCH 35/56] Remove ExportMenu.js and ModelImporter.js --- examples/editEntities.js | 3 - examples/libraries/ExportMenu.js | 223 ---------------------------- examples/libraries/ModelImporter.js | 200 ------------------------- 3 files changed, 426 deletions(-) delete mode 100644 examples/libraries/ExportMenu.js delete mode 100644 examples/libraries/ModelImporter.js diff --git a/examples/editEntities.js b/examples/editEntities.js index 6d7d0c7cb4..e6d4534b86 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -22,9 +22,7 @@ Script.include([ "libraries/progressDialog.js", "libraries/entitySelectionTool.js", - "libraries/ModelImporter.js", - "libraries/ExportMenu.js", "libraries/ToolTip.js", "libraries/entityPropertyDialogBox.js", @@ -35,7 +33,6 @@ Script.include([ var selectionDisplay = SelectionDisplay; var selectionManager = SelectionManager; -var modelImporter = new ModelImporter(); var entityPropertyDialogBox = EntityPropertyDialogBox; var cameraManager = new CameraManager(); diff --git a/examples/libraries/ExportMenu.js b/examples/libraries/ExportMenu.js deleted file mode 100644 index dd6dcd4324..0000000000 --- a/examples/libraries/ExportMenu.js +++ /dev/null @@ -1,223 +0,0 @@ -// -// ExportMenu.js -// examples/libraries -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -ExportMenu = function (opts) { - var self = this; - - var windowDimensions = Controller.getViewportDimensions(); - var pos = { x: windowDimensions.x / 2, y: windowDimensions.y - 100 }; - - this._onClose = opts.onClose || function () { }; - this._position = { x: 0.0, y: 0.0, z: 0.0 }; - this._scale = 1.0; - - var minScale = 1; - var maxScale = 32768; - var titleWidth = 120; - var locationWidth = 100; - var scaleWidth = 144; - var exportWidth = 100; - var cancelWidth = 100; - var margin = 4; - var height = 30; - var outerHeight = height + (2 * margin); - var buttonColor = { red: 128, green: 128, blue: 128 }; - - var SCALE_MINUS = scaleWidth * 40.0 / 100.0; - var SCALE_PLUS = scaleWidth * 63.0 / 100.0; - - var fullWidth = locationWidth + scaleWidth + exportWidth + cancelWidth + (2 * margin); - var offset = fullWidth / 2; - pos.x -= offset; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y - height, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - text: "Export Models" - }); - - var locationButton = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - width: locationWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "0, 0, 0", - }); - var scaleOverlay = Overlays.addOverlay("image", { - x: pos.x + margin + locationWidth, - y: pos.y + margin, - width: scaleWidth, - height: height, - subImage: { x: 0, y: 3, width: 144, height: height }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - }); - var scaleViewWidth = 40; - var scaleView = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + SCALE_MINUS, - y: pos.y + margin, - width: scaleViewWidth, - height: height, - backgroundAlpha: 0.0, - color: { red: 255, green: 255, blue: 255 }, - text: "1" - }); - var exportButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth, - y: pos.y + margin, - width: exportWidth, - height: height, - color: { red: 0, green: 255, blue: 255 }, - text: "Export" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth + exportWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "Cancel" - }); - - var voxelPreview = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: this._scale, - color: { red: 255, green: 255, blue: 0 }, - alpha: 1, - solid: false, - visible: true, - lineWidth: 4 - }); - - this.parsePosition = function (str) { - var parts = str.split(','); - if (parts.length == 3) { - var x = parseFloat(parts[0]); - var y = parseFloat(parts[1]); - var z = parseFloat(parts[2]); - if (isFinite(x) && isFinite(y) && isFinite(z)) { - return { x: x, y: y, z: z }; - } - } - return null; - }; - - this.showPositionPrompt = function () { - var positionStr = self._position.x + ", " + self._position.y + ", " + self._position.z; - while (1) { - positionStr = Window.prompt("Position to export form:", positionStr); - if (positionStr == null) { - break; - } - var position = self.parsePosition(positionStr); - if (position != null) { - self.setPosition(position.x, position.y, position.z); - break; - } - Window.alert("The position you entered was invalid."); - } - }; - - this.setScale = function (scale) { - self._scale = Math.min(maxScale, Math.max(minScale, scale)); - Overlays.editOverlay(scaleView, { text: self._scale }); - Overlays.editOverlay(voxelPreview, { size: self._scale }); - } - - this.decreaseScale = function () { - self.setScale(self._scale /= 2); - } - - this.increaseScale = function () { - self.setScale(self._scale *= 2); - } - - this.exportEntities = function() { - var x = self._position.x; - var y = self._position.y; - var z = self._position.z; - var s = self._scale; - var filename = "models__" + Window.location.hostname + "__" + x + "_" + y + "_" + z + "_" + s + "__.svo"; - filename = Window.save("Select where to save", filename, "*.svo") - if (filename) { - var success = Clipboard.exportEntities(filename, x, y, z, s); - if (!success) { - Window.alert("Export failed: no models found in selected area."); - } - } - self.close(); - }; - - this.getPosition = function () { - return self._position; - }; - - this.setPosition = function (x, y, z) { - self._position = { x: x, y: y, z: z }; - var positionStr = x + ", " + y + ", " + z; - Overlays.editOverlay(locationButton, { text: positionStr }); - Overlays.editOverlay(voxelPreview, { position: self._position }); - - }; - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == locationButton) { - self.showPositionPrompt(); - } else if (clickedOverlay == exportButton) { - self.exportEntities(); - } else if (clickedOverlay == cancelButton) { - self.close(); - } else if (clickedOverlay == scaleOverlay) { - var x = event.x - pos.x - margin - locationWidth; - print(x); - if (x < SCALE_MINUS) { - self.decreaseScale(); - } else if (x > SCALE_PLUS) { - self.increaseScale(); - } - } - }; - - this.close = function () { - this.cleanup(); - this._onClose(); - }; - - this.cleanup = function () { - Overlays.deleteOverlay(background); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(locationButton); - Overlays.deleteOverlay(exportButton); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(voxelPreview); - Overlays.deleteOverlay(scaleOverlay); - Overlays.deleteOverlay(scaleView); - }; - - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); -}; diff --git a/examples/libraries/ModelImporter.js b/examples/libraries/ModelImporter.js deleted file mode 100644 index 1e52c8fdec..0000000000 --- a/examples/libraries/ModelImporter.js +++ /dev/null @@ -1,200 +0,0 @@ -// -// ModelImporter.js -// examples/libraries -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - -ModelImporter = function (opts) { - var self = this; - - var windowDimensions = Controller.getViewportDimensions(); - - var height = 30; - var margin = 4; - var outerHeight = height + (2 * margin); - var titleWidth = 120; - var cancelWidth = 100; - var fullWidth = titleWidth + cancelWidth + (2 * margin); - - var localModels = Overlays.addOverlay("localmodels", { - position: { x: 1, y: 1, z: 1 }, - scale: 1, - visible: false - }); - var importScale = 1; - var importBoundaries = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: 1, - color: { red: 128, blue: 128, green: 128 }, - lineWidth: 4, - solid: false, - visible: false - }); - - var pos = { x: windowDimensions.x / 2 - (fullWidth / 2), y: windowDimensions.y - 100 }; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - visible: false, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Import Models" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + titleWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Close" - }); - this._importing = false; - - this.setImportVisible = function (visible) { - Overlays.editOverlay(importBoundaries, { visible: visible }); - Overlays.editOverlay(localModels, { visible: visible }); - Overlays.editOverlay(cancelButton, { visible: visible }); - Overlays.editOverlay(titleText, { visible: visible }); - Overlays.editOverlay(background, { visible: visible }); - }; - - var importPosition = { x: 0, y: 0, z: 0 }; - this.moveImport = function (position) { - importPosition = position; - Overlays.editOverlay(localModels, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - Overlays.editOverlay(importBoundaries, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - } - - this.mouseMoveEvent = function (event) { - if (self._importing) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = Entities.findRayIntersection(pickRay); - - var distance = 2;// * self._scale; - - if (false) {//intersection.intersects) { - var intersectionDistance = Vec3.length(Vec3.subtract(pickRay.origin, intersection.intersection)); - if (intersectionDistance < distance) { - distance = intersectionDistance * 0.99; - } - - } - - var targetPosition = { - x: pickRay.origin.x + (pickRay.direction.x * distance), - y: pickRay.origin.y + (pickRay.direction.y * distance), - z: pickRay.origin.z + (pickRay.direction.z * distance) - }; - - if (targetPosition.x < 0) targetPosition.x = 0; - if (targetPosition.y < 0) targetPosition.y = 0; - if (targetPosition.z < 0) targetPosition.z = 0; - - var nudgeFactor = 1; - var newPosition = { - x: Math.floor(targetPosition.x / nudgeFactor) * nudgeFactor, - y: Math.floor(targetPosition.y / nudgeFactor) * nudgeFactor, - z: Math.floor(targetPosition.z / nudgeFactor) * nudgeFactor - } - - self.moveImport(newPosition); - } - } - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == cancelButton) { - self._importing = false; - self.setImportVisible(false); - } - }; - - // Would prefer to use {4} for the coords, but it would only capture the last digit. - var fileRegex = /__(.+)__(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)__/; - this.doImport = function () { - if (!self._importing) { - var filename = Window.browse("Select models to import", "", "*.svo") - if (filename) { - parts = fileRegex.exec(filename); - if (parts == null) { - Window.alert("The file you selected does not contain source domain or location information"); - } else { - var hostname = parts[1]; - var x = parts[2]; - var y = parts[3]; - var z = parts[4]; - var s = parts[5]; - importScale = s; - if (hostname != location.hostname) { - if (!Window.confirm(("These models were not originally exported from this domain. Continue?"))) { - return; - } - } else { - if (Window.confirm(("Would you like to import back to the source location?"))) { - var success = Clipboard.importEntities(filename); - if (success) { - Clipboard.pasteEntities(x, y, z, 1); - } else { - Window.alert("There was an error importing the entity file."); - } - return; - } - } - } - var success = Clipboard.importEntities(filename); - if (success) { - self._importing = true; - self.setImportVisible(true); - Overlays.editOverlay(importBoundaries, { size: s }); - } else { - Window.alert("There was an error importing the entity file."); - } - } - } - } - - this.paste = function () { - if (self._importing) { - // self._importing = false; - // self.setImportVisible(false); - Clipboard.pasteEntities(importPosition.x, importPosition.y, importPosition.z, 1); - } - } - - this.cleanup = function () { - Overlays.deleteOverlay(localModels); - Overlays.deleteOverlay(importBoundaries); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(background); - } - - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); - Controller.mouseMoveEvent.connect(this.mouseMoveEvent); -}; From e4c68bf31c0a2e1e2842538594581e262352b7dd Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Thu, 5 Mar 2015 18:06:08 -0800 Subject: [PATCH 36/56] committing some temp debug stuff to help git diff (will remove this stuff later) --- CMakeLists.txt | 2 +- .../src/EntityTreeRenderer.cpp | 8 +++++- libraries/entities/src/BoxEntityItem.cpp | 1 + libraries/entities/src/EntityItem.cpp | 28 ++++++------------- libraries/entities/src/EntityItem.h | 7 +++-- .../entities/src/EntityItemProperties.cpp | 1 + libraries/entities/src/EntityTreeElement.cpp | 7 +++++ libraries/entities/src/EntityTreeElement.h | 1 + libraries/octree/src/OctreeRenderer.cpp | 3 ++ 9 files changed, 34 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af707acf57..3242d981ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,4 +181,4 @@ endif () if (ANDROID OR DESKTOP_GVR) add_subdirectory(gvr-interface) -endif () \ No newline at end of file +endif () diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 82b9825a56..1a7d9c8ca7 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -48,6 +48,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf _displayModelElementProxy(false), _dontDoPrecisionPicking(false) { + std::cout << "adebug " << (void*)(this) << " EntityTreeRenderer ctor" << std::endl; // adebug REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory) @@ -480,7 +481,6 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg maxCube.scale((float) TREE_SCALE); minCube.scale((float) TREE_SCALE); - entityBox.scale((float) TREE_SCALE); glm::vec3 maxCenter = maxCube.calcCenter(); glm::vec3 minCenter = minCube.calcCenter(); @@ -672,10 +672,16 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons (void**)&intersectedEntity, lockType, &result.accurate, precisionPicking); if (result.intersects && intersectedEntity) { + std::cout << "adebug " << (void*)(this) << " EntityTreeRenderer's tree = " << (void*)(_tree) << std::endl; // adebug + int foo = 0; result.entityID = intersectedEntity->getEntityItemID(); + foo = 1; result.properties = intersectedEntity->getProperties(); + foo = 2; result.intersection = ray.origin + (ray.direction * result.distance); + foo = 3; result.entity = intersectedEntity; + std::cout << "adebug foo = " << foo << std::endl; // adebug } } return result; diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index 1e8c811122..5256877b44 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -41,6 +41,7 @@ EntityItemProperties BoxEntityItem::getProperties() const { properties._glowLevel = getGlowLevel(); properties._glowLevelChanged = false; + std::cout << "adebug end of BoxEntityItem::getProperties()" << std::endl; // adebug return properties; } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 12eaeff62f..b6381f196d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -795,6 +795,7 @@ quint64 EntityItem::getExpiry() const { } EntityItemProperties EntityItem::getProperties() const { + std::cout << "adebug EntityItem::getProperties" << std::endl; // adebug EntityItemProperties properties; properties._id = getID(); properties._idSet = true; @@ -824,6 +825,7 @@ EntityItemProperties EntityItem::getProperties() const { properties._defaultSettings = false; + std::cout << "adebug about to delete properties" << std::endl; // adebug return properties; } @@ -1017,31 +1019,27 @@ const float MIN_SPIN_DELTA = 0.0003f; void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) { glm::vec3 position = value * (float)TREE_SCALE; - if (glm::distance(_position, position) > MIN_POSITION_DELTA) { - _position = position; - _dirtyFlags |= EntityItem::DIRTY_POSITION; - } + updatePositionInMeters(position); } void EntityItem::updatePositionInMeters(const glm::vec3& value) { if (glm::distance(_position, value) > MIN_POSITION_DELTA) { _position = value; _dirtyFlags |= EntityItem::DIRTY_POSITION; + std::cout << "adebug updatePositionInMeters = " << _position << std::endl; // adebug } } void EntityItem::updateDimensionsInDomainUnits(const glm::vec3& value) { glm::vec3 dimensions = value * (float)TREE_SCALE; - if (glm::distance(_dimensions, dimensions) > MIN_DIMENSIONS_DELTA) { - _dimensions = glm::abs(dimensions); - _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); - } + updateDimensionsInMeters(dimensions); } void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { if (glm::distance(_dimensions, value) > MIN_DIMENSIONS_DELTA) { _dimensions = value; _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); + std::cout << "adebug updateDimensionsInMeters = " << value << std::endl; // adebug } } @@ -1078,14 +1076,7 @@ void EntityItem::updateMass(float mass) { void EntityItem::updateVelocityInDomainUnits(const glm::vec3& value) { glm::vec3 velocity = value * (float)TREE_SCALE; - if (glm::distance(_velocity, velocity) > MIN_VELOCITY_DELTA) { - if (glm::length(velocity) < MIN_VELOCITY_DELTA) { - _velocity = ENTITY_ITEM_ZERO_VEC3; - } else { - _velocity = velocity; - } - _dirtyFlags |= EntityItem::DIRTY_VELOCITY; - } + updateVelocityInMeters(velocity); } void EntityItem::updateVelocityInMeters(const glm::vec3& value) { @@ -1108,10 +1099,7 @@ void EntityItem::updateDamping(float value) { void EntityItem::updateGravityInDomainUnits(const glm::vec3& value) { glm::vec3 gravity = value * (float) TREE_SCALE; - if (glm::distance(_gravity, gravity) > MIN_GRAVITY_DELTA) { - _gravity = gravity; - _dirtyFlags |= EntityItem::DIRTY_VELOCITY; - } + updateGravityInMeters(gravity); } void EntityItem::updateGravityInMeters(const glm::vec3& value) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ad20ca66e4..a494831317 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -22,6 +22,7 @@ #include <OctreeElement.h> // for OctreeElement::AppendState #include <OctreePacketData.h> #include <ShapeInfo.h> +#include <StreamUtils.h> // adebug #include "EntityItemID.h" #include "EntityItemProperties.h" @@ -151,14 +152,16 @@ public: /// set position in domain scale units (0.0 - 1.0) void setPositionInDomainUnits(const glm::vec3& value) { setPositionInMeters(glm::clamp(value, 0.0f, 1.0f) * (float)TREE_SCALE); } - void setPositionInMeters(const glm::vec3& value) { _position = value; } + void setPositionInMeters(const glm::vec3& value) { + _position = value; + std::cout << "adebug setPosition = " << _position << std::endl; // adebug + } glm::vec3 getCenterInDomainUnits() const { return getCenterInMeters() / (float) TREE_SCALE; } glm::vec3 getCenterInMeters() const; glm::vec3 getDimensionsInDomainUnits() const { return _dimensions / (float)TREE_SCALE; } /// get dimensions in domain scale units (0.0 - 1.0) const glm::vec3& getDimensionsInMeters() const { return _dimensions; } /// get dimensions in meters - float getLargestDimensionInDomainUnits() const { return glm::length(_dimensions); } /// get the largest possible dimension /// set dimensions in domain scale units (0.0 - 1.0) virtual void setDimensionsInDomainUnits(const glm::vec3& value) { _dimensions = glm::abs(value) * (float)TREE_SCALE; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index e53a6ede3d..c6414f620b 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -80,6 +80,7 @@ EntityItemProperties::EntityItemProperties() : } EntityItemProperties::~EntityItemProperties() { + std::cout << "adebug delete properties" << std::endl; // adebug } void EntityItemProperties::setSittingPoints(const QVector<SittingPoint>& sittingPoints) { diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index f746a03054..e32434b4c6 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -22,9 +22,15 @@ EntityTreeElement::EntityTreeElement(unsigned char* octalCode) : OctreeElement() }; EntityTreeElement::~EntityTreeElement() { + int bar = 0; _octreeMemoryUsage -= sizeof(EntityTreeElement); + bar = 1; + std::cout << "adebug EntityTreeElement " << (void*)(this) << " deletes old entityItems = " << (void*)(_entityItems) << std::endl; // adebug delete _entityItems; + bar = 2; _entityItems = NULL; + bar = 3; + std::cout << "adebug bar = " << bar << std::endl; // adebug } // This will be called primarily on addChildAt(), which means we're adding a child of our @@ -39,6 +45,7 @@ OctreeElement* EntityTreeElement::createNewElement(unsigned char* octalCode) { void EntityTreeElement::init(unsigned char* octalCode) { OctreeElement::init(octalCode); _entityItems = new QList<EntityItem*>; + std::cout << "adebug EntityTreeElement " << (void*)(this) << " gets new entityItems = " << (void*)(_entityItems) << std::endl; // adebug _octreeMemoryUsage += sizeof(EntityTreeElement); } diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index 424e3ca520..ad91010b0b 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -73,6 +73,7 @@ public: class EntityTreeElement : public OctreeElement { friend class EntityTree; // to allow createElement to new us... + EntityTreeElement(); EntityTreeElement(unsigned char* octalCode = NULL); virtual OctreeElement* createNewElement(unsigned char* octalCode = NULL); diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 187f916d35..c4ccd98036 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -22,11 +22,13 @@ OctreeRenderer::OctreeRenderer() : _managedTree(false), _viewFrustum(NULL) { + std::cout << "adebug " << (void*)(this) << " OctreeRenderer() _tree = " << (void*)(_tree) << std::endl; // adebug } void OctreeRenderer::init() { if (!_tree) { _tree = createTree(); + std::cout << "adebug " << (void*)(this) << " init _tree = " << (void*)(_tree) << std::endl; // adebug _managedTree = true; } } @@ -43,6 +45,7 @@ void OctreeRenderer::setTree(Octree* newTree) { _managedTree = false; } _tree = newTree; + std::cout << "adebug " << (void*)(this) << " setTree() _tree = " << (void*)(_tree) << std::endl; // adebug } void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { From ffab6ffe489ae6b2853c499c5830fc1348e9dc36 Mon Sep 17 00:00:00 2001 From: ZappoMan <bradh@konamoxt.com> Date: Fri, 6 Mar 2015 15:11:02 -0800 Subject: [PATCH 37/56] tweaks to hacks for detecting mixamo files --- interface/src/ModelUploader.cpp | 14 ++++++++++++-- libraries/fbx/src/FBXReader.cpp | 3 +++ libraries/fbx/src/FBXReader.h | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index ad73d119a3..a2b729ad39 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -311,8 +311,18 @@ void ModelUploader::populateBasicMapping(QVariantHash& mapping, QString filename mapping.insertMulti(FREE_JOINT_FIELD, "RightForeArm"); } - // mixamo blendshapes - if (!mapping.contains(BLENDSHAPE_FIELD) && geometry.applicationName == "mixamo.com") { + // mixamo blendshapes - in the event that a mixamo file was edited by some other tool, it's likely the applicationName will + // be rewritten, so we detect the existence of several different blendshapes which indicate we're likely a mixamo file + bool likelyMixamoFile = geometry.applicationName == "mixamo.com" || + (geometry.blendshapeChannelNames.contains("BrowsDown_Left") && + geometry.blendshapeChannelNames.contains("BrowsDown_Right") && + geometry.blendshapeChannelNames.contains("MouthOpen") && + geometry.blendshapeChannelNames.contains("TongueUp") && + geometry.blendshapeChannelNames.contains("MouthWhistle_NarrowAdjust_Left") && + geometry.blendshapeChannelNames.contains("NoseScrunch_Left") && + geometry.blendshapeChannelNames.contains("Squint_Right")); + + if (!mapping.contains(BLENDSHAPE_FIELD) && likelyMixamoFile) { QVariantHash blendshapes; blendshapes.insertMulti("BrowsD_L", QVariantList() << "BrowsDown_Left" << 1.0); blendshapes.insertMulti("BrowsD_R", QVariantList() << "BrowsDown_Right" << 1.0); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 72d153289a..cbbaae3d82 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1266,6 +1266,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QVector<QString> humanIKJointIDs(humanIKJointNames.size()); QVariantHash blendshapeMappings = mapping.value("bs").toHash(); + QMultiHash<QByteArray, WeightedIndex> blendshapeIndices; for (int i = 0;; i++) { QByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i]; @@ -1720,12 +1721,14 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (object.properties.last() == "BlendShapeChannel") { QByteArray name = object.properties.at(1).toByteArray(); + name = name.left(name.indexOf('\0')); if (!blendshapeIndices.contains(name)) { // try everything after the dot name = name.mid(name.lastIndexOf('.') + 1); } QString id = getID(object.properties); + geometry.blendshapeChannelNames << name; foreach (const WeightedIndex& index, blendshapeIndices.values(name)) { blendshapeChannelIndices.insert(id, index); } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3f6f836950..6912dd730f 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -257,6 +257,8 @@ public: /// given a meshIndex this will return the name of the model that mesh belongs to if known QString getModelNameOfMesh(int meshIndex) const; + + QList<QString> blendshapeChannelNames; }; Q_DECLARE_METATYPE(FBXGeometry) From 7c78e598b84c1cae1f7d346498effd2a83258ffb Mon Sep 17 00:00:00 2001 From: Grayson Stebbins <g@graysonstebbins.com> Date: Fri, 6 Mar 2015 15:15:48 -0800 Subject: [PATCH 38/56] Update to .com instead of .io in Welcome dialog --- interface/resources/html/interface-welcome.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/html/interface-welcome.html b/interface/resources/html/interface-welcome.html index d632cb0e5c..ed905eb392 100644 --- a/interface/resources/html/interface-welcome.html +++ b/interface/resources/html/interface-welcome.html @@ -154,7 +154,7 @@ devour all we've written and make<br> suggestions where necessary.<br> Documentation is always at<br> - <a href="http://docs.highfidelity.io/"><b>docs.highfidelity.io</b></a> + <a href="http://docs.highfidelity.com/"><b>docs.highfidelity.com</b></a> </p> </div> <div class="grid-unit padding-block"></div> @@ -187,4 +187,4 @@ } </script> -</html> \ No newline at end of file +</html> From a4963f18953a974a72148c39385b1b55c0b78336 Mon Sep 17 00:00:00 2001 From: Stephen Birarda <commit@birarda.com> Date: Fri, 6 Mar 2015 15:22:25 -0800 Subject: [PATCH 39/56] render application overlay only if enabled --- interface/src/Application.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6484e364bc..5aff8f0310 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -772,13 +772,10 @@ void Application::paintGL() { DependencyManager::get<GlowEffect>()->render(); - { + if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { PerformanceTimer perfTimer("renderOverlay"); - // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() _applicationOverlay.renderOverlay(true); - if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { - _applicationOverlay.displayOverlayTexture(); - } + _applicationOverlay.displayOverlayTexture(); } } From 6fa1b1c6007d4dcd8eb10f8323414d10a6e2bf9a Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Fri, 6 Mar 2015 15:31:27 -0800 Subject: [PATCH 40/56] remove unused cruft and fix float casts --- libraries/shared/src/OctalCode.cpp | 15 ++++----------- libraries/shared/src/OctalCode.h | 3 --- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/libraries/shared/src/OctalCode.cpp b/libraries/shared/src/OctalCode.cpp index 82bd471975..f26f103487 100644 --- a/libraries/shared/src/OctalCode.cpp +++ b/libraries/shared/src/OctalCode.cpp @@ -129,18 +129,17 @@ unsigned char* childOctalCode(const unsigned char* parentOctalCode, char childNu void voxelDetailsForCode(const unsigned char* octalCode, VoxelPositionSize& voxelPositionSize) { float output[3]; memset(&output[0], 0, 3 * sizeof(float)); - float currentScale = 1.0; + float currentScale = 1.0f; if (octalCode) { for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { - currentScale *= 0.5; + currentScale *= 0.5f; int sectionIndex = sectionValue(octalCode + 1 + (BITS_IN_OCTAL * i / BITS_IN_BYTE), (BITS_IN_OCTAL * i) % BITS_IN_BYTE); for (int j = 0; j < BITS_IN_OCTAL; j++) { - output[j] += currentScale * (int)oneAtBit(sectionIndex, (BITS_IN_BYTE - BITS_IN_OCTAL) + j); + output[j] += currentScale * (float)oneAtBit(sectionIndex, (BITS_IN_BYTE - BITS_IN_OCTAL) + j); } - } } voxelPositionSize.x = output[0]; @@ -152,7 +151,7 @@ void voxelDetailsForCode(const unsigned char* octalCode, VoxelPositionSize& voxe void copyFirstVertexForCode(const unsigned char* octalCode, float* output) { memset(output, 0, 3 * sizeof(float)); - float currentScale = 0.5; + float currentScale = 0.5f; for (int i = 0; i < numberOfThreeBitSectionsInCode(octalCode); i++) { int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8); @@ -165,12 +164,6 @@ void copyFirstVertexForCode(const unsigned char* octalCode, float* output) { } } -float * firstVertexForCode(const unsigned char* octalCode) { - float * firstVertex = new float[3]; - copyFirstVertexForCode(octalCode, firstVertex); - return firstVertex; -} - OctalCodeComparison compareOctalCodes(const unsigned char* codeA, const unsigned char* codeB) { if (!codeA || !codeB) { return ILLEGAL_CODE; diff --git a/libraries/shared/src/OctalCode.h b/libraries/shared/src/OctalCode.h index 07895ff67f..9229157c3d 100644 --- a/libraries/shared/src/OctalCode.h +++ b/libraries/shared/src/OctalCode.h @@ -43,9 +43,6 @@ const int CHECK_NODE_ONLY = -1; bool isAncestorOf(const unsigned char* possibleAncestor, const unsigned char* possibleDescendent, int descendentsChild = CHECK_NODE_ONLY); -// Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return -// but other than that these do the same thing. -float * firstVertexForCode(const unsigned char* octalCode); void copyFirstVertexForCode(const unsigned char* octalCode, float* output); struct VoxelPositionSize { From 6936d65db9d6b4b046d293aa1caba2bc4ffa4632 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Fri, 6 Mar 2015 15:31:52 -0800 Subject: [PATCH 41/56] remove unused *= operator for AABox --- libraries/shared/src/AABox.cpp | 6 ------ libraries/shared/src/AABox.h | 2 -- 2 files changed, 8 deletions(-) diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index cf02720976..6cb361a4a3 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -485,9 +485,3 @@ AABox& AABox::operator += (const AABox& box) { } return (*this); } - -AABox& AABox::operator *= (float multiplier) { - _corner *= multiplier; - _scale *= multiplier; - return (*this); -} diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index 71c1cf0650..9beb0a85f2 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -75,8 +75,6 @@ public: AABox& operator += (const glm::vec3& point); AABox& operator += (const AABox& box); - AABox& operator *= (float multiplier); - bool isInvalid() const { return _corner == glm::vec3(std::numeric_limits<float>::infinity()); } private: From 373be9529760f7edf9ff42218671cb898da87658 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Fri, 6 Mar 2015 15:32:03 -0800 Subject: [PATCH 42/56] entity cubes are in meters --- interface/src/Application.cpp | 2 - interface/src/avatar/ModelReferential.cpp | 26 +++---- interface/src/octree/OctreeFade.cpp | 2 +- interface/src/ui/NodeBounds.cpp | 7 +- interface/src/ui/OctreeStatsDialog.cpp | 1 - .../src/EntityTreeRenderer.cpp | 28 +++---- .../src/RenderableBoxEntityItem.cpp | 6 +- .../src/RenderableLightEntityItem.cpp | 6 +- .../src/RenderableLightEntityItem.h | 2 +- .../src/RenderableModelEntityItem.cpp | 8 +- .../src/RenderableModelEntityItem.h | 2 +- .../src/RenderableSphereEntityItem.cpp | 6 +- .../src/RenderableTextEntityItem.cpp | 4 +- libraries/entities/src/AddEntityOperator.cpp | 4 +- libraries/entities/src/BoxEntityItem.cpp | 1 - .../entities/src/DeleteEntityOperator.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 76 +++++++++---------- libraries/entities/src/EntityItem.h | 40 +++++----- .../entities/src/EntityItemProperties.cpp | 13 +--- libraries/entities/src/EntityItemProperties.h | 5 +- .../entities/src/EntityScriptingInterface.cpp | 2 +- libraries/entities/src/EntitySimulation.cpp | 4 +- libraries/entities/src/EntityTree.cpp | 18 ++--- libraries/entities/src/EntityTree.h | 2 +- libraries/entities/src/EntityTreeElement.cpp | 52 +++++-------- libraries/entities/src/EntityTreeElement.h | 3 +- libraries/entities/src/ModelEntityItem.cpp | 4 +- .../entities/src/MovingEntitiesOperator.cpp | 4 +- .../entities/src/MovingEntitiesOperator.h | 8 +- libraries/entities/src/SphereEntityItem.cpp | 6 +- libraries/entities/src/SphereEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 10 +-- libraries/entities/src/TextEntityItem.h | 4 +- .../entities/src/UpdateEntityOperator.cpp | 14 ++-- libraries/octree/src/Octree.cpp | 29 +++---- libraries/octree/src/Octree.h | 8 ++ libraries/octree/src/OctreeElement.cpp | 39 ++++------ libraries/octree/src/OctreeHeadlessViewer.cpp | 2 - libraries/octree/src/OctreeRenderer.cpp | 3 - libraries/physics/src/EntityMotionState.cpp | 12 +-- tests/octree/src/ModelTests.cpp | 40 +++++----- 41 files changed, 221 insertions(+), 286 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fea6a1fb73..49ac272b35 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2262,7 +2262,6 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); - serverBounds.scale(TREE_SCALE); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); @@ -2326,7 +2325,6 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); - serverBounds.scale(TREE_SCALE); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index beb378403d..b8acf78cd3 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -31,9 +31,9 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); if (item != NULL) { - _lastRefDimension = item->getDimensionsInMeters(); + _lastRefDimension = item->getDimensions(); _refRotation = item->getRotation(); - _refPosition = item->getPositionInMeters(); + _refPosition = item->getPosition(); update(); } } @@ -50,9 +50,9 @@ ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, Avat return; } - _lastRefDimension = item->getDimensionsInMeters(); + _lastRefDimension = item->getDimensions(); _refRotation = item->getRotation(); - _refPosition = item->getPositionInMeters(); + _refPosition = item->getPosition(); glm::quat refInvRot = glm::inverse(_refRotation); _rotation = refInvRot * _avatar->getOrientation(); @@ -66,9 +66,9 @@ void ModelReferential::update() { } bool somethingChanged = false; - if (item->getDimensionsInMeters() != _lastRefDimension) { + if (item->getDimensions() != _lastRefDimension) { glm::vec3 oldDimension = _lastRefDimension; - _lastRefDimension = item->getDimensionsInMeters(); + _lastRefDimension = item->getDimensions(); _translation *= _lastRefDimension / oldDimension; somethingChanged = true; } @@ -77,8 +77,8 @@ void ModelReferential::update() { _avatar->setOrientation(_refRotation * _rotation, true); somethingChanged = true; } - if (item->getPositionInMeters() != _refPosition || somethingChanged) { - _refPosition = item->getPositionInMeters(); + if (item->getPosition() != _refPosition || somethingChanged) { + _refPosition = item->getPosition(); _avatar->setPosition(_refPosition + _refRotation * _translation, true); } } @@ -107,7 +107,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) { - _lastRefDimension = item->getDimensionsInMeters(); + _lastRefDimension = item->getDimensions(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); } @@ -127,7 +127,7 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E return; } - _lastRefDimension = item->getDimensionsInMeters(); + _lastRefDimension = item->getDimensions(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); @@ -145,9 +145,9 @@ void JointReferential::update() { } bool somethingChanged = false; - if (item->getDimensionsInMeters() != _lastRefDimension) { + if (item->getDimensions() != _lastRefDimension) { glm::vec3 oldDimension = _lastRefDimension; - _lastRefDimension = item->getDimensionsInMeters(); + _lastRefDimension = item->getDimensions(); _translation *= _lastRefDimension / oldDimension; somethingChanged = true; } @@ -156,7 +156,7 @@ void JointReferential::update() { _avatar->setOrientation(_refRotation * _rotation, true); somethingChanged = true; } - if (item->getPositionInMeters() != _refPosition || somethingChanged) { + if (item->getPosition() != _refPosition || somethingChanged) { model->getJointPositionInWorldFrame(_jointIndex, _refPosition); _avatar->setPosition(_refPosition + _refRotation * _translation, true); } diff --git a/interface/src/octree/OctreeFade.cpp b/interface/src/octree/OctreeFade.cpp index 917bb67124..ad313bdb6d 100644 --- a/interface/src/octree/OctreeFade.cpp +++ b/interface/src/octree/OctreeFade.cpp @@ -42,7 +42,7 @@ void OctreeFade::render() { glDisable(GL_LIGHTING); glPushMatrix(); - glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); + glScalef(1.0f, 1.0f, 1.0f); glTranslatef(voxelDetails.x + voxelDetails.s * 0.5f, voxelDetails.y + voxelDetails.s * 0.5f, voxelDetails.z + voxelDetails.s * 0.5f); diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index 85cbf72953..f0f4d432db 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -71,20 +71,19 @@ void NodeBounds::draw() { voxelDetailsForCode(rootCode, rootDetails); serverJurisdictions->unlock(); glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z); - location *= (float)TREE_SCALE; - AACube serverBounds(location, rootDetails.s * TREE_SCALE); + AACube serverBounds(location, rootDetails.s); glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR) + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f); const float ENTITY_NODE_SCALE = 0.99f; - float scaleFactor = rootDetails.s * TREE_SCALE; + float scaleFactor = rootDetails.s; // Scale by 0.92 - 1.00 depending on the scale of the node. This allows smaller nodes to scale in // a bit and not overlap larger nodes. - scaleFactor *= 0.92 + (rootDetails.s * 0.08); + scaleFactor *= 0.92f + (rootDetails.s * 0.08f); // Scale different node types slightly differently because it's common for them to overlap. if (nodeType == NodeType::EntityServer) { diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index d9c8124180..462811fc1c 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -273,7 +273,6 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); - serverBounds.scale(TREE_SCALE); serverDetails << " jurisdiction: " << qPrintable(rootCodeHex) << " [" diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 1a7d9c8ca7..ebc79250cc 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -48,7 +48,6 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf _displayModelElementProxy(false), _dontDoPrecisionPicking(false) { - std::cout << "adebug " << (void*)(this) << " EntityTreeRenderer ctor" << std::endl; // adebug REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory) @@ -285,11 +284,11 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { QVector<EntityItemID> entitiesContainingAvatar; // find the entities near us - static_cast<EntityTree*>(_tree)->findEntitiesInMeters(avatarPosition, radius, foundEntities); + static_cast<EntityTree*>(_tree)->findEntities(avatarPosition, radius, foundEntities); // create a list of entities that actually contain the avatar's position foreach(const EntityItem* entity, foundEntities) { - if (entity->containsInMeters(avatarPosition)) { + if (entity->contains(avatarPosition)) { entitiesContainingAvatar << entity->getEntityItemID(); } } @@ -417,8 +416,8 @@ const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityI } void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement) { - glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter() * (float) TREE_SCALE; - float elementSize = entityTreeElement->getScale() * (float) TREE_SCALE; + glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter(); + float elementSize = entityTreeElement->getScale(); glPushMatrix(); glTranslatef(elementCenter.x, elementCenter.y, elementCenter.z); DependencyManager::get<DeferredLightingEffect>()->renderWireCube(elementSize, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); @@ -477,10 +476,7 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg AACube maxCube = entity->getMaximumAACube(); AACube minCube = entity->getMinimumAACube(); - AABox entityBox = entity->getAABoxInMeters(); - - maxCube.scale((float) TREE_SCALE); - minCube.scale((float) TREE_SCALE); + AABox entityBox = entity->getAABox(); glm::vec3 maxCenter = maxCube.calcCenter(); glm::vec3 minCenter = minCube.calcCenter(); @@ -507,9 +503,9 @@ void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* arg glPopMatrix(); - glm::vec3 position = entity->getPositionInMeters(); - glm::vec3 center = entity->getCenterInMeters(); - glm::vec3 dimensions = entity->getDimensionsInMeters(); + glm::vec3 position = entity->getPosition(); + glm::vec3 center = entity->getCenter(); + glm::vec3 dimensions = entity->getDimensions(); glm::quat rotation = entity->getRotation(); glPushMatrix(); @@ -548,7 +544,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) if (entityItem->isVisible()) { // render entityItem - AABox entityBox = entityItem->getAABoxInMeters(); + AABox entityBox = entityItem->getAABox(); // TODO: some entity types (like lights) might want to be rendered even // when they are outside of the view frustum... @@ -672,16 +668,10 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons (void**)&intersectedEntity, lockType, &result.accurate, precisionPicking); if (result.intersects && intersectedEntity) { - std::cout << "adebug " << (void*)(this) << " EntityTreeRenderer's tree = " << (void*)(_tree) << std::endl; // adebug - int foo = 0; result.entityID = intersectedEntity->getEntityItemID(); - foo = 1; result.properties = intersectedEntity->getProperties(); - foo = 2; result.intersection = ray.origin + (ray.direction * result.distance); - foo = 3; result.entity = intersectedEntity; - std::cout << "adebug foo = " << foo << std::endl; // adebug } } return result; diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index a80fc91995..f7828806ab 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -25,9 +25,9 @@ EntityItem* RenderableBoxEntityItem::factory(const EntityItemID& entityID, const void RenderableBoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); assert(getType() == EntityTypes::Box); - glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); - glm::vec3 dimensions = getDimensionsInMeters(); + glm::vec3 position = getPosition(); + glm::vec3 center = getCenter(); + glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); const float MAX_COLOR = 255.0f; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 5889e6b34a..838c9fd8c4 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -26,8 +26,8 @@ EntityItem* RenderableLightEntityItem::factory(const EntityItemID& entityID, con void RenderableLightEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLightEntityItem::render"); assert(getType() == EntityTypes::Light); - glm::vec3 position = getPositionInMeters(); - glm::vec3 dimensions = getDimensionsInMeters(); + glm::vec3 position = getPosition(); + glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); @@ -67,7 +67,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { #endif }; -bool RenderableLightEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, +bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index 1ea3e7e884..cfafb85983 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -24,7 +24,7 @@ public: virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 6c1d24b845..75c9f07881 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -114,8 +114,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) { bool drawAsModel = hasModel(); - glm::vec3 position = getPositionInMeters(); - glm::vec3 dimensions = getDimensionsInMeters(); + glm::vec3 position = getPosition(); + glm::vec3 dimensions = getDimensions(); float size = glm::length(dimensions); if (drawAsModel) { @@ -254,13 +254,13 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { return properties; } -bool RenderableModelEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, +bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { if (!_model) { return true; } - //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersectionInMeters() precisionPicking:" << precisionPicking; + //qDebug() << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; QString extraInfo; return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 7e20b0bd15..65cded0207 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -44,7 +44,7 @@ public: virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index 4688e7cc29..083a34c02f 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -26,9 +26,9 @@ EntityItem* RenderableSphereEntityItem::factory(const EntityItemID& entityID, co void RenderableSphereEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableSphereEntityItem::render"); assert(getType() == EntityTypes::Sphere); - glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); - glm::vec3 dimensions = getDimensionsInMeters(); + glm::vec3 position = getPosition(); + glm::vec3 center = getCenter(); + glm::vec3 dimensions = getDimensions(); glm::quat rotation = getRotation(); const float MAX_COLOR = 255.0f; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 097aef3b38..3586a8c8c5 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -30,8 +30,8 @@ EntityItem* RenderableTextEntityItem::factory(const EntityItemID& entityID, cons void RenderableTextEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableTextEntityItem::render"); assert(getType() == EntityTypes::Text); - glm::vec3 position = getPositionInMeters(); - glm::vec3 dimensions = getDimensionsInMeters(); + glm::vec3 position = getPosition(); + glm::vec3 dimensions = getDimensions(); glm::vec3 halfDimensions = dimensions / 2.0f; glm::quat rotation = getRotation(); float leftMargin = 0.1f; diff --git a/libraries/entities/src/AddEntityOperator.cpp b/libraries/entities/src/AddEntityOperator.cpp index 34ccc75030..0844a10ede 100644 --- a/libraries/entities/src/AddEntityOperator.cpp +++ b/libraries/entities/src/AddEntityOperator.cpp @@ -25,7 +25,7 @@ AddEntityOperator::AddEntityOperator(EntityTree* tree, { // caller must have verified existence of newEntity assert(_newEntity); - _newEntityBox = _newEntity->getMaximumAACube().clamp(0.0f, 1.0f); + _newEntityBox = _newEntity->getMaximumAACube().clamp(0.0f, (float)TREE_SCALE); } bool AddEntityOperator::preRecursion(OctreeElement* element) { @@ -43,7 +43,7 @@ bool AddEntityOperator::preRecursion(OctreeElement* element) { if (!_foundNew && element->getAACube().contains(_newEntityBox)) { // If this element is the best fit for the new entity properties, then add/or update it - if (entityTreeElement->bestFitBounds(_newEntityBox)) { + if (entityTreeElement->bestFitBoundsInMeters(_newEntityBox)) { entityTreeElement->addEntityItem(_newEntity); _tree->setContainingElement(_newEntity->getEntityItemID(), entityTreeElement); diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index 5256877b44..1e8c811122 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -41,7 +41,6 @@ EntityItemProperties BoxEntityItem::getProperties() const { properties._glowLevel = getGlowLevel(); properties._glowLevelChanged = false; - std::cout << "adebug end of BoxEntityItem::getProperties()" << std::endl; // adebug return properties; } diff --git a/libraries/entities/src/DeleteEntityOperator.cpp b/libraries/entities/src/DeleteEntityOperator.cpp index 698ef18936..d17e1c66d6 100644 --- a/libraries/entities/src/DeleteEntityOperator.cpp +++ b/libraries/entities/src/DeleteEntityOperator.cpp @@ -60,7 +60,7 @@ bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElement* el // If we don't have an old entity, then we don't contain the entity, otherwise // check the bounds if (_entitiesToDelete.size() > 0) { - AACube elementCube = element->getAACube(); + const AACube& elementCube = element->getAACube(); foreach(const EntityToDeleteDetails& details, _entitiesToDelete) { if (elementCube.contains(details.cube)) { containsEntity = true; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index b6381f196d..5a1712a1f6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -221,12 +221,12 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet // PROP_PAGED_PROPERTY, // PROP_CUSTOM_PROPERTIES_INCLUDED, - APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPositionInMeters()); - APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensionsInMeters()); // NOTE: PROP_RADIUS obsolete + APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition()); + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation()); APPEND_ENTITY_PROPERTY(PROP_DENSITY, appendValue, getDensity()); - APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocityInMeters()); - APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravityInMeters()); + APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity()); + APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); @@ -503,7 +503,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef bytesRead += propertyFlags.getEncodedLength(); bool useMeters = (args.bitstreamVersion == VERSION_ENTITIES_USE_METERS); if (useMeters) { - READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePositionInMeters); + READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePosition); } else { READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePositionInDomainUnits); } @@ -521,7 +521,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } } else { if (useMeters) { - READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensionsInMeters); + READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensions); } else { READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensionsInDomainUnits); } @@ -530,8 +530,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation); READ_ENTITY_PROPERTY_SETTER(PROP_DENSITY, float, updateDensity); if (useMeters) { - READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocityInMeters); - READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravityInMeters); + READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocity); + READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravity); } else { READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits); READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits); @@ -726,7 +726,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { if (hasVelocity()) { // linear damping - glm::vec3 velocity = getVelocityInMeters(); + glm::vec3 velocity = getVelocity(); if (_damping > 0.0f) { velocity *= powf(1.0f - _damping, timeElapsed); #ifdef WANT_DEBUG @@ -738,7 +738,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { } // integrate position forward - glm::vec3 position = getPositionInMeters(); + glm::vec3 position = getPosition(); glm::vec3 newPosition = position + (velocity * timeElapsed); #ifdef WANT_DEBUG @@ -758,19 +758,19 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { if (hasGravity()) { // handle resting on surface case, this is definitely a bit of a hack, and it only works on the // "ground" plane of the domain, but for now it's what we've got - velocity += getGravityInMeters() * timeElapsed; + velocity += getGravity() * timeElapsed; } float speed = glm::length(velocity); const float EPSILON_LINEAR_VELOCITY_LENGTH = 0.001f; // 1mm/sec if (speed < EPSILON_LINEAR_VELOCITY_LENGTH) { - setVelocityInMeters(ENTITY_ITEM_ZERO_VEC3); + setVelocity(ENTITY_ITEM_ZERO_VEC3); if (speed > 0.0f) { _dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE; } } else { - setPositionInMeters(position); - setVelocityInMeters(velocity); + setPosition(position); + setVelocity(velocity); } #ifdef WANT_DEBUG @@ -795,7 +795,6 @@ quint64 EntityItem::getExpiry() const { } EntityItemProperties EntityItem::getProperties() const { - std::cout << "adebug EntityItem::getProperties" << std::endl; // adebug EntityItemProperties properties; properties._id = getID(); properties._idSet = true; @@ -803,12 +802,12 @@ EntityItemProperties EntityItem::getProperties() const { properties._type = getType(); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getPositionInMeters); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensionsInMeters); // NOTE: radius is obsolete + COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getPosition); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensions); // NOTE: radius is obsolete COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getRotation); COPY_ENTITY_PROPERTY_TO_PROPERTIES(density, getDensity); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getVelocityInMeters); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(gravity, getGravityInMeters); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getVelocity); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(gravity, getGravity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(damping, getDamping); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifetime, getLifetime); COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript); @@ -825,19 +824,18 @@ EntityItemProperties EntityItem::getProperties() const { properties._defaultSettings = false; - std::cout << "adebug about to delete properties" << std::endl; // adebug return properties; } bool EntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; - SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePositionInMeters); // this will call recalculate collision shape if needed - SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensionsInMeters); // NOTE: radius is obsolete + SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePosition); // this will call recalculate collision shape if needed + SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensions); // NOTE: radius is obsolete SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation); SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, updateDensity); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocityInMeters); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravityInMeters); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, updateDamping); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime); SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript); @@ -900,7 +898,7 @@ void EntityItem::recordCreationTime() { // TODO: doesn't this need to handle rotation? -glm::vec3 EntityItem::getCenterInMeters() const { +glm::vec3 EntityItem::getCenter() const { return _position + (_dimensions * (glm::vec3(0.5f,0.5f,0.5f) - _registrationPoint)); } @@ -957,7 +955,7 @@ AACube EntityItem::getMinimumAACube() const { return AACube(cornerOfCube, longestSide); } -AABox EntityItem::getAABoxInMeters() const { +AABox EntityItem::getAABox() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; @@ -973,8 +971,8 @@ AABox EntityItem::getAABoxInMeters() const { } AABox EntityItem::getAABoxInDomainUnits() const { - AABox box = getAABoxInMeters(); - box *= 1.0f / (float)TREE_SCALE; + AABox box = getAABox(); + box.scale(1.0f / (float)TREE_SCALE); return box; } @@ -1001,12 +999,12 @@ void EntityItem::setRadius(float value) { // ... radius = cornerToCornerLength / 2.0f // ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) // ... radius = sqrt(3 x maxDimension ^ 2) / 2.0f; -float EntityItem::getRadiusInMeters() const { +float EntityItem::getRadius() const { return 0.5f * glm::length(_dimensions); } void EntityItem::computeShapeInfo(ShapeInfo& info) const { - info.setParams(getShapeType(), 0.5f * getDimensionsInMeters()); + info.setParams(getShapeType(), 0.5f * getDimensions()); } const float MIN_POSITION_DELTA = 0.0001f; @@ -1019,27 +1017,25 @@ const float MIN_SPIN_DELTA = 0.0003f; void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) { glm::vec3 position = value * (float)TREE_SCALE; - updatePositionInMeters(position); + updatePosition(position); } -void EntityItem::updatePositionInMeters(const glm::vec3& value) { +void EntityItem::updatePosition(const glm::vec3& value) { if (glm::distance(_position, value) > MIN_POSITION_DELTA) { _position = value; _dirtyFlags |= EntityItem::DIRTY_POSITION; - std::cout << "adebug updatePositionInMeters = " << _position << std::endl; // adebug } } void EntityItem::updateDimensionsInDomainUnits(const glm::vec3& value) { glm::vec3 dimensions = value * (float)TREE_SCALE; - updateDimensionsInMeters(dimensions); + updateDimensions(dimensions); } -void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { +void EntityItem::updateDimensions(const glm::vec3& value) { if (glm::distance(_dimensions, value) > MIN_DIMENSIONS_DELTA) { _dimensions = value; _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); - std::cout << "adebug updateDimensionsInMeters = " << value << std::endl; // adebug } } @@ -1076,10 +1072,10 @@ void EntityItem::updateMass(float mass) { void EntityItem::updateVelocityInDomainUnits(const glm::vec3& value) { glm::vec3 velocity = value * (float)TREE_SCALE; - updateVelocityInMeters(velocity); + updateVelocity(velocity); } -void EntityItem::updateVelocityInMeters(const glm::vec3& value) { +void EntityItem::updateVelocity(const glm::vec3& value) { if (glm::distance(_velocity, value) > MIN_VELOCITY_DELTA) { if (glm::length(value) < MIN_VELOCITY_DELTA) { _velocity = ENTITY_ITEM_ZERO_VEC3; @@ -1099,10 +1095,10 @@ void EntityItem::updateDamping(float value) { void EntityItem::updateGravityInDomainUnits(const glm::vec3& value) { glm::vec3 gravity = value * (float) TREE_SCALE; - updateGravityInMeters(gravity); + updateGravity(gravity); } -void EntityItem::updateGravityInMeters(const glm::vec3& value) { +void EntityItem::updateGravity(const glm::vec3& value) { if ( glm::distance(_gravity, value) > MIN_GRAVITY_DELTA) { _gravity = value; _dirtyFlags |= EntityItem::DIRTY_VELOCITY; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index a494831317..0f8139eea5 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -22,7 +22,6 @@ #include <OctreeElement.h> // for OctreeElement::AppendState #include <OctreePacketData.h> #include <ShapeInfo.h> -#include <StreamUtils.h> // adebug #include "EntityItemID.h" #include "EntityItemProperties.h" @@ -140,34 +139,33 @@ public: virtual void debugDump() const; virtual bool supportsDetailedRayIntersection() const { return false; } - virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return true; } // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } glm::vec3 getPositionInDomainUnits() const { return _position / (float)TREE_SCALE; } /// get position in domain scale units (0.0 - 1.0) - const glm::vec3& getPositionInMeters() const { return _position; } /// get position in meters + const glm::vec3& getPosition() const { return _position; } /// get position in meters /// set position in domain scale units (0.0 - 1.0) void setPositionInDomainUnits(const glm::vec3& value) - { setPositionInMeters(glm::clamp(value, 0.0f, 1.0f) * (float)TREE_SCALE); } - void setPositionInMeters(const glm::vec3& value) { + { setPosition(glm::clamp(value, 0.0f, 1.0f) * (float)TREE_SCALE); } + void setPosition(const glm::vec3& value) { _position = value; - std::cout << "adebug setPosition = " << _position << std::endl; // adebug } - glm::vec3 getCenterInDomainUnits() const { return getCenterInMeters() / (float) TREE_SCALE; } - glm::vec3 getCenterInMeters() const; + glm::vec3 getCenterInDomainUnits() const { return getCenter() / (float) TREE_SCALE; } + glm::vec3 getCenter() const; glm::vec3 getDimensionsInDomainUnits() const { return _dimensions / (float)TREE_SCALE; } /// get dimensions in domain scale units (0.0 - 1.0) - const glm::vec3& getDimensionsInMeters() const { return _dimensions; } /// get dimensions in meters + const glm::vec3& getDimensions() const { return _dimensions; } /// get dimensions in meters /// set dimensions in domain scale units (0.0 - 1.0) virtual void setDimensionsInDomainUnits(const glm::vec3& value) { _dimensions = glm::abs(value) * (float)TREE_SCALE; } /// set dimensions in meter units (0.0 - TREE_SCALE) - virtual void setDimensionsInMeters(const glm::vec3& value) { _dimensions = glm::abs(value); } + virtual void setDimensions(const glm::vec3& value) { _dimensions = glm::abs(value); } const glm::quat& getRotation() const { return _rotation; } void setRotation(const glm::quat& rotation) { _rotation = rotation; } @@ -185,15 +183,15 @@ public: float getDensity() const { return _density; } glm::vec3 getVelocityInDomainUnits() const { return _velocity / (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second - const glm::vec3 getVelocityInMeters() const { return _velocity; } /// get velocity in meters + const glm::vec3 getVelocity() const { return _velocity; } /// get velocity in meters void setVelocityInDomainUnits(const glm::vec3& value) { _velocity = value * (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second - void setVelocityInMeters(const glm::vec3& value) { _velocity = value; } /// velocity in meters + void setVelocity(const glm::vec3& value) { _velocity = value; } /// velocity in meters bool hasVelocity() const { return _velocity != ENTITY_ITEM_ZERO_VEC3; } glm::vec3 getGravityInDomainUnits() const { return _gravity / (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared - const glm::vec3& getGravityInMeters() const { return _gravity; } /// get gravity in meters + const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters void setGravityInDomainUnits(const glm::vec3& value) { _gravity = value * (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared - void setGravityInMeters(const glm::vec3& value) { _gravity = value; } /// gravity in meters + void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } float getDamping() const { return _damping; } @@ -217,7 +215,7 @@ public: // position, size, and bounds related helpers AACube getMaximumAACube() const; AACube getMinimumAACube() const; - AABox getAABoxInMeters() const; /// axis aligned bounding box in world-frame (meters) + AABox getAABox() const; /// axis aligned bounding box in world-frame (meters) AABox getAABoxInDomainUnits() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0) const QString& getScript() const { return _script; } @@ -254,9 +252,9 @@ public: void setUserData(const QString& value) { _userData = value; } // TODO: get rid of users of getRadius()... - float getRadiusInMeters() const; + float getRadius() const; - virtual bool containsInMeters(const glm::vec3& point) const { return getAABoxInMeters().contains(point); } + virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } virtual bool containsInDomainUnits(const glm::vec3& point) const { return getAABoxInDomainUnits().contains(point); } virtual void computeShapeInfo(ShapeInfo& info) const; @@ -265,17 +263,17 @@ public: // updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags void updatePositionInDomainUnits(const glm::vec3& value); - void updatePositionInMeters(const glm::vec3& value); + void updatePosition(const glm::vec3& value); void updateDimensionsInDomainUnits(const glm::vec3& value); - void updateDimensionsInMeters(const glm::vec3& value); + void updateDimensions(const glm::vec3& value); void updateRotation(const glm::quat& rotation); void updateDensity(float value); void updateMass(float value); void updateVelocityInDomainUnits(const glm::vec3& value); - void updateVelocityInMeters(const glm::vec3& value); + void updateVelocity(const glm::vec3& value); void updateDamping(float value); void updateGravityInDomainUnits(const glm::vec3& value); - void updateGravityInMeters(const glm::vec3& value); + void updateGravity(const glm::vec3& value); void updateAngularVelocity(const glm::vec3& value); void updateAngularDamping(float value); void updateIgnoreForCollisions(bool value); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index c6414f620b..53a39e1a99 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -80,7 +80,6 @@ EntityItemProperties::EntityItemProperties() : } EntityItemProperties::~EntityItemProperties() { - std::cout << "adebug delete properties" << std::endl; // adebug } void EntityItemProperties::setSittingPoints(const QVector<SittingPoint>& sittingPoints) { @@ -296,7 +295,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons sittingPoints.setProperty("length", _sittingPoints.size()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable - AABox aaBox = getAABoxInMeters(); + AABox aaBox = getAABox(); QScriptValue boundingBox = engine->newObject(); QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner()); QScriptValue topFarLeft = vec3toScriptValue(engine, aaBox.calcTopFarLeft()); @@ -821,16 +820,10 @@ void EntityItemProperties::markAllChanged() { _shapeTypeChanged = true; } -AACube EntityItemProperties::getMaximumAACubeInTreeUnits() const { - AACube maxCube = getMaximumAACubeInMeters(); - maxCube.scale(1.0f / (float)TREE_SCALE); - return maxCube; -} - /// The maximum bounding cube for the entity, independent of it's rotation. /// This accounts for the registration point (upon which rotation occurs around). /// -AACube EntityItemProperties::getMaximumAACubeInMeters() const { +AACube EntityItemProperties::getMaximumAACube() const { // * we know that the position is the center of rotation glm::vec3 centerOfRotation = _position; // also where _registration point is @@ -854,7 +847,7 @@ AACube EntityItemProperties::getMaximumAACubeInMeters() const { } // The minimum bounding box for the entity. -AABox EntityItemProperties::getAABoxInMeters() const { +AABox EntityItemProperties::getAABox() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9bf3c93c2b..bf10fd4c87 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -129,9 +129,8 @@ public: /// used by EntityScriptingInterface to return EntityItemProperties for unknown models void setIsUnknownID() { _id = UNKNOWN_ENTITY_ID; _idSet = true; } - AACube getMaximumAACubeInTreeUnits() const; - AACube getMaximumAACubeInMeters() const; - AABox getAABoxInMeters() const; + AACube getMaximumAACube() const; + AABox getAABox() const; void debugDump() const; void setLastEdited(quint64 usecTime); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 24bad08b6b..5ef0db57ec 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -206,7 +206,7 @@ QVector<EntityItemID> EntityScriptingInterface::findEntities(const glm::vec3& ce if (_entityTree) { _entityTree->lockForRead(); QVector<const EntityItem*> entities; - _entityTree->findEntitiesInMeters(center, radius, entities); + _entityTree->findEntities(center, radius, entities); _entityTree->unlock(); foreach (const EntityItem* entity, entities) { diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index f7d6c55803..758cd6771a 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -87,7 +87,7 @@ void EntitySimulation::sortEntitiesThatMoved() { // External changes to entity position/shape are expected to be sorted outside of the EntitySimulation. PerformanceTimer perfTimer("sortingEntities"); MovingEntitiesOperator moveOperator(_entityTree); - AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); + AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), (float)TREE_SCALE); QSet<EntityItem*>::iterator itemItr = _entitiesToBeSorted.begin(); while (itemItr != _entitiesToBeSorted.end()) { EntityItem* entity = *itemItr; @@ -150,7 +150,7 @@ void EntitySimulation::entityChanged(EntityItem* entity) { bool wasRemoved = false; uint32_t dirtyFlags = entity->getDirtyFlags(); if (dirtyFlags & EntityItem::DIRTY_POSITION) { - AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f); + AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), (float)TREE_SCALE); AACube newCube = entity->getMaximumAACube(); if (!domainBounds.touches(newCube)) { qDebug() << "Entity " << entity->getEntityItemID() << " moved out of domain bounds."; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 9e75615117..ba9a4c61e8 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -424,9 +424,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element); glm::vec3 penetration; - AACube cube = entityTreeElement->getAACube(); - cube.scale((float)TREE_SCALE); - bool sphereIntersection = cube.findSpherePenetration(args->position, args->targetRadius, penetration); + bool sphereIntersection = entityTreeElement->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); // If this entityTreeElement contains the point, then search it... if (sphereIntersection) { @@ -434,7 +432,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) // we may have gotten NULL back, meaning no entity was available if (thisClosestEntity) { - glm::vec3 entityPosition = thisClosestEntity->getPositionInMeters(); + glm::vec3 entityPosition = thisClosestEntity->getPosition(); float distanceFromPointToEntity = glm::distance(entityPosition, args->position); // If we're within our target radius @@ -457,7 +455,6 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) } const EntityItem* EntityTree::findClosestEntity(glm::vec3 position, float targetRadius) { - // position and targetRadius are in meters, so we need to convert to TreeUnits in FindNearPointArgs FindNearPointArgs args = { position, targetRadius, false, NULL, FLT_MAX }; lockForRead(); // NOTE: This should use recursion, since this is a spatial operation @@ -477,9 +474,7 @@ public: bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData) { FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData); glm::vec3 penetration; - AACube cube = element->getAACube(); - cube.scale((float)TREE_SCALE); - bool sphereIntersection = cube.findSpherePenetration(args->position, args->targetRadius, penetration); + bool sphereIntersection = element->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); // If this element contains the point, then search it... if (sphereIntersection) { @@ -493,8 +488,7 @@ bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData) } // NOTE: assumes caller has handled locking -void EntityTree::findEntitiesInMeters(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities) { - // position and targetRadius are in meters, so we need to convert to TreeUnits in FindNearPointArgs +void EntityTree::findEntities(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities) { FindAllNearPointArgs args = { center, radius }; // NOTE: This should use recursion, since this is a spatial operation recurseTreeWithOperation(findInSphereOperation, &args); @@ -515,9 +509,7 @@ public: bool EntityTree::findInCubeOperation(OctreeElement* element, void* extraData) { FindEntitiesInCubeArgs* args = static_cast<FindEntitiesInCubeArgs*>(extraData); - AACube elementCube = element->getAACube(); - elementCube.scale((float)TREE_SCALE); - if (elementCube.touches(args->_cube)) { + if (element->getAACube().touches(args->_cube)) { EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element); entityTreeElement->getEntities(args->_cube, args->_foundEntities); return true; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 852d07d20f..d897e6628e 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -109,7 +109,7 @@ public: /// \param radius the radius of the sphere in world-frame (meters) /// \param foundEntities[out] vector of const EntityItem* /// \remark Side effect: any initial contents in foundEntities will be lost - void findEntitiesInMeters(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities); + void findEntities(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities); /// finds all entities that touch a cube /// \param cube the query cube in world-frame (meters) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e32434b4c6..fbd377cfeb 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -22,15 +22,9 @@ EntityTreeElement::EntityTreeElement(unsigned char* octalCode) : OctreeElement() }; EntityTreeElement::~EntityTreeElement() { - int bar = 0; _octreeMemoryUsage -= sizeof(EntityTreeElement); - bar = 1; - std::cout << "adebug EntityTreeElement " << (void*)(this) << " deletes old entityItems = " << (void*)(_entityItems) << std::endl; // adebug delete _entityItems; - bar = 2; _entityItems = NULL; - bar = 3; - std::cout << "adebug bar = " << bar << std::endl; // adebug } // This will be called primarily on addChildAt(), which means we're adding a child of our @@ -45,7 +39,6 @@ OctreeElement* EntityTreeElement::createNewElement(unsigned char* octalCode) { void EntityTreeElement::init(unsigned char* octalCode) { OctreeElement::init(octalCode); _entityItems = new QList<EntityItem*>; - std::cout << "adebug EntityTreeElement " << (void*)(this) << " gets new entityItems = " << (void*)(_entityItems) << std::endl; // adebug _octreeMemoryUsage += sizeof(EntityTreeElement); } @@ -57,7 +50,7 @@ EntityTreeElement* EntityTreeElement::addChildAtIndex(int index) { void EntityTreeElement::debugExtraEncodeData(EncodeBitstreamParams& params) const { qDebug() << "EntityTreeElement::debugExtraEncodeData()... "; - qDebug() << " element:" << getAACube(); + qDebug() << " element:" << _cube; OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData; assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes @@ -166,7 +159,7 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, Oct const bool wantDebug = false; if (wantDebug) { - qDebug() << "EntityTreeElement::elementEncodeComplete() element:" << getAACube(); + qDebug() << "EntityTreeElement::elementEncodeComplete() element:" << _cube; } OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData; @@ -201,7 +194,7 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, Oct = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(childElement)); if (wantDebug) { - qDebug() << "checking child: " << childElement->getAACube(); + qDebug() << "checking child: " << childElement->_cube; qDebug() << " childElement->isLeaf():" << childElement->isLeaf(); qDebug() << " childExtraEncodeData->elementCompleted:" << childExtraEncodeData->elementCompleted; qDebug() << " childExtraEncodeData->subtreeCompleted:" << childExtraEncodeData->subtreeCompleted; @@ -222,7 +215,7 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, Oct } if (wantDebug) { - qDebug() << "for this element: " << getAACube(); + qDebug() << "for this element: " << _cube; qDebug() << " WAS elementCompleted:" << thisExtraEncodeData->elementCompleted; qDebug() << " WAS subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted; } @@ -309,7 +302,6 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData // the entity may not be in view and then in view a frame later, let the client side handle it's view // frustum culling on rendering. AACube entityCube = entity->getMaximumAACube(); - entityCube.scale(TREE_SCALE); if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) { includeThisEntity = false; // out of view, don't include it } @@ -448,14 +440,14 @@ bool EntityTreeElement::bestFitBounds(const AABox& bounds) const { } bool EntityTreeElement::containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const { - glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, 1.0f); - glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, 1.0f); + glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, (float)TREE_SCALE); + glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, (float)TREE_SCALE); return _cube.contains(clampedMin) && _cube.contains(clampedMax); } bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const { - glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, 1.0f); - glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, 1.0f); + glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, (float)TREE_SCALE); + glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, (float)TREE_SCALE); if (_cube.contains(clampedMin) && _cube.contains(clampedMax)) { @@ -476,7 +468,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 return false; } -bool EntityTreeElement::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, +bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube) { @@ -492,7 +484,7 @@ bool EntityTreeElement::findDetailedRayIntersectionInMeters(const glm::vec3& ori while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); - AABox entityBox = entity->getAABoxInMeters(); + AABox entityBox = entity->getAABox(); float localDistance; BoxFace localFace; @@ -501,11 +493,11 @@ bool EntityTreeElement::findDetailedRayIntersectionInMeters(const glm::vec3& ori // extents is the entity relative, scaled, centered extents of the entity glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); - glm::mat4 translation = glm::translate(entity->getPositionInMeters()); + glm::mat4 translation = glm::translate(entity->getPosition()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getDimensionsInMeters(); + glm::vec3 dimensions = entity->getDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -520,7 +512,7 @@ bool EntityTreeElement::findDetailedRayIntersectionInMeters(const glm::vec3& ori if (localDistance < distance) { // now ask the entity if we actually intersect if (entity->supportsDetailedRayIntersection()) { - if (entity->findDetailedRayIntersectionInMeters(origin, direction, keepSearching, element, localDistance, + if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, localFace, intersectedObject, precisionPicking)) { if (localDistance < distance) { @@ -556,8 +548,8 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad QList<EntityItem*>::const_iterator entityEnd = _entityItems->end(); while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); - glm::vec3 entityCenter = entity->getPositionInMeters(); - float entityRadius = entity->getRadiusInMeters(); + glm::vec3 entityCenter = entity->getPosition(); + float entityRadius = entity->getRadius(); // don't penetrate yourself if (entityCenter == center && entityRadius == radius) { @@ -592,7 +584,7 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const float closestEntityDistance = FLT_MAX; uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { - float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPositionInMeters()); + float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPosition()); if (distanceToEntity < closestEntityDistance) { closestEntity = (*_entityItems)[i]; } @@ -605,8 +597,8 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { const EntityItem* entity = (*_entityItems)[i]; - float distance = glm::length(entity->getPositionInMeters() - searchPosition); - if (distance < searchRadius + entity->getRadiusInMeters()) { + float distance = glm::length(entity->getPosition() - searchPosition); + if (distance < searchRadius + entity->getRadius()) { foundEntities.push_back(entity); } } @@ -619,11 +611,11 @@ void EntityTreeElement::getEntities(const AACube& box, QVector<EntityItem*>& fou AACube entityCube; while(entityItr != entityEnd) { EntityItem* entity = (*entityItr); - float radius = entity->getRadiusInMeters(); + float radius = entity->getRadius(); // NOTE: we actually do cube-cube collision queries here, which is sloppy but good enough for now // TODO: decide whether to replace entityCube-cube query with sphere-cube (requires a square root // but will be slightly more accurate). - entityCube.setBox(entity->getPositionInMeters() - glm::vec3(radius), 2.0f * radius); + entityCube.setBox(entity->getPosition() - glm::vec3(radius), 2.0f * radius); if (entityCube.touches(box)) { foundEntities.push_back(entity); } @@ -830,9 +822,7 @@ bool EntityTreeElement::pruneChildren() { void EntityTreeElement::debugDump() { qDebug() << "EntityTreeElement..."; - AACube temp = getAACube(); - temp.scale((float)TREE_SCALE); - qDebug() << " cube:" << temp; + qDebug() << " cube:" << _cube; qDebug() << " has child elements:" << getChildCount(); if (_entityItems->size()) { qDebug() << " has entities:" << _entityItems->size(); diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index ad91010b0b..0b28dd30d0 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -73,7 +73,6 @@ public: class EntityTreeElement : public OctreeElement { friend class EntityTree; // to allow createElement to new us... - EntityTreeElement(); EntityTreeElement(unsigned char* octalCode = NULL); virtual OctreeElement* createNewElement(unsigned char* octalCode = NULL); @@ -136,7 +135,7 @@ public: virtual bool deleteApproved() const { return !hasEntities(); } virtual bool canRayIntersect() const { return hasEntities(); } - virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 5a95fe4e33..f30d43c7d5 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -255,8 +255,8 @@ void ModelEntityItem::update(const quint64& now) { void ModelEntityItem::debugDump() const { qDebug() << "ModelEntityItem id:" << getEntityItemID(); qDebug() << " edited ago:" << getEditedAgo(); - qDebug() << " position:" << getPositionInMeters(); - qDebug() << " dimensions:" << getDimensionsInMeters(); + qDebug() << " position:" << getPosition(); + qDebug() << " dimensions:" << getDimensions(); qDebug() << " model URL:" << getModelURL(); } diff --git a/libraries/entities/src/MovingEntitiesOperator.cpp b/libraries/entities/src/MovingEntitiesOperator.cpp index 48ba8e4ec2..7cace205e1 100644 --- a/libraries/entities/src/MovingEntitiesOperator.cpp +++ b/libraries/entities/src/MovingEntitiesOperator.cpp @@ -51,7 +51,7 @@ MovingEntitiesOperator::~MovingEntitiesOperator() { void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& newCube) { EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID()); - AABox newCubeClamped = newCube.clamp(0.0f, 1.0f); + AABox newCubeClamped = newCube.clamp(0.0f, (float)TREE_SCALE); if (_wantDebug) { qDebug() << "MovingEntitiesOperator::addEntityToMoveList() -----------------------------"; @@ -114,7 +114,7 @@ bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElement* element) { // If we don't have an old entity, then we don't contain the entity, otherwise // check the bounds if (_entitiesToMove.size() > 0) { - AACube elementCube = element->getAACube(); + const AACube& elementCube = element->getAACube(); int detailIndex = 0; foreach(const EntityToMoveDetails& details, _entitiesToMove) { diff --git a/libraries/entities/src/MovingEntitiesOperator.h b/libraries/entities/src/MovingEntitiesOperator.h index fefda3328e..760b001081 100644 --- a/libraries/entities/src/MovingEntitiesOperator.h +++ b/libraries/entities/src/MovingEntitiesOperator.h @@ -15,11 +15,11 @@ class EntityToMoveDetails { public: EntityItem* entity; - AACube oldCube; - AACube newCube; - AABox newCubeClamped; + AACube oldCube; // meters + AACube newCube; // meters + AABox newCubeClamped; // meters EntityTreeElement* oldContainingElement; - AACube oldContainingElementCube; + AACube oldContainingElementCube; // meters bool oldFound; bool newFound; }; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index e21a2573a2..49149e78ae 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -91,13 +91,13 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); } -bool SphereEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, +bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { // determine the ray in the frame of the entity transformed from a unit sphere - glm::mat4 translation = glm::translate(getPositionInMeters()); + glm::mat4 translation = glm::translate(getPosition()); glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 scale = glm::scale(getDimensionsInMeters()); + glm::mat4 scale = glm::scale(getDimensions()); glm::mat4 registration = glm::translate(glm::vec3(0.5f, 0.5f, 0.5f) - getRegistrationPoint()); glm::mat4 entityToWorldMatrix = translation * rotation * scale * registration; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index f8419e75b9..f79a2db7ff 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -56,7 +56,7 @@ public: virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; } virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index d008bceccc..2b35ee9a59 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -42,7 +42,7 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityIte const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f; -void TextEntityItem::setDimensionsInMeters(const glm::vec3& value) { +void TextEntityItem::setDimensions(const glm::vec3& value) { // NOTE: Text Entities always have a "depth" of 1cm. _dimensions = glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH); } @@ -128,7 +128,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits } -bool TextEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, +bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { @@ -142,7 +142,7 @@ bool TextEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); glm::vec3 normal = _rotation * UNROTATED_NORMAL; plane.setNormal(normal); - plane.setPoint(getPositionInMeters()); // the position is definitely a point on our plane + plane.setPoint(getPosition()); // the position is definitely a point on our plane bool intersects = plane.findRayIntersection(rayInfo); @@ -151,11 +151,11 @@ bool TextEntityItem::findDetailedRayIntersectionInMeters(const glm::vec3& origin // now we know the point the ray hit our plane glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(getPositionInMeters()); + glm::mat4 translation = glm::translate(getPosition()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = getDimensionsInMeters(); + glm::vec3 dimensions = getDimensions(); glm::vec3 registrationPoint = getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); AABox entityFrameBox(corner, dimensions); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 1ee9c2c194..044975bdc8 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -23,7 +23,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensionsInMeters(const glm::vec3& value); + virtual void setDimensions(const glm::vec3& value); virtual void setDimensionsInDomainUnits(const glm::vec3& value); virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } @@ -47,7 +47,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData); virtual bool supportsDetailedRayIntersection() const { return true; } - virtual bool findDetailedRayIntersectionInMeters(const glm::vec3& origin, const glm::vec3& direction, + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; diff --git a/libraries/entities/src/UpdateEntityOperator.cpp b/libraries/entities/src/UpdateEntityOperator.cpp index 43052c6a73..f93be2f563 100644 --- a/libraries/entities/src/UpdateEntityOperator.cpp +++ b/libraries/entities/src/UpdateEntityOperator.cpp @@ -46,7 +46,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, // which can handle all potential rotations? // the getMaximumAACube is the relaxed form. _oldEntityCube = _existingEntity->getMaximumAACube(); - _oldEntityBox = _oldEntityCube.clamp(0.0f, 1.0f); // clamp to domain bounds + _oldEntityBox = _oldEntityCube.clamp(0.0f, (float)TREE_SCALE); // clamp to domain bounds // If the old properties doesn't contain the properties required to calculate a bounding box, // get them from the existing entity. Registration point is required to correctly calculate @@ -59,8 +59,8 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, // get the old property value and set it in our properties in order for our bounds // calculations to work. if (_properties.containsPositionChange() && !_properties.containsDimensionsChange()) { - glm::vec3 oldDimensionsInMeters = _existingEntity->getDimensionsInMeters(); - _properties.setDimensions(oldDimensionsInMeters); + glm::vec3 oldDimensions= _existingEntity->getDimensions(); + _properties.setDimensions(oldDimensions); if (_wantDebug) { qDebug() << " ** setting properties dimensions - had position change, no dimension change **"; @@ -68,8 +68,8 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, } if (!_properties.containsPositionChange() && _properties.containsDimensionsChange()) { - glm::vec3 oldPositionInMeters = _existingEntity->getPositionInMeters(); - _properties.setPosition(oldPositionInMeters); + glm::vec3 oldPosition= _existingEntity->getPosition(); + _properties.setPosition(oldPosition); if (_wantDebug) { qDebug() << " ** setting properties position - had dimensions change, no position change **"; @@ -114,7 +114,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, } } else { - _newEntityCube = _properties.getMaximumAACubeInTreeUnits(); + _newEntityCube = _properties.getMaximumAACube(); _removeOld = true; // our properties are going to move us, so remember this for later processing if (_wantDebug) { @@ -122,7 +122,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, } } - _newEntityBox = _newEntityCube.clamp(0.0f, 1.0f); // clamp to domain bounds + _newEntityBox = _newEntityCube.clamp(0.0f, (float)TREE_SCALE); // clamp to domain bounds if (_wantDebug) { diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 3b43a4a5d2..6b8f8c31e8 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -274,7 +274,7 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch if (destinationElement->getScale() < SCALE_AT_DANGEROUSLY_DEEP_RECURSION) { qDebug() << "UNEXPECTED: readElementData() destination element is unreasonably small [" - << destinationElement->getScale() * (float)TREE_SCALE << " meters] " + << destinationElement->getScale() << " meters] " << " Discarding " << bytesAvailable << " remaining bytes."; return bytesAvailable; // assume we read the entire buffer... } @@ -748,12 +748,8 @@ public: bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { SphereArgs* args = static_cast<SphereArgs*>(extraData); - // the details in args is in meters (world-frame) so we have to scale the element cube up - AACube box = element->getAACube(); - box.scale((float)TREE_SCALE); - // coarse check against bounds - if (!box.expandedContains(args->center, args->radius)) { + if (!element->getAACube().expandedContains(args->center, args->radius)) { return false; } if (element->hasContent()) { @@ -837,14 +833,12 @@ bool findCapsulePenetrationOp(OctreeElement* element, void* extraData) { CapsuleArgs* args = static_cast<CapsuleArgs*>(extraData); // coarse check against bounds - AACube box = element->getAACube(); - box.scale((float)TREE_SCALE); - if (!box.expandedIntersectsSegment(args->start, args->end, args->radius)) { + if (!element->getAACube().expandedIntersectsSegment(args->start, args->end, args->radius)) { return false; } if (element->hasContent()) { glm::vec3 nodePenetration; - if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) { + if (element->getAACube().findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) { args->penetration = addPenetrations(args->penetration, nodePenetration); args->found = true; } @@ -872,8 +866,7 @@ bool findContentInCubeOp(OctreeElement* element, void* extraData) { ContentArgs* args = static_cast<ContentArgs*>(extraData); // coarse check against bounds - AACube cube = element->getAACube(); - cube.scale(TREE_SCALE); + const AACube& cube = element->getAACube(); if (!cube.touches(args->cube)) { return false; } @@ -940,8 +933,7 @@ public: // Find the smallest colored voxel enclosing a point (if there is one) bool getElementEnclosingOperation(OctreeElement* element, void* extraData) { GetElementEnclosingArgs* args = static_cast<GetElementEnclosingArgs*>(extraData); - AACube elementBox = element->getAACube(); - if (elementBox.contains(args->point)) { + if (element->getAACube().contains(args->point)) { if (element->hasContent() && element->isLeaf()) { // we've reached a solid leaf containing the point, return the element. args->element = element; @@ -1207,9 +1199,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // If the user also asked for occlusion culling, check if this element is occluded, but only if it's not a leaf. // leaf occlusion is handled down below when we check child nodes if (params.wantOcclusionCulling && !element->isLeaf()) { - AACube voxelBox = element->getAACube(); - voxelBox.scale(TREE_SCALE); - OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(params.viewFrustum->getProjectedPolygon(voxelBox)); + OctreeProjectedPolygon* voxelPolygon = + new OctreeProjectedPolygon(params.viewFrustum->getProjectedPolygon(element->getAACube())); // In order to check occlusion culling, the shadow has to be "all in view" otherwise, we will ignore occlusion // culling and proceed as normal @@ -1360,10 +1351,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, if (params.wantOcclusionCulling && childElement->isLeaf()) { // Don't check occlusion here, just add them to our distance ordered array... - AACube voxelBox = childElement->getAACube(); - voxelBox.scale(TREE_SCALE); OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon( - params.viewFrustum->getProjectedPolygon(voxelBox)); + params.viewFrustum->getProjectedPolygon(childElement->getAACube())); // In order to check occlusion culling, the shadow has to be "all in view" otherwise, we ignore occlusion // culling and proceed as normal diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 8774ebe55b..a2265e38ed 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -270,6 +270,9 @@ public: void recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData = NULL); void recurseTreeWithPostOperation(RecurseOctreeOperation operation, void* extraData = NULL); + /// \param operation type of operation + /// \param point point in world-frame (meters) + /// \param extraData hook for user data to be interpreted by special context void recurseTreeWithOperationDistanceSorted(RecurseOctreeOperation operation, const glm::vec3& point, void* extraData = NULL); @@ -308,8 +311,13 @@ public: bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration, Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); + /// \param cube query cube in world-frame (meters) + /// \param[out] cubes list of cubes (world-frame) of child elements that have content bool findContentInCube(const AACube& cube, CubeList& cubes); + /// \param point query point in world-frame (meters) + /// \param lockType how to lock the tree (Lock, TryLock, NoLock) + /// \param[out] accurateResult pointer to output result, will be set "true" or "false" if non-null OctreeElement* getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 5e6fd0dde3..c8564ee5cb 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -194,14 +194,14 @@ void OctreeElement::setShouldRender(bool shouldRender) { } void OctreeElement::calculateAACube() { - glm::vec3 corner; - // copy corner into cube - copyFirstVertexForCode(getOctalCode(),(float*)&corner); + glm::vec3 corner; + copyFirstVertexForCode(getOctalCode(), (float*)&corner); // this tells you the "size" of the voxel - float voxelScale = 1 / powf(2, numberOfThreeBitSectionsInCode(getOctalCode())); - _cube.setBox(corner,voxelScale); + float voxelScale = (float)TREE_SCALE / powf(2.0f, numberOfThreeBitSectionsInCode(getOctalCode())); + corner *= (float)TREE_SCALE; + _cube.setBox(corner, voxelScale); } void OctreeElement::deleteChildAtIndex(int childIndex) { @@ -1221,9 +1221,7 @@ float OctreeElement::getEnclosingRadius() const { } ViewFrustum::location OctreeElement::inFrustum(const ViewFrustum& viewFrustum) const { - AACube cube = _cube; // use temporary cube so we can scale it - cube.scale(TREE_SCALE); - return viewFrustum.cubeInFrustum(cube); + return viewFrustum.cubeInFrustum(_cube); } // There are two types of nodes for which we want to "render" @@ -1257,16 +1255,13 @@ bool OctreeElement::calculateShouldRender(const ViewFrustum* viewFrustum, float // does as much math as possible in voxel scale and then scales up to TREE_SCALE at end float OctreeElement::furthestDistanceToCamera(const ViewFrustum& viewFrustum) const { glm::vec3 furthestPoint; - AACube cube = getAACube(); - cube.scale((float)TREE_SCALE); - viewFrustum.getFurthestPointFromCamera(cube, furthestPoint); + viewFrustum.getFurthestPointFromCamera(_cube, furthestPoint); glm::vec3 temp = viewFrustum.getPosition() - furthestPoint; - float distanceToFurthestPoint = sqrtf(glm::dot(temp, temp)); - return distanceToFurthestPoint; + return sqrtf(glm::dot(temp, temp)); } float OctreeElement::distanceToCamera(const ViewFrustum& viewFrustum) const { - glm::vec3 center = _cube.calcCenter() * (float)TREE_SCALE; + glm::vec3 center = _cube.calcCenter(); glm::vec3 temp = viewFrustum.getPosition() - center; float distanceToVoxelCenter = sqrtf(glm::dot(temp, temp)); return distanceToVoxelCenter; @@ -1339,14 +1334,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 keepSearching = true; // assume that we will continue searching after this. - AACube cube = getAACube(); - cube.scale((float)TREE_SCALE); float distanceToElementCube = std::numeric_limits<float>::max(); float distanceToElementDetails = distance; BoxFace localFace; // if the ray doesn't intersect with our cube, we can stop searching! - if (!cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { + if (!_cube.findRayIntersection(origin, direction, distanceToElementCube, localFace)) { keepSearching = false; // no point in continuing to search return false; // we did not intersect } @@ -1358,7 +1351,7 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 // if the distance to the element cube is not less than the current best distance, then it's not possible // for any details inside the cube to be closer so we don't need to consider them. - if (cube.contains(origin) || distanceToElementCube < distance) { + if (_cube.contains(origin) || distanceToElementCube < distance) { if (findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails, face, intersectedObject, precisionPicking, distanceToElementCube)) { @@ -1393,9 +1386,7 @@ bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const g bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const { // center and radius are in meters, so we have to scale the _cube into world-frame - AACube cube = _cube; - cube.scale((float)TREE_SCALE); - return cube.findSpherePenetration(center, radius, penetration); + return _cube.findSpherePenetration(center, radius, penetration); } // TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)... @@ -1532,15 +1523,15 @@ int OctreeElement::getMyChildContaining(const AACube& cube) const { if (cubeScale > ourScale) { qDebug() << "UNEXPECTED -- OctreeElement::getMyChildContaining() -- (cubeScale > ourScale)"; qDebug() << " cube=" << cube; - qDebug() << " elements AACube=" << getAACube(); + qDebug() << " elements AACube=" << _cube; qDebug() << " cubeScale=" << cubeScale; qDebug() << " ourScale=" << ourScale; assert(false); } // Determine which of our children the minimum and maximum corners of the cube live in... - glm::vec3 cubeCornerMinimum = glm::clamp(cube.getCorner(), 0.0f, 1.0f); - glm::vec3 cubeCornerMaximum = glm::clamp(cube.calcTopFarLeft(), 0.0f, 1.0f); + glm::vec3 cubeCornerMinimum = glm::clamp(cube.getCorner(), 0.0f, (float)TREE_SCALE); + glm::vec3 cubeCornerMaximum = glm::clamp(cube.calcTopFarLeft(), 0.0f, (float)TREE_SCALE); if (_cube.contains(cubeCornerMinimum) && _cube.contains(cubeCornerMaximum)) { int childIndexCubeMinimum = getMyChildContainingPoint(cubeCornerMinimum); diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index 8fe4fbd4d5..d47a324e07 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -101,7 +101,6 @@ void OctreeHeadlessViewer::queryOctree() { voxelDetailsForCode(rootCode, rootDetails); jurisdictions.unlock(); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); - serverBounds.scale(TREE_SCALE); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); @@ -170,7 +169,6 @@ void OctreeHeadlessViewer::queryOctree() { voxelDetailsForCode(rootCode, rootDetails); jurisdictions.unlock(); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); - serverBounds.scale(TREE_SCALE); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index c4ccd98036..187f916d35 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -22,13 +22,11 @@ OctreeRenderer::OctreeRenderer() : _managedTree(false), _viewFrustum(NULL) { - std::cout << "adebug " << (void*)(this) << " OctreeRenderer() _tree = " << (void*)(_tree) << std::endl; // adebug } void OctreeRenderer::init() { if (!_tree) { _tree = createTree(); - std::cout << "adebug " << (void*)(this) << " init _tree = " << (void*)(_tree) << std::endl; // adebug _managedTree = true; } } @@ -45,7 +43,6 @@ void OctreeRenderer::setTree(Octree* newTree) { _managedTree = false; } _tree = newTree; - std::cout << "adebug " << (void*)(this) << " setTree() _tree = " << (void*)(_tree) << std::endl; // adebug } void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 699b4cc386..c35ace6b11 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -84,19 +84,19 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { // bypass const-ness so we can remember the substep const_cast<EntityMotionState*>(this)->_lastKinematicSubstep = substep; } - worldTrans.setOrigin(glmToBullet(_entity->getPositionInMeters() - ObjectMotionState::getWorldOffset())); + worldTrans.setOrigin(glmToBullet(_entity->getPosition() - ObjectMotionState::getWorldOffset())); worldTrans.setRotation(glmToBullet(_entity->getRotation())); } // This callback is invoked by the physics simulation at the end of each simulation frame... // iff the corresponding RigidBody is DYNAMIC and has moved. void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { - _entity->setPositionInMeters(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); + _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); _entity->setRotation(bulletToGLM(worldTrans.getRotation())); glm::vec3 v; getVelocity(v); - _entity->setVelocityInMeters(v); + _entity->setVelocity(v); getAngularVelocity(v); // DANGER! EntityItem stores angularVelocity in degrees/sec!!! @@ -119,7 +119,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t frame) { if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) { if (flags & EntityItem::DIRTY_POSITION) { - _sentPosition = _entity->getPositionInMeters() - ObjectMotionState::getWorldOffset(); + _sentPosition = _entity->getPosition() - ObjectMotionState::getWorldOffset(); btTransform worldTrans; worldTrans.setOrigin(glmToBullet(_sentPosition)); @@ -156,14 +156,14 @@ void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t frame) { void EntityMotionState::updateObjectVelocities() { if (_body) { - _sentVelocity = _entity->getVelocityInMeters(); + _sentVelocity = _entity->getVelocity(); setVelocity(_sentVelocity); // DANGER! EntityItem stores angularVelocity in degrees/sec!!! _sentAngularVelocity = glm::radians(_entity->getAngularVelocity()); setAngularVelocity(_sentAngularVelocity); - _sentAcceleration = _entity->getGravityInMeters(); + _sentAcceleration = _entity->getGravity(); setGravity(_sentAcceleration); _body->setActivationState(ACTIVE_TAG); diff --git a/tests/octree/src/ModelTests.cpp b/tests/octree/src/ModelTests.cpp index e46fbc157a..e4309100af 100644 --- a/tests/octree/src/ModelTests.cpp +++ b/tests/octree/src/ModelTests.cpp @@ -66,17 +66,17 @@ void EntityTests::entityTreeTests(bool verbose) { const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius); const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID); EntityTreeElement* containingElement = tree.getContainingElement(entityID); - AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); + const AACube& elementCube = containingElement ? containingElement->getAACube() : AACube(); if (verbose) { qDebug() << "foundEntityByRadius=" << foundEntityByRadius; qDebug() << "foundEntityByID=" << foundEntityByID; qDebug() << "containingElement=" << containingElement; qDebug() << "containingElement.box=" - << elementCube.getCorner().x * TREE_SCALE << "," - << elementCube.getCorner().y * TREE_SCALE << "," - << elementCube.getCorner().z * TREE_SCALE << ":" - << elementCube.getScale() * TREE_SCALE; + << elementCube.getCorner().x << "," + << elementCube.getCorner().y << "," + << elementCube.getCorner().z << ":" + << elementCube.getScale(); qDebug() << "elementCube.getScale()=" << elementCube.getScale(); //containingElement->printDebugDetails("containingElement"); } @@ -109,17 +109,17 @@ void EntityTests::entityTreeTests(bool verbose) { const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOrigin, targetRadius); const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID); EntityTreeElement* containingElement = tree.getContainingElement(entityID); - AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); + const AACube& elementCube = containingElement ? containingElement->getAACube() : AACube(); if (verbose) { qDebug() << "foundEntityByRadius=" << foundEntityByRadius; qDebug() << "foundEntityByID=" << foundEntityByID; qDebug() << "containingElement=" << containingElement; qDebug() << "containingElement.box=" - << elementCube.getCorner().x * TREE_SCALE << "," - << elementCube.getCorner().y * TREE_SCALE << "," - << elementCube.getCorner().z * TREE_SCALE << ":" - << elementCube.getScale() * TREE_SCALE; + << elementCube.getCorner().x << "," + << elementCube.getCorner().y << "," + << elementCube.getCorner().z << ":" + << elementCube.getScale(); //containingElement->printDebugDetails("containingElement"); } @@ -149,17 +149,17 @@ void EntityTests::entityTreeTests(bool verbose) { const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius); const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID); EntityTreeElement* containingElement = tree.getContainingElement(entityID); - AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); + const AACube& elementCube = containingElement ? containingElement->getAACube() : AACube(); if (verbose) { qDebug() << "foundEntityByRadius=" << foundEntityByRadius; qDebug() << "foundEntityByID=" << foundEntityByID; qDebug() << "containingElement=" << containingElement; qDebug() << "containingElement.box=" - << elementCube.getCorner().x * TREE_SCALE << "," - << elementCube.getCorner().y * TREE_SCALE << "," - << elementCube.getCorner().z * TREE_SCALE << ":" - << elementCube.getScale() * TREE_SCALE; + << elementCube.getCorner().x << "," + << elementCube.getCorner().y << "," + << elementCube.getCorner().z << ":" + << elementCube.getScale(); //containingElement->printDebugDetails("containingElement"); } @@ -288,7 +288,7 @@ void EntityTests::entityTreeTests(bool verbose) { totalElapsedFind += (endFind - startFind); EntityTreeElement* containingElement = tree.getContainingElement(entityID); - AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); + const AACube& elementCube = containingElement ? containingElement->getAACube() : AACube(); bool elementIsBestFit = containingElement->bestFitEntityBounds(foundEntityByID); @@ -297,10 +297,10 @@ void EntityTests::entityTreeTests(bool verbose) { qDebug() << "foundEntityByID=" << foundEntityByID; qDebug() << "containingElement=" << containingElement; qDebug() << "containingElement.box=" - << elementCube.getCorner().x * TREE_SCALE << "," - << elementCube.getCorner().y * TREE_SCALE << "," - << elementCube.getCorner().z * TREE_SCALE << ":" - << elementCube.getScale() * TREE_SCALE; + << elementCube.getCorner().x << "," + << elementCube.getCorner().y << "," + << elementCube.getCorner().z << ":" + << elementCube.getScale(); qDebug() << "elementCube.getScale()=" << elementCube.getScale(); //containingElement->printDebugDetails("containingElement"); qDebug() << "elementIsBestFit=" << elementIsBestFit; From c4dafc74ad2f4a1918c7e328d0590692d5ae8f42 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Fri, 6 Mar 2015 15:33:15 -0800 Subject: [PATCH 43/56] whoops, remove last bestFitBoundsInMeters() call --- libraries/entities/src/AddEntityOperator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/AddEntityOperator.cpp b/libraries/entities/src/AddEntityOperator.cpp index 0844a10ede..09aa6af0cb 100644 --- a/libraries/entities/src/AddEntityOperator.cpp +++ b/libraries/entities/src/AddEntityOperator.cpp @@ -43,7 +43,7 @@ bool AddEntityOperator::preRecursion(OctreeElement* element) { if (!_foundNew && element->getAACube().contains(_newEntityBox)) { // If this element is the best fit for the new entity properties, then add/or update it - if (entityTreeElement->bestFitBoundsInMeters(_newEntityBox)) { + if (entityTreeElement->bestFitBounds(_newEntityBox)) { entityTreeElement->addEntityItem(_newEntity); _tree->setContainingElement(_newEntity->getEntityItemID(), entityTreeElement); From 95c7bcb5f8494d49f080b03f65ffea4e20814784 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Fri, 6 Mar 2015 15:34:35 -0800 Subject: [PATCH 44/56] whoops -- remove last *InTreeUnits() calls --- libraries/entities/src/EntityTreeElement.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index fbd377cfeb..223a4eb478 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -416,11 +416,11 @@ bool EntityTreeElement::bestFitEntityBounds(const EntityItem* entity) const { } bool EntityTreeElement::containsBounds(const EntityItemProperties& properties) const { - return containsBounds(properties.getMaximumAACubeInTreeUnits()); + return containsBounds(properties.getMaximumAACube()); } bool EntityTreeElement::bestFitBounds(const EntityItemProperties& properties) const { - return bestFitBounds(properties.getMaximumAACubeInTreeUnits()); + return bestFitBounds(properties.getMaximumAACube()); } bool EntityTreeElement::containsBounds(const AACube& bounds) const { From 7a5669f14ec2de834f0c7a7efa64a0286e90cd8d Mon Sep 17 00:00:00 2001 From: Jason <2billbrasky@gmail.com> Date: Fri, 6 Mar 2015 15:52:21 -0800 Subject: [PATCH 45/56] Interview project updates. Tried to address all of Brad's notes, most of which were related to matching the coding style for the project. Also used GeometryCache instead of making direct calls to OpenGL to do drawing, took a different approach to seeding rand(), updated the packet version, and fixed a bug that I noticed in the setting of the dimensions for the particle effect entity. --- .../RenderableParticleEffectEntityItem.cpp | 88 +-- .../src/RenderableParticleEffectEntityItem.h | 9 +- .../entities/src/EntityItemProperties.cpp | 106 +-- libraries/entities/src/EntityItemProperties.h | 46 +- .../entities/src/ParticleEffectEntityItem.cpp | 704 +++++++++--------- .../entities/src/ParticleEffectEntityItem.h | 210 +++--- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 8 files changed, 581 insertions(+), 585 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index a10f59287c..9cb8c3912e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -15,11 +15,17 @@ #include <DependencyManager.h> #include <DeferredLightingEffect.h> #include <PerfStat.h> +#include <GeometryCache.h> #include "RenderableParticleEffectEntityItem.h" EntityItem* RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new RenderableParticleEffectEntityItem(entityID, properties); + return new RenderableParticleEffectEntityItem(entityID, properties); +} + +RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + ParticleEffectEntityItem(entityItemID, properties) { + _cacheID = DependencyManager::get<GeometryCache>()->allocateID(); } void RenderableParticleEffectEntityItem::render(RenderArgs* args) { @@ -28,11 +34,45 @@ void RenderableParticleEffectEntityItem::render(RenderArgs* args) { glm::vec3 position = getPositionInMeters(); glm::vec3 center = getCenterInMeters(); glm::quat rotation = getRotation(); - float pa_rad = getParticleRadius(); + float pa_rad = getParticleRadius(); const float MAX_COLOR = 255.0f; - glm::vec4 sphereColor(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, + glm::vec4 paColor(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); + + // Right now we're just iterating over particles and rendering as a cross of four quads. + // This is pretty dumb, it was quick enough to code up. Really, there should be many + // rendering modes, including the all-important textured billboards. + + QVector<glm::vec3>* pointVec = new QVector<glm::vec3>(_paCount * VERTS_PER_PARTICLE); + quint32 paIter = _paHead; + while (_paLife[paIter] > 0.0f) { + int j = paIter * XYZ_STRIDE; + + pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2])); + pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2])); + pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2])); + pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2])); + + pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2])); + pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2])); + pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2])); + pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2])); + + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] - pa_rad)); + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] + pa_rad)); + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] + pa_rad)); + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] - pa_rad)); + + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] + pa_rad)); + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] - pa_rad)); + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] - pa_rad)); + pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] + pa_rad)); + + paIter = (paIter + 1) % _maxParticles; + } + + DependencyManager::get<GeometryCache>()->updateVertices(_cacheID, *pointVec, paColor); glPushMatrix(); glTranslatef(position.x, position.y, position.z); @@ -44,45 +84,9 @@ void RenderableParticleEffectEntityItem::render(RenderArgs* args) { glm::vec3 positionToCenter = center - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - const int SLICES = 8; - const int STACKS = 5; - - glBegin(GL_QUADS); - glColor4f(sphereColor.r, sphereColor.g, sphereColor.b, sphereColor.a); - - // Right now we're just iterating over particles and rendering as a cross of four quads. - // This is pretty dumb, it was quick enough to code up. Really, there should be many - // rendering modes, including the all-important textured billboards. - - quint32 paiter = pa_head; - while (pa_life[paiter] > 0.0f) - { - int j = paiter * 3; - - glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); - glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); - glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); - glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); - - glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); - glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] + pa_rad, pa_position[j + 2]); - glVertex3f(pa_position[j] - pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); - glVertex3f(pa_position[j] + pa_rad, pa_position[j + 1] - pa_rad, pa_position[j + 2]); - - glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] - pa_rad); - glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] + pa_rad); - glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] + pa_rad); - glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] - pa_rad); - - glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] + pa_rad); - glVertex3f(pa_position[j], pa_position[j + 1] + pa_rad, pa_position[j + 2] - pa_rad); - glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] - pa_rad); - glVertex3f(pa_position[j], pa_position[j + 1] - pa_rad, pa_position[j + 2] + pa_rad); - - paiter = (paiter + 1) % _maxParticles; - } - - glEnd(); + DependencyManager::get<GeometryCache>()->renderVertices(gpu::QUADS, _cacheID); glPopMatrix(); glPopMatrix(); + + delete pointVec; }; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 837c878a45..74b29574c3 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -16,13 +16,12 @@ class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem { public: static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); - - RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : - ParticleEffectEntityItem(entityItemID, properties) - { } - + RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); virtual void render(RenderArgs* args); +protected: + int _cacheID; + const int VERTS_PER_PARTICLE = 16; }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 87b59b0392..3a2bacf9b1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -67,13 +67,13 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR), CONSTRUCT_PROPERTY(backgroundColor, TextEntityItem::DEFAULT_BACKGROUND_COLOR), CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE), - CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES), - CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), - CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), - CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), - CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), - CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), - CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), + CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES), + CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), + CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), + CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), + CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), + CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), + CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -246,13 +246,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_TEXT_COLOR, textColor); CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_COLOR, backgroundColor); CHECK_PROPERTY_CHANGE(PROP_SHAPE_TYPE, shapeType); - CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); - CHECK_PROPERTY_CHANGE(PROP_LIFESPAN, lifespan); - CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); - CHECK_PROPERTY_CHANGE(PROP_EMIT_DIRECTION, emitDirection); - CHECK_PROPERTY_CHANGE(PROP_EMIT_STRENGTH, emitStrength); - CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); - CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); + CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); + CHECK_PROPERTY_CHANGE(PROP_LIFESPAN, lifespan); + CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); + CHECK_PROPERTY_CHANGE(PROP_EMIT_DIRECTION, emitDirection); + CHECK_PROPERTY_CHANGE(PROP_EMIT_STRENGTH, emitStrength); + CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); + CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); return changedProperties; } @@ -312,13 +312,13 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeAsString()); - COPY_PROPERTY_TO_QSCRIPTVALUE(maxParticles); - COPY_PROPERTY_TO_QSCRIPTVALUE(lifespan); - COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate); - COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(emitDirection); - COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength); - COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); - COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); + COPY_PROPERTY_TO_QSCRIPTVALUE(maxParticles); + COPY_PROPERTY_TO_QSCRIPTVALUE(lifespan); + COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate); + COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(emitDirection); + COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength); + COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); + COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); @@ -397,13 +397,13 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor); COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(maxParticles, setMaxParticles); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lifespan, setLifespan); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitRate, setEmitRate); - COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(emitDirection, setEmitDirection); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitStrength, setEmitStrength); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localGravity, setLocalGravity); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(maxParticles, setMaxParticles); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lifespan, setLifespan); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitRate, setEmitRate); + COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(emitDirection, setEmitDirection); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitStrength, setEmitStrength); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localGravity, setLocalGravity); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius); _lastEdited = usecTimestampNow(); } @@ -582,15 +582,15 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, properties.getCutoff()); } - if (properties.getType() == EntityTypes::ParticleEffect) { - APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, properties.getMaxParticles()); - APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, properties.getLifespan()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, properties.getEmitRate()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, properties.getEmitDirection()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, properties.getEmitStrength()); - APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, properties.getLocalGravity()); - APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, properties.getParticleRadius()); - } + if (properties.getType() == EntityTypes::ParticleEffect) { + APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, properties.getMaxParticles()); + APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, properties.getLifespan()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, properties.getEmitRate()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, properties.getEmitDirection()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, properties.getEmitStrength()); + APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, properties.getLocalGravity()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, properties.getParticleRadius()); + } } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); @@ -814,15 +814,15 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff); } - if (properties.getType() == EntityTypes::ParticleEffect) { - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_STRENGTH, float, setEmitStrength); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); - } + if (properties.getType() == EntityTypes::ParticleEffect) { + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_STRENGTH, float, setEmitStrength); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); + } return valid; } @@ -901,13 +901,13 @@ void EntityItemProperties::markAllChanged() { _backgroundColorChanged = true; _shapeTypeChanged = true; - _maxParticlesChanged = true; - _lifespanChanged = true; - _emitRateChanged = true; - _emitDirectionChanged = true; - _emitStrengthChanged = true; - _localGravityChanged = true; - _particleRadiusChanged = true; + _maxParticlesChanged = true; + _lifespanChanged = true; + _emitRateChanged = true; + _emitDirectionChanged = true; + _emitStrengthChanged = true; + _localGravityChanged = true; + _particleRadiusChanged = true; } AACube EntityItemProperties::getMaximumAACubeInTreeUnits() const { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index d5a3c32809..15527288ab 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -84,14 +84,14 @@ enum EntityPropertyList { PROP_USER_DATA, PROP_SHAPE_TYPE, - // used by ParticleEffect entities - PROP_MAX_PARTICLES, - PROP_LIFESPAN, - PROP_EMIT_RATE, - PROP_EMIT_DIRECTION, - PROP_EMIT_STRENGTH, - PROP_LOCAL_GRAVITY, - PROP_PARTICLE_RADIUS, + // used by ParticleEffect entities + PROP_MAX_PARTICLES, + PROP_LIFESPAN, + PROP_EMIT_RATE, + PROP_EMIT_DIRECTION, + PROP_EMIT_STRENGTH, + PROP_LOCAL_GRAVITY, + PROP_PARTICLE_RADIUS, // NOTE: add new properties ABOVE this line and then modify PROP_LAST_ITEM below PROP_LAST_ITEM = PROP_PARTICLE_RADIUS, @@ -119,7 +119,7 @@ class EntityItemProperties { friend class SphereEntityItem; // TODO: consider removing this friend relationship and use public methods friend class LightEntityItem; // TODO: consider removing this friend relationship and use public methods friend class TextEntityItem; // TODO: consider removing this friend relationship and use public methods - friend class ParticleEffectEntityItem; // TODO: consider removing this friend relationship and use public methods + friend class ParticleEffectEntityItem; // TODO: consider removing this friend relationship and use public methods public: EntityItemProperties(); virtual ~EntityItemProperties(); @@ -192,13 +192,13 @@ public: DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); - DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); - DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); - DEFINE_PROPERTY_REF(PROP_EMIT_DIRECTION, EmitDirection, emitDirection, glm::vec3); - DEFINE_PROPERTY(PROP_EMIT_STRENGTH, EmitStrength, emitStrength, float); - DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); - DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); + DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); + DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); + DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); + DEFINE_PROPERTY_REF(PROP_EMIT_DIRECTION, EmitDirection, emitDirection, glm::vec3); + DEFINE_PROPERTY(PROP_EMIT_STRENGTH, EmitStrength, emitStrength, float); + DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); + DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); public: float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } @@ -321,13 +321,13 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, TextColor, textColor, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundColor, backgroundColor, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ShapeType, shapeType, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, MaxParticles, maxParticles, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitDirection, emitDirection, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, MaxParticles, maxParticles, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitDirection, emitDirection, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); debug << " last edited:" << properties.getLastEdited() << "\n"; debug << " edited ago:" << properties.getEditedAgo() << "\n"; diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index cf84f7be75..31b002b23f 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -57,466 +57,456 @@ const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; EntityItem* ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new ParticleEffectEntityItem(entityID, properties); + return new ParticleEffectEntityItem(entityID, properties); } // our non-pure virtual subclass for now... ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : -EntityItem(entityItemID, properties) -{ - _type = EntityTypes::ParticleEffect; - _maxParticles = DEFAULT_MAX_PARTICLES; - _lifespan = DEFAULT_LIFESPAN; - _emitRate = DEFAULT_EMIT_RATE; - _emitDirection = DEFAULT_EMIT_DIRECTION; - _emitStrength = DEFAULT_EMIT_STRENGTH; - _localGravity = DEFAULT_LOCAL_GRAVITY; - _particleRadius = DEFAULT_PARTICLE_RADIUS; - setProperties(properties); - // this is a pretty dumb thing to do, and it should probably be changed to use a more dynamic - // data structure in the future. I'm just trying to get some code out the door for now (and it's - // at least time efficient (though not space efficient). - // Also, this being a real-time application, it's doubtful we'll ever have millions of particles - // to keep track of, so this really isn't all that bad. - pa_life = (float*) malloc(sizeof(float) * _maxParticles); - pa_position = (float*)malloc(sizeof(float) * _maxParticles * 3); // x,y,z - pa_velocity = (float*)malloc(sizeof(float) * _maxParticles * 3); // x,y,z - pa_xmax = pa_ymax = pa_zmax = 1.0f; - pa_xmin = pa_ymin = pa_zmin = -1.0f; - resetSim(); - _lastAnimated = usecTimestampNow(); + EntityItem(entityItemID, properties) { + _type = EntityTypes::ParticleEffect; + _maxParticles = DEFAULT_MAX_PARTICLES; + _lifespan = DEFAULT_LIFESPAN; + _emitRate = DEFAULT_EMIT_RATE; + _emitDirection = DEFAULT_EMIT_DIRECTION; + _emitStrength = DEFAULT_EMIT_STRENGTH; + _localGravity = DEFAULT_LOCAL_GRAVITY; + _particleRadius = DEFAULT_PARTICLE_RADIUS; + setProperties(properties); + // this is a pretty dumb thing to do, and it should probably be changed to use a more dynamic + // data structure in the future. I'm just trying to get some code out the door for now (and it's + // at least time efficient (though not space efficient). + // Also, this being a real-time application, it's doubtful we'll ever have millions of particles + // to keep track of, so this really isn't all that bad. + _paLife = new float[_maxParticles]; + _paPosition = new float[_maxParticles * XYZ_STRIDE]; // x,y,z + _paVelocity = new float[_maxParticles * XYZ_STRIDE]; // x,y,z + _paXmax = _paYmax = _paZmax = 1.0f; + _paXmin = _paYmin = _paZmin = -1.0f; + _randSeed = (unsigned int) glm::abs(_lifespan + _emitRate + _localGravity + getPosition().x + getPosition().y + getPosition().z); + resetSimulation(); + _lastAnimated = usecTimestampNow(); } -ParticleEffectEntityItem::~ParticleEffectEntityItem() -{ - free(pa_life); - free(pa_position); - free(pa_velocity); +ParticleEffectEntityItem::~ParticleEffectEntityItem() { + delete [] _paLife; + delete [] _paPosition; + delete [] _paVelocity; } EntityItemProperties ParticleEffectEntityItem::getProperties() const { - EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class - - COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFPS, getAnimationFPS); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitDirection, getEmitDirection); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitStrength, getEmitStrength); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius); + EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class + + COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFPS, getAnimationFPS); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitDirection, getEmitDirection); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitStrength, getEmitStrength); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius); - return properties; + return properties; } bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& properties) { - bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class - SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitDirection, setEmitDirection); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitStrength, setEmitStrength); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitDirection, setEmitDirection); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitStrength, setEmitStrength); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); - if (somethingChanged) { - bool wantDebug = false; - if (wantDebug) { - uint64_t now = usecTimestampNow(); - int elapsed = now - getLastEdited(); - qDebug() << "ParticleEffectEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << - "now=" << now << " getLastEdited()=" << getLastEdited(); - } - setLastEdited(properties.getLastEdited()); - } - return somethingChanged; + if (somethingChanged) { + bool wantDebug = false; + if (wantDebug) { + uint64_t now = usecTimestampNow(); + int elapsed = now - getLastEdited(); + qDebug() << "ParticleEffectEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << + "now=" << now << " getLastEdited()=" << getLastEdited(); + } + setLastEdited(properties.getLastEdited()); + } + return somethingChanged; } int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, - ReadBitstreamToTreeParams& args, - EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { - int bytesRead = 0; - const unsigned char* dataAt = data; + int bytesRead = 0; + const unsigned char* dataAt = data; - READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color); + READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color); - // Because we're using AnimationLoop which will reset the frame index if you change it's running state - // we want to read these values in the order they appear in the buffer, but call our setters in an - // order that allows AnimationLoop to preserve the correct frame rate. - float animationFPS = getAnimationFPS(); - float animationFrameIndex = getAnimationFrameIndex(); - bool animationIsPlaying = getAnimationIsPlaying(); - READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, animationFPS); - READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, animationFrameIndex); - READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying); + // Because we're using AnimationLoop which will reset the frame index if you change it's running state + // we want to read these values in the order they appear in the buffer, but call our setters in an + // order that allows AnimationLoop to preserve the correct frame rate. + float animationFPS = getAnimationFPS(); + float animationFrameIndex = getAnimationFrameIndex(); + bool animationIsPlaying = getAnimationIsPlaying(); + READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, animationFPS); + READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, animationFrameIndex); + READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying); - if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) { - if (animationIsPlaying != getAnimationIsPlaying()) { - setAnimationIsPlaying(animationIsPlaying); - } - } - if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) { - setAnimationFPS(animationFPS); - } - if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) { - setAnimationFrameIndex(animationFrameIndex); - } + if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) { + if (animationIsPlaying != getAnimationIsPlaying()) { + setAnimationIsPlaying(animationIsPlaying); + } + } + if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) { + setAnimationFPS(animationFPS); + } + if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) { + setAnimationFrameIndex(animationFrameIndex); + } - READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings); - READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType); - READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, _maxParticles); - READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, _lifespan); - READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, _emitRate); - READ_ENTITY_PROPERTY_SETTER(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); - READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, _emitStrength); - READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, _localGravity); - READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, _particleRadius); + READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings); + READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType); + READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, _maxParticles); + READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, _lifespan); + READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, _emitRate); + READ_ENTITY_PROPERTY_SETTER(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); + READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, _emitStrength); + READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, _localGravity); + READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, _particleRadius); - return bytesRead; + return bytesRead; } // TODO: eventually only include properties changed since the params.lastViewFrustumSent time EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { - EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); - - requestedProperties += PROP_COLOR; - requestedProperties += PROP_ANIMATION_FPS; - requestedProperties += PROP_ANIMATION_FRAME_INDEX; - requestedProperties += PROP_ANIMATION_PLAYING; - requestedProperties += PROP_ANIMATION_SETTINGS; - requestedProperties += PROP_SHAPE_TYPE; - requestedProperties += PROP_MAX_PARTICLES; - requestedProperties += PROP_LIFESPAN; - requestedProperties += PROP_EMIT_RATE; - requestedProperties += PROP_EMIT_DIRECTION; - requestedProperties += PROP_EMIT_STRENGTH; - requestedProperties += PROP_LOCAL_GRAVITY; - requestedProperties += PROP_PARTICLE_RADIUS; + EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + + requestedProperties += PROP_COLOR; + requestedProperties += PROP_ANIMATION_FPS; + requestedProperties += PROP_ANIMATION_FRAME_INDEX; + requestedProperties += PROP_ANIMATION_PLAYING; + requestedProperties += PROP_ANIMATION_SETTINGS; + requestedProperties += PROP_SHAPE_TYPE; + requestedProperties += PROP_MAX_PARTICLES; + requestedProperties += PROP_LIFESPAN; + requestedProperties += PROP_EMIT_RATE; + requestedProperties += PROP_EMIT_DIRECTION; + requestedProperties += PROP_EMIT_STRENGTH; + requestedProperties += PROP_LOCAL_GRAVITY; + requestedProperties += PROP_PARTICLE_RADIUS; - return requestedProperties; + return requestedProperties; } void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, - EntityPropertyFlags& requestedProperties, - EntityPropertyFlags& propertyFlags, - EntityPropertyFlags& propertiesDidntFit, - int& propertyCount, - OctreeElement::AppendState& appendState) const { + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { - bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying()); - APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings()); - APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType()); - APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, getMaxParticles()); - APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, getLifespan()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, getEmitRate()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, getEmitDirection()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, getEmitStrength()); - APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, getLocalGravity()); - APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius()); + bool successPropertyFits = true; + APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings()); + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType()); + APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, appendValue, getMaxParticles()); + APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, appendValue, getLifespan()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, appendValue, getEmitRate()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, appendValue, getEmitDirection()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, getEmitStrength()); + APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, getLocalGravity()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius()); } bool ParticleEffectEntityItem::isAnimatingSomething() const { - return getAnimationIsPlaying() && - getAnimationFPS() != 0.0f; + return getAnimationIsPlaying() && + getAnimationFPS() != 0.0f; } bool ParticleEffectEntityItem::needsToCallUpdate() const { - return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate(); + return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate(); } void ParticleEffectEntityItem::update(const quint64& now) { - // only advance the frame index if we're playing - if (getAnimationIsPlaying()) { - float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; - _lastAnimated = now; - float lastFrame = _animationLoop.getFrameIndex(); - _animationLoop.simulate(deltaTime); - float curFrame = _animationLoop.getFrameIndex(); - if (curFrame > lastFrame) - { - stepSim(deltaTime); - } - else if (curFrame < lastFrame) - { - // we looped around, so restart the sim and only sim up to the point - // since the beginning of the frame range. - resetSim(); - stepSim((curFrame - _animationLoop.getFirstFrame()) / _animationLoop.getFPS()); - } - } - else { - _lastAnimated = now; - } + // only advance the frame index if we're playing + if (getAnimationIsPlaying()) { + float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; + _lastAnimated = now; + float lastFrame = _animationLoop.getFrameIndex(); + _animationLoop.simulate(deltaTime); + float curFrame = _animationLoop.getFrameIndex(); + if (curFrame > lastFrame) { + stepSimulation(deltaTime); + } + else if (curFrame < lastFrame) { + // we looped around, so restart the sim and only sim up to the point + // since the beginning of the frame range. + resetSimulation(); + stepSimulation((curFrame - _animationLoop.getFirstFrame()) / _animationLoop.getFPS()); + } + } + else { + _lastAnimated = now; + } - // update the dimensions - glm::vec3 dims; - dims.x = glm::max(glm::abs(pa_xmin), glm::abs(pa_xmax)); - dims.y = glm::max(glm::abs(pa_xmin), glm::abs(pa_xmax)); - dims.z = glm::max(glm::abs(pa_xmin), glm::abs(pa_xmax)); - setDimensionsInMeters(dims); + // update the dimensions + glm::vec3 dims; + dims.x = glm::max(glm::abs(_paXmin), glm::abs(_paXmax)) * 2.0; + dims.y = glm::max(glm::abs(_paYmin), glm::abs(_paYmax)) * 2.0; + dims.z = glm::max(glm::abs(_paZmin), glm::abs(_paZmax)) * 2.0; + setDimensionsInMeters(dims); - EntityItem::update(now); // let our base class handle it's updates... + EntityItem::update(now); // let our base class handle it's updates... } void ParticleEffectEntityItem::debugDump() const { - quint64 now = usecTimestampNow(); - qDebug() << "PA EFFECT EntityItem id:" << getEntityItemID() << "---------------------------------------------"; - qDebug() << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; - qDebug() << " position:" << debugTreeVector(_position); - qDebug() << " dimensions:" << debugTreeVector(_dimensions); - qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now); + quint64 now = usecTimestampNow(); + qDebug() << "PA EFFECT EntityItem id:" << getEntityItemID() << "---------------------------------------------"; + qDebug() << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; + qDebug() << " position:" << debugTreeVector(_position); + qDebug() << " dimensions:" << debugTreeVector(_dimensions); + qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now); } void ParticleEffectEntityItem::updateShapeType(ShapeType type) { - if (type != _shapeType) { - _shapeType = type; - _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; - } + if (type != _shapeType) { + _shapeType = type; + _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; + } } void ParticleEffectEntityItem::setAnimationFrameIndex(float value) { #ifdef WANT_DEBUG - if (isAnimatingSomething()) { - qDebug() << "ParticleEffectEntityItem::setAnimationFrameIndex()"; - qDebug() << " value:" << value; - qDebug() << " was:" << _animationLoop.getFrameIndex(); - } + if (isAnimatingSomething()) { + qDebug() << "ParticleEffectEntityItem::setAnimationFrameIndex()"; + qDebug() << " value:" << value; + qDebug() << " was:" << _animationLoop.getFrameIndex(); + } #endif - _animationLoop.setFrameIndex(value); + _animationLoop.setFrameIndex(value); } void ParticleEffectEntityItem::setAnimationSettings(const QString& value) { - // the animations setting is a JSON string that may contain various animation settings. - // if it includes fps, frameIndex, or running, those values will be parsed out and - // will over ride the regular animation settings + // the animations setting is a JSON string that may contain various animation settings. + // if it includes fps, frameIndex, or running, those values will be parsed out and + // will over ride the regular animation settings - QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); - QJsonObject settingsAsJsonObject = settingsAsJson.object(); - QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); - if (settingsMap.contains("fps")) { - float fps = settingsMap["fps"].toFloat(); - setAnimationFPS(fps); - } + QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); + QJsonObject settingsAsJsonObject = settingsAsJson.object(); + QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); + if (settingsMap.contains("fps")) { + float fps = settingsMap["fps"].toFloat(); + setAnimationFPS(fps); + } - if (settingsMap.contains("frameIndex")) { - float frameIndex = settingsMap["frameIndex"].toFloat(); + if (settingsMap.contains("frameIndex")) { + float frameIndex = settingsMap["frameIndex"].toFloat(); #ifdef WANT_DEBUG - if (isAnimatingSomething()) { - qDebug() << "ParticleEffectEntityItem::setAnimationSettings() calling setAnimationFrameIndex()..."; - qDebug() << " settings:" << value; - qDebug() << " settingsMap[frameIndex]:" << settingsMap["frameIndex"]; - qDebug(" frameIndex: %20.5f", frameIndex); - } + if (isAnimatingSomething()) { + qDebug() << "ParticleEffectEntityItem::setAnimationSettings() calling setAnimationFrameIndex()..."; + qDebug() << " settings:" << value; + qDebug() << " settingsMap[frameIndex]:" << settingsMap["frameIndex"]; + qDebug(" frameIndex: %20.5f", frameIndex); + } #endif - setAnimationFrameIndex(frameIndex); - } + setAnimationFrameIndex(frameIndex); + } - if (settingsMap.contains("running")) { - bool running = settingsMap["running"].toBool(); - if (running != getAnimationIsPlaying()) { - setAnimationIsPlaying(running); - } - } + if (settingsMap.contains("running")) { + bool running = settingsMap["running"].toBool(); + if (running != getAnimationIsPlaying()) { + setAnimationIsPlaying(running); + } + } - if (settingsMap.contains("firstFrame")) { - float firstFrame = settingsMap["firstFrame"].toFloat(); - setAnimationFirstFrame(firstFrame); - } + if (settingsMap.contains("firstFrame")) { + float firstFrame = settingsMap["firstFrame"].toFloat(); + setAnimationFirstFrame(firstFrame); + } - if (settingsMap.contains("lastFrame")) { - float lastFrame = settingsMap["lastFrame"].toFloat(); - setAnimationLastFrame(lastFrame); - } + if (settingsMap.contains("lastFrame")) { + float lastFrame = settingsMap["lastFrame"].toFloat(); + setAnimationLastFrame(lastFrame); + } - if (settingsMap.contains("loop")) { - bool loop = settingsMap["loop"].toBool(); - setAnimationLoop(loop); - } + if (settingsMap.contains("loop")) { + bool loop = settingsMap["loop"].toBool(); + setAnimationLoop(loop); + } - if (settingsMap.contains("hold")) { - bool hold = settingsMap["hold"].toBool(); - setAnimationHold(hold); - } + if (settingsMap.contains("hold")) { + bool hold = settingsMap["hold"].toBool(); + setAnimationHold(hold); + } - if (settingsMap.contains("startAutomatically")) { - bool startAutomatically = settingsMap["startAutomatically"].toBool(); - setAnimationStartAutomatically(startAutomatically); - } + if (settingsMap.contains("startAutomatically")) { + bool startAutomatically = settingsMap["startAutomatically"].toBool(); + setAnimationStartAutomatically(startAutomatically); + } - _animationSettings = value; - _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationSettings = value; + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; } void ParticleEffectEntityItem::setAnimationIsPlaying(bool value) { - _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; - _animationLoop.setRunning(value); + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationLoop.setRunning(value); } void ParticleEffectEntityItem::setAnimationFPS(float value) { - _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; - _animationLoop.setFPS(value); + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _animationLoop.setFPS(value); } QString ParticleEffectEntityItem::getAnimationSettings() const { - // the animations setting is a JSON string that may contain various animation settings. - // if it includes fps, frameIndex, or running, those values will be parsed out and - // will over ride the regular animation settings - QString value = _animationSettings; + // the animations setting is a JSON string that may contain various animation settings. + // if it includes fps, frameIndex, or running, those values will be parsed out and + // will over ride the regular animation settings + QString value = _animationSettings; - QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); - QJsonObject settingsAsJsonObject = settingsAsJson.object(); - QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); + QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); + QJsonObject settingsAsJsonObject = settingsAsJson.object(); + QVariantMap settingsMap = settingsAsJsonObject.toVariantMap(); - QVariant fpsValue(getAnimationFPS()); - settingsMap["fps"] = fpsValue; + QVariant fpsValue(getAnimationFPS()); + settingsMap["fps"] = fpsValue; - QVariant frameIndexValue(getAnimationFrameIndex()); - settingsMap["frameIndex"] = frameIndexValue; + QVariant frameIndexValue(getAnimationFrameIndex()); + settingsMap["frameIndex"] = frameIndexValue; - QVariant runningValue(getAnimationIsPlaying()); - settingsMap["running"] = runningValue; + QVariant runningValue(getAnimationIsPlaying()); + settingsMap["running"] = runningValue; - QVariant firstFrameValue(getAnimationFirstFrame()); - settingsMap["firstFrame"] = firstFrameValue; + QVariant firstFrameValue(getAnimationFirstFrame()); + settingsMap["firstFrame"] = firstFrameValue; - QVariant lastFrameValue(getAnimationLastFrame()); - settingsMap["lastFrame"] = lastFrameValue; + QVariant lastFrameValue(getAnimationLastFrame()); + settingsMap["lastFrame"] = lastFrameValue; - QVariant loopValue(getAnimationLoop()); - settingsMap["loop"] = loopValue; + QVariant loopValue(getAnimationLoop()); + settingsMap["loop"] = loopValue; - QVariant holdValue(getAnimationHold()); - settingsMap["hold"] = holdValue; + QVariant holdValue(getAnimationHold()); + settingsMap["hold"] = holdValue; - QVariant startAutomaticallyValue(getAnimationStartAutomatically()); - settingsMap["startAutomatically"] = startAutomaticallyValue; + QVariant startAutomaticallyValue(getAnimationStartAutomatically()); + settingsMap["startAutomatically"] = startAutomaticallyValue; - settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap); - QJsonDocument newDocument(settingsAsJsonObject); - QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact); - QString jsonByteString(jsonByteArray); - return jsonByteString; + settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap); + QJsonDocument newDocument(settingsAsJsonObject); + QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact); + QString jsonByteString(jsonByteArray); + return jsonByteString; } -void ParticleEffectEntityItem::stepSim(float deltaTime) -{ - pa_xmin = pa_ymin = pa_zmin = -1.0; - pa_xmax = pa_ymax = pa_zmax = 1.0; +void ParticleEffectEntityItem::stepSimulation(float deltaTime) { + _paXmin = _paYmin = _paZmin = -1.0; + _paXmax = _paYmax = _paZmax = 1.0; - // update particles - quint32 updateIter = pa_head; - while (pa_life[updateIter] > 0.0f) - { - pa_life[updateIter] -= deltaTime; - if (pa_life[updateIter] <= 0.0f) - { - pa_life[updateIter] = -1.0f; - pa_head = (pa_head + 1) % _maxParticles; - pa_count--; - } - else - { - // DUMB FORWARD EULER just to get it done - int j = updateIter * 3; - pa_position[j] += pa_velocity[j] * deltaTime; - pa_position[j+1] += pa_velocity[j+1] * deltaTime; - pa_position[j+2] += pa_velocity[j+2] * deltaTime; + // update particles + quint32 updateIter = _paHead; + while (_paLife[updateIter] > 0.0f) { + _paLife[updateIter] -= deltaTime; + if (_paLife[updateIter] <= 0.0f) { + _paLife[updateIter] = -1.0f; + _paHead = (_paHead + 1) % _maxParticles; + _paCount--; + } + else { + // DUMB FORWARD EULER just to get it done + int j = updateIter * XYZ_STRIDE; + _paPosition[j] += _paVelocity[j] * deltaTime; + _paPosition[j+1] += _paVelocity[j+1] * deltaTime; + _paPosition[j+2] += _paVelocity[j+2] * deltaTime; - pa_xmin = glm::min(pa_xmin, pa_position[j]); - pa_ymin = glm::min(pa_ymin, pa_position[j+1]); - pa_zmin = glm::min(pa_zmin, pa_position[j+2]); - pa_xmax = glm::max(pa_xmax, pa_position[j]); - pa_ymax = glm::max(pa_ymax, pa_position[j + 1]); - pa_zmax = glm::max(pa_zmax, pa_position[j + 2]); + _paXmin = glm::min(_paXmin, _paPosition[j]); + _paYmin = glm::min(_paYmin, _paPosition[j+1]); + _paZmin = glm::min(_paZmin, _paPosition[j+2]); + _paXmax = glm::max(_paXmax, _paPosition[j]); + _paYmax = glm::max(_paYmax, _paPosition[j + 1]); + _paZmax = glm::max(_paZmax, _paPosition[j + 2]); - // massless particles - pa_velocity[j + 1] += deltaTime * _localGravity; - } - updateIter = (updateIter + 1) % _maxParticles; - } + // massless particles + _paVelocity[j + 1] += deltaTime * _localGravity; + } + updateIter = (updateIter + 1) % _maxParticles; + } - // emit new particles - quint32 pa_emit_idx = updateIter; - partial_emit += ((float)_emitRate) * deltaTime; - quint32 birthed = (quint32)partial_emit; - partial_emit -= (float)birthed; - glm::vec3 randOffset; + // emit new particles + quint32 emitIdx = updateIter; + _partialEmit += ((float)_emitRate) * deltaTime; + quint32 birthed = (quint32)_partialEmit; + _partialEmit -= (float)birthed; + glm::vec3 randOffset; - for (quint32 i = 0; i < birthed; i++) - { - if (pa_life[pa_emit_idx] < 0.0f) - { - int j = pa_emit_idx * 3; - pa_life[pa_emit_idx] = _lifespan; - randOffset.x = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; - randOffset.y = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; - randOffset.z = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; - pa_velocity[j] = (_emitDirection.x * _emitStrength) + randOffset.x; - pa_velocity[j + 1] = (_emitDirection.y * _emitStrength) + randOffset.y; - pa_velocity[j + 2] = (_emitDirection.z * _emitStrength) + randOffset.z; + for (quint32 i = 0; i < birthed; i++) { + if (_paLife[emitIdx] < 0.0f) { + int j = emitIdx * XYZ_STRIDE; + _paLife[emitIdx] = _lifespan; + randOffset.x = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; + randOffset.y = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; + randOffset.z = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength; + _paVelocity[j] = (_emitDirection.x * _emitStrength) + randOffset.x; + _paVelocity[j + 1] = (_emitDirection.y * _emitStrength) + randOffset.y; + _paVelocity[j + 2] = (_emitDirection.z * _emitStrength) + randOffset.z; - // DUMB FORWARD EULER just to get it done - pa_position[j] += pa_velocity[j] * deltaTime; - pa_position[j + 1] += pa_velocity[j + 1] * deltaTime; - pa_position[j + 2] += pa_velocity[j + 2] * deltaTime; + // DUMB FORWARD EULER just to get it done + _paPosition[j] += _paVelocity[j] * deltaTime; + _paPosition[j + 1] += _paVelocity[j + 1] * deltaTime; + _paPosition[j + 2] += _paVelocity[j + 2] * deltaTime; - pa_xmin = glm::min(pa_xmin, pa_position[j]); - pa_ymin = glm::min(pa_ymin, pa_position[j + 1]); - pa_zmin = glm::min(pa_zmin, pa_position[j + 2]); - pa_xmax = glm::max(pa_xmax, pa_position[j]); - pa_ymax = glm::max(pa_ymax, pa_position[j + 1]); - pa_zmax = glm::max(pa_zmax, pa_position[j + 2]); + _paXmin = glm::min(_paXmin, _paPosition[j]); + _paYmin = glm::min(_paYmin, _paPosition[j + 1]); + _paZmin = glm::min(_paZmin, _paPosition[j + 2]); + _paXmax = glm::max(_paXmax, _paPosition[j]); + _paYmax = glm::max(_paYmax, _paPosition[j + 1]); + _paZmax = glm::max(_paZmax, _paPosition[j + 2]); - // massless particles - pa_velocity[j + 1] += deltaTime * _localGravity; + // massless particles + // and simple gravity down + _paVelocity[j + 1] += deltaTime * _localGravity; - pa_emit_idx = (pa_emit_idx + 1) % _maxParticles; - pa_count++; - } - else - break; - } + emitIdx = (emitIdx + 1) % _maxParticles; + _paCount++; + } + else + break; + } } -void ParticleEffectEntityItem::resetSim() -{ - for (int i = 0; i < _maxParticles; i++) - { - int j = i * 3; - pa_life[i] = -1.0f; - pa_position[j] = 0.0f; - pa_position[j+1] = 0.0f; - pa_position[j+2] = 0.0f; - pa_velocity[j] = 0.0f; - pa_velocity[j+1] = 0.0f; - pa_velocity[j+2] = 0.0f; - } - pa_count = 0; - pa_head = 0; - partial_emit = 0.0f; +void ParticleEffectEntityItem::resetSimulation() { + for (int i = 0; i < _maxParticles; i++) { + int j = i * XYZ_STRIDE; + _paLife[i] = -1.0f; + _paPosition[j] = 0.0f; + _paPosition[j+1] = 0.0f; + _paPosition[j+2] = 0.0f; + _paVelocity[j] = 0.0f; + _paVelocity[j+1] = 0.0f; + _paVelocity[j+2] = 0.0f; + } + _paCount = 0; + _paHead = 0; + _partialEmit = 0.0f; - srand((unsigned int) this); + srand(_randSeed); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 1306620bc6..b00eb94685 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -39,141 +39,143 @@ class ParticleEffectEntityItem : public EntityItem { public: - - static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); - ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - virtual ~ParticleEffectEntityItem(); + ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); + virtual ~ParticleEffectEntityItem(); - ALLOW_INSTANTIATION // This class can be instantiated - - // methods for getting/setting all properties of this entity - virtual EntityItemProperties getProperties() const; - virtual bool setProperties(const EntityItemProperties& properties); + ALLOW_INSTANTIATION // This class can be instantiated + + // methods for getting/setting all properties of this entity + virtual EntityItemProperties getProperties() const; + virtual bool setProperties(const EntityItemProperties& properties); - virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; + virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; - virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, - EntityPropertyFlags& requestedProperties, - EntityPropertyFlags& propertyFlags, - EntityPropertyFlags& propertiesDidntFit, - int& propertyCount, - OctreeElement::AppendState& appendState) const; + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const; - virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, - ReadBitstreamToTreeParams& args, - EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData); - virtual void update(const quint64& now); - virtual bool needsToCallUpdate() const; + virtual void update(const quint64& now); + virtual bool needsToCallUpdate() const; - const rgbColor& getColor() const { return _color; } - xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } + const rgbColor& getColor() const { return _color; } + xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } - void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } - void setColor(const xColor& value) { - _color[RED_INDEX] = value.red; - _color[GREEN_INDEX] = value.green; - _color[BLUE_INDEX] = value.blue; - } + void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } + void setColor(const xColor& value) { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + } - void updateShapeType(ShapeType type); - virtual ShapeType getShapeType() const { return _shapeType; } + void updateShapeType(ShapeType type); + virtual ShapeType getShapeType() const { return _shapeType; } - virtual void debugDump() const; + virtual void debugDump() const; - static const float DEFAULT_ANIMATION_FRAME_INDEX; - void setAnimationFrameIndex(float value); - void setAnimationSettings(const QString& value); + static const float DEFAULT_ANIMATION_FRAME_INDEX; + void setAnimationFrameIndex(float value); + void setAnimationSettings(const QString& value); - static const bool DEFAULT_ANIMATION_IS_PLAYING; - void setAnimationIsPlaying(bool value); + static const bool DEFAULT_ANIMATION_IS_PLAYING; + void setAnimationIsPlaying(bool value); - static const float DEFAULT_ANIMATION_FPS; - void setAnimationFPS(float value); + static const float DEFAULT_ANIMATION_FPS; + void setAnimationFPS(float value); - void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); } - bool getAnimationLoop() const { return _animationLoop.getLoop(); } + void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); } + bool getAnimationLoop() const { return _animationLoop.getLoop(); } - void setAnimationHold(bool hold) { _animationLoop.setHold(hold); } - bool getAnimationHold() const { return _animationLoop.getHold(); } + void setAnimationHold(bool hold) { _animationLoop.setHold(hold); } + bool getAnimationHold() const { return _animationLoop.getHold(); } - void setAnimationStartAutomatically(bool startAutomatically) { _animationLoop.setStartAutomatically(startAutomatically); } - bool getAnimationStartAutomatically() const { return _animationLoop.getStartAutomatically(); } + void setAnimationStartAutomatically(bool startAutomatically) { _animationLoop.setStartAutomatically(startAutomatically); } + bool getAnimationStartAutomatically() const { return _animationLoop.getStartAutomatically(); } - void setAnimationFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); } - float getAnimationFirstFrame() const { return _animationLoop.getFirstFrame(); } + void setAnimationFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); } + float getAnimationFirstFrame() const { return _animationLoop.getFirstFrame(); } - void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); } - float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } + void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); } + float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } - static const quint32 DEFAULT_MAX_PARTICLES; - void setMaxParticles(quint32 maxParticles) { _maxParticles = maxParticles; } - quint32 getMaxParticles() const { return _maxParticles; } + static const quint32 DEFAULT_MAX_PARTICLES; + void setMaxParticles(quint32 maxParticles) { _maxParticles = maxParticles; } + quint32 getMaxParticles() const { return _maxParticles; } - static const float DEFAULT_LIFESPAN; - void setLifespan(float lifespan) { _lifespan = lifespan; } - float getLifespan() const { return _lifespan; } + static const float DEFAULT_LIFESPAN; + void setLifespan(float lifespan) { _lifespan = lifespan; } + float getLifespan() const { return _lifespan; } - static const float DEFAULT_EMIT_RATE; - void setEmitRate(float emitRate) { _emitRate = emitRate; } - float getEmitRate() const { return _emitRate; } + static const float DEFAULT_EMIT_RATE; + void setEmitRate(float emitRate) { _emitRate = emitRate; } + float getEmitRate() const { return _emitRate; } - static const glm::vec3 DEFAULT_EMIT_DIRECTION; - void setEmitDirection(glm::vec3 emitDirection) { _emitDirection = emitDirection; } - const glm::vec3& getEmitDirection() const { return _emitDirection; } + static const glm::vec3 DEFAULT_EMIT_DIRECTION; + void setEmitDirection(glm::vec3 emitDirection) { _emitDirection = emitDirection; } + const glm::vec3& getEmitDirection() const { return _emitDirection; } - static const float DEFAULT_EMIT_STRENGTH; - void setEmitStrength(float emitStrength) { _emitStrength = emitStrength; } - float getEmitStrength() const { return _emitStrength; } + static const float DEFAULT_EMIT_STRENGTH; + void setEmitStrength(float emitStrength) { _emitStrength = emitStrength; } + float getEmitStrength() const { return _emitStrength; } - static const float DEFAULT_LOCAL_GRAVITY; - void setLocalGravity(float localGravity) { _localGravity = localGravity; } - float getLocalGravity() const { return _localGravity; } + static const float DEFAULT_LOCAL_GRAVITY; + void setLocalGravity(float localGravity) { _localGravity = localGravity; } + float getLocalGravity() const { return _localGravity; } - static const float DEFAULT_PARTICLE_RADIUS; - void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } - float getParticleRadius() const { return _particleRadius; } + static const float DEFAULT_PARTICLE_RADIUS; + void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } + float getParticleRadius() const { return _particleRadius; } - bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } - float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); } - float getAnimationFPS() const { return _animationLoop.getFPS(); } - QString getAnimationSettings() const; + bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } + float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); } + float getAnimationFPS() const { return _animationLoop.getFPS(); } + QString getAnimationSettings() const; protected: - bool isAnimatingSomething() const; - void stepSim(float deltaTime); - void resetSim(); + bool isAnimatingSomething() const; + void stepSimulation(float deltaTime); + void resetSimulation(); - // the properties of this entity - rgbColor _color; - quint32 _maxParticles; - float _lifespan; - float _emitRate; - glm::vec3 _emitDirection; - float _emitStrength; - float _localGravity; - float _particleRadius; - quint64 _lastAnimated; - AnimationLoop _animationLoop; - QString _animationSettings; - ShapeType _shapeType = SHAPE_TYPE_NONE; + // the properties of this entity + rgbColor _color; + quint32 _maxParticles; + float _lifespan; + float _emitRate; + glm::vec3 _emitDirection; + float _emitStrength; + float _localGravity; + float _particleRadius; + quint64 _lastAnimated; + AnimationLoop _animationLoop; + QString _animationSettings; + ShapeType _shapeType = SHAPE_TYPE_NONE; - // all the internals of running the particle sim - float* pa_life; - float* pa_position; - float* pa_velocity; - float partial_emit; - quint32 pa_count; - quint32 pa_head; - float pa_xmin; - float pa_xmax; - float pa_ymin; - float pa_ymax; - float pa_zmin; - float pa_zmax; + // all the internals of running the particle sim + const quint32 XYZ_STRIDE = 3; + float* _paLife; + float* _paPosition; + float* _paVelocity; + float _partialEmit; + quint32 _paCount; + quint32 _paHead; + float _paXmin; + float _paXmax; + float _paYmin; + float _paYmax; + float _paZmin; + float _paZmax; + unsigned int _randSeed; }; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 2eee540fff..0aaa27e17f 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; + return VERSION_ENTITIES_HAS_PARTICLES; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index e593955b51..8e15c64b4b 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -129,5 +129,6 @@ const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6; const PacketVersion VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME = 7; const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE = 8; const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; +const PacketVersion VERSION_ENTITIES_HAS_PARTICLES = 10; #endif // hifi_PacketHeaders_h From cfcc4679e13ba13f351dd2890c5833f3ee9264e4 Mon Sep 17 00:00:00 2001 From: Jason <2billbrasky@gmail.com> Date: Fri, 6 Mar 2015 15:57:38 -0800 Subject: [PATCH 46/56] Interview project updates (2). Oops, I forgot to convert tabs-to-spaces on EntityTreeRenderer. Committing it now. --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 3db4ffb2ac..ce946af93c 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -54,7 +54,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory) - REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory) + REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory) _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID From f5352333f06167f238cd6a68c7095bb45aa50518 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Fri, 6 Mar 2015 16:42:06 -0800 Subject: [PATCH 47/56] entities use radians per second for angular velocity --- .../src/octree/OctreePacketProcessor.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 25 +++++++++---------- libraries/entities/src/EntityItem.h | 1 + libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 2 +- libraries/physics/src/EntityMotionState.cpp | 9 +++---- 6 files changed, 19 insertions(+), 22 deletions(-) diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index f87e978b66..92eb7f7f31 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -61,7 +61,7 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, // check version of piggyback packet against expected version if (packetVersion != expectedVersion // TODO: remove the temporary exception below when everyone is using meters instead of DomainUnits - && !(PacketTypeEntityData == voxelPacketType && packetVersion < VERSION_ENTITIES_USE_METERS)) { + && !(PacketTypeEntityData == voxelPacketType && packetVersion < VERSION_ENTITIES_USE_METERS_AND_RADIANS)) { static QMultiMap<QUuid, PacketType> versionDebugSuppressMap; QUuid senderUUID = uuidFromPacketHeader(packet); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5a1712a1f6..093f8cf84c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -501,7 +501,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef EntityPropertyFlags propertyFlags = encodedPropertyFlags; dataAt += propertyFlags.getEncodedLength(); bytesRead += propertyFlags.getEncodedLength(); - bool useMeters = (args.bitstreamVersion == VERSION_ENTITIES_USE_METERS); + bool useMeters = (args.bitstreamVersion == VERSION_ENTITIES_USE_METERS_AND_RADIANS); if (useMeters) { READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePosition); } else { @@ -540,7 +540,11 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT, setScript); READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, _registrationPoint); - READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); + if (useMeters) { + READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); + } else { + READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees); + } READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, _angularDamping); READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, _visible); READ_ENTITY_PROPERTY_SETTER(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions); @@ -683,41 +687,36 @@ void EntityItem::simulate(const quint64& now) { void EntityItem::simulateKinematicMotion(float timeElapsed) { if (hasAngularVelocity()) { // angular damping - glm::vec3 angularVelocity = getAngularVelocity(); if (_angularDamping > 0.0f) { - angularVelocity *= powf(1.0f - _angularDamping, timeElapsed); + _angularVelocity *= powf(1.0f - _angularDamping, timeElapsed); #ifdef WANT_DEBUG qDebug() << " angularDamping :" << _angularDamping; - qDebug() << " newAngularVelocity:" << angularVelocity; + qDebug() << " newAngularVelocity:" << _angularVelocity; #endif - setAngularVelocity(angularVelocity); } float angularSpeed = glm::length(_angularVelocity); - const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.1f; // + const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.0017453f; // 0.0017453 rad/sec = 0.1f degrees/sec if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) { if (angularSpeed > 0.0f) { _dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE; } - setAngularVelocity(ENTITY_ITEM_ZERO_VEC3); + _angularVelocity = ENTITY_ITEM_ZERO_VEC3; } else { - // NOTE: angularSpeed is currently in degrees/sec!!! - // TODO: Andrew to convert to radians/sec - glm::vec3 angularVelocity = glm::radians(_angularVelocity); // for improved agreement with the way Bullet integrates rotations we use an approximation // and break the integration into bullet-sized substeps glm::quat rotation = getRotation(); float dt = timeElapsed; while (dt > PHYSICS_ENGINE_FIXED_SUBSTEP) { - glm::quat dQ = computeBulletRotationStep(angularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP); + glm::quat dQ = computeBulletRotationStep(_angularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP); rotation = glm::normalize(dQ * rotation); dt -= PHYSICS_ENGINE_FIXED_SUBSTEP; } // NOTE: this final partial substep can drift away from a real Bullet simulation however // it only becomes significant for rapidly rotating objects // (e.g. around PI/4 radians per substep, or 7.5 rotations/sec at 60 substeps/sec). - glm::quat dQ = computeBulletRotationStep(angularVelocity, dt); + glm::quat dQ = computeBulletRotationStep(_angularVelocity, dt); rotation = glm::normalize(dQ * rotation); setRotation(rotation); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 0f8139eea5..5193aa4490 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -275,6 +275,7 @@ public: void updateGravityInDomainUnits(const glm::vec3& value); void updateGravity(const glm::vec3& value); void updateAngularVelocity(const glm::vec3& value); + void updateAngularVelocityInDegrees(const glm::vec3& value) { updateAngularVelocity(glm::radians(value)); } void updateAngularDamping(float value); void updateIgnoreForCollisions(bool value); void updateCollisionsWillMove(bool value); diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 6150ba5a9e..c7f1f4ec88 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_USE_METERS; + return VERSION_ENTITIES_USE_METERS_AND_RADIANS; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index dd0e166ea8..731be118af 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -129,7 +129,7 @@ const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6; const PacketVersion VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME = 7; const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE = 8; const PacketVersion VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES = 9; -const PacketVersion VERSION_ENTITIES_USE_METERS = 10; +const PacketVersion VERSION_ENTITIES_USE_METERS_AND_RADIANS = 10; const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c35ace6b11..cd0769255b 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -99,8 +99,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { _entity->setVelocity(v); getAngularVelocity(v); - // DANGER! EntityItem stores angularVelocity in degrees/sec!!! - _entity->setAngularVelocity(glm::degrees(v)); + _entity->setAngularVelocity(v); _entity->setLastSimulated(usecTimestampNow()); @@ -159,8 +158,7 @@ void EntityMotionState::updateObjectVelocities() { _sentVelocity = _entity->getVelocity(); setVelocity(_sentVelocity); - // DANGER! EntityItem stores angularVelocity in degrees/sec!!! - _sentAngularVelocity = glm::radians(_entity->getAngularVelocity()); + _sentAngularVelocity = _entity->getAngularVelocity(); setAngularVelocity(_sentAngularVelocity); _sentAcceleration = _entity->getGravity(); @@ -219,8 +217,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setVelocity(_sentVelocity); _sentAcceleration = bulletToGLM(_body->getGravity()); properties.setGravity(_sentAcceleration); - // DANGER! EntityItem stores angularVelocity in degrees/sec!!! - properties.setAngularVelocity(glm::degrees(_sentAngularVelocity)); + properties.setAngularVelocity(_sentAngularVelocity); } // RELIABLE_SEND_HACK: count number of updates for entities at rest so we can stop sending them after some limit. From d112c455e2f1c7d43750a5a320535a1568b004cd Mon Sep 17 00:00:00 2001 From: David Rowe <david@ctrlaltstudio.com> Date: Fri, 6 Mar 2015 17:49:31 -0800 Subject: [PATCH 48/56] Add hmdDefaults.js script --- examples/hmdDefaults.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 examples/hmdDefaults.js diff --git a/examples/hmdDefaults.js b/examples/hmdDefaults.js new file mode 100644 index 0000000000..0096b11777 --- /dev/null +++ b/examples/hmdDefaults.js @@ -0,0 +1,16 @@ +// +// hmdDefaults.js +// examples +// +// Created by David Rowe on 6 Mar 2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +Script.load("progress.js"); +Script.load("lobby.js"); +Script.load("notifications.js"); +Script.load("controllers/oculus/goTo.js"); +//Script.load("scripts.js"); // Not created yet From 7088c0287aeea192a7b1fd5ad6ff99fc0584d474 Mon Sep 17 00:00:00 2001 From: ZappoMan <bradh@konamoxt.com> Date: Fri, 6 Mar 2015 18:29:22 -0800 Subject: [PATCH 49/56] different mixamo detection --- interface/src/ModelUploader.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index a2b729ad39..6740ea9634 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -314,14 +314,16 @@ void ModelUploader::populateBasicMapping(QVariantHash& mapping, QString filename // mixamo blendshapes - in the event that a mixamo file was edited by some other tool, it's likely the applicationName will // be rewritten, so we detect the existence of several different blendshapes which indicate we're likely a mixamo file bool likelyMixamoFile = geometry.applicationName == "mixamo.com" || - (geometry.blendshapeChannelNames.contains("BrowsDown_Left") && + (geometry.blendshapeChannelNames.contains("Facial_Blends") && geometry.blendshapeChannelNames.contains("BrowsDown_Right") && geometry.blendshapeChannelNames.contains("MouthOpen") && - geometry.blendshapeChannelNames.contains("TongueUp") && - geometry.blendshapeChannelNames.contains("MouthWhistle_NarrowAdjust_Left") && - geometry.blendshapeChannelNames.contains("NoseScrunch_Left") && + geometry.blendshapeChannelNames.contains("Blink_Left") && + geometry.blendshapeChannelNames.contains("Blink_Right") && geometry.blendshapeChannelNames.contains("Squint_Right")); - + +qDebug() << "likelyMixamoFile:" << likelyMixamoFile; +qDebug() << "geometry.blendshapeChannelNames:" << geometry.blendshapeChannelNames; + if (!mapping.contains(BLENDSHAPE_FIELD) && likelyMixamoFile) { QVariantHash blendshapes; blendshapes.insertMulti("BrowsD_L", QVariantList() << "BrowsDown_Left" << 1.0); From 5b854857c19d54488d5dc01f372c6729fee67660 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Sat, 7 Mar 2015 18:02:41 -0800 Subject: [PATCH 50/56] fix JS scripts to use radians per second in entity properties --- examples/controllers/hydra/toyball.js | 2 -- examples/dice.js | 6 ++-- examples/example/entities/spotlightExample.js | 4 ++- examples/html/entityProperties.html | 30 +++++++++++++++---- examples/libraries/entityPropertyDialogBox.js | 17 +++++++---- examples/planets.js | 6 ++-- examples/popcorn.js | 7 +++-- examples/walk.js | 2 +- 8 files changed, 53 insertions(+), 21 deletions(-) diff --git a/examples/controllers/hydra/toyball.js b/examples/controllers/hydra/toyball.js index 5306769e95..89085fad19 100644 --- a/examples/controllers/hydra/toyball.js +++ b/examples/controllers/hydra/toyball.js @@ -92,7 +92,6 @@ function checkControllerSide(whichSide) { Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[0])); linearVelocity = averageLinearVelocity[0]; angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(LEFT_TIP)); - angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity); } else { BUTTON_FWD = RIGHT_BUTTON_FWD; BUTTON_3 = RIGHT_BUTTON_3; @@ -104,7 +103,6 @@ function checkControllerSide(whichSide) { Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[1])); linearVelocity = averageLinearVelocity[1]; angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(RIGHT_TIP)); - angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity); handMessage = "RIGHT"; } diff --git a/examples/dice.js b/examples/dice.js index 1205f38ee1..b0021ecebb 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -53,7 +53,9 @@ function shootDice(position, velocity) { position: position, velocity: velocity, rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), - angularVelocity: { x: Math.random() * 100, y: Math.random() * 100, z: Math.random() * 100 }, + // NOTE: angularVelocity is in radians/sec + var maxAngularSpeed = Math.PI; + angularVelocity: { x: Math.random() * maxAngularSpeed, y: Math.random() * maxAngularSpeed, z: Math.random() * maxAngularSpeed }, lifetime: LIFETIME, gravity: { x: 0, y: GRAVITY, z: 0 }, shapeType: "box", @@ -108,4 +110,4 @@ function scriptEnding() { Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); Controller.mousePressEvent.connect(mousePressEvent); -Script.scriptEnding.connect(scriptEnding); \ No newline at end of file +Script.scriptEnding.connect(scriptEnding); diff --git a/examples/example/entities/spotlightExample.js b/examples/example/entities/spotlightExample.js index 5eb5432f3f..80c89926a3 100644 --- a/examples/example/entities/spotlightExample.js +++ b/examples/example/entities/spotlightExample.js @@ -11,11 +11,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +var DEGREES_TO_RADIANS = Math.PI / 180.0; + var lightProperties = { type: "Light", position: { x: 0, y: 0, z: 0 }, dimensions: { x: 1000, y: 1000, z: 1000 }, - angularVelocity: { x: 0, y: 10, z: 0 }, + angularVelocity: { x: 0, y: 10 * DEGREES_TO_RADIANS, z: 0 }, angularDamping: 0, isSpotlight: true, diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index fd1a4e3821..cb49b86975 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -2,6 +2,10 @@ <head> <link rel="stylesheet" type="text/css" href="style.css"> <script> + var PI = 3.14159265358979; + var DEGREES_TO_RADIANS = PI / 180.0; + var RADIANS_TO_DEGREES = 180.0 / PI; + function enableChildren(el, selector) { els = el.querySelectorAll(selector); for (var i = 0; i < els.length; i++) { @@ -58,6 +62,22 @@ } }; + function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { + return function() { + var data = { + type: "update", + properties: { + } + }; + data.properties[property] = { + x: elX.value * multiplier, + y: elY.value * multiplier, + z: elZ.value * multiplier, + }; + EventBridge.emitWebEvent(JSON.stringify(data)); + } + }; + function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) { return function() { var data = { @@ -227,9 +247,9 @@ elLinearVelocityZ.value = properties.velocity.z.toFixed(2); elLinearDamping.value = properties.damping.toFixed(2); - elAngularVelocityX.value = properties.angularVelocity.x.toFixed(2); - elAngularVelocityY.value = properties.angularVelocity.y.toFixed(2); - elAngularVelocityZ.value = properties.angularVelocity.z.toFixed(2); + elAngularVelocityX.value = (properties.angularVelocity.x * RADIANS_TO_DEGREES).toFixed(2); + elAngularVelocityY.value = (properties.angularVelocity.y * RADIANS_TO_DEGREES).toFixed(2); + elAngularVelocityZ.value = (properties.angularVelocity.z * RADIANS_TO_DEGREES).toFixed(2); elAngularDamping.value = properties.angularDamping.toFixed(2); elGravityX.value = properties.gravity.x.toFixed(2); @@ -352,8 +372,8 @@ elLinearVelocityZ.addEventListener('change', velocityChangeFunction); elLinearDamping.addEventListener('change', createEmitNumberPropertyUpdateFunction('damping')); - var angularVelocityChangeFunction = createEmitVec3PropertyUpdateFunction( - 'angularVelocity', elAngularVelocityX, elAngularVelocityY, elAngularVelocityZ); + var angularVelocityChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier( + 'angularVelocity', elAngularVelocityX, elAngularVelocityY, elAngularVelocityZ, DEGREES_TO_RADIANS); elAngularVelocityX.addEventListener('change', angularVelocityChangeFunction); elAngularVelocityY.addEventListener('change', angularVelocityChangeFunction); elAngularVelocityZ.addEventListener('change', angularVelocityChangeFunction); diff --git a/examples/libraries/entityPropertyDialogBox.js b/examples/libraries/entityPropertyDialogBox.js index 0cb76276d8..7b0d3eb382 100644 --- a/examples/libraries/entityPropertyDialogBox.js +++ b/examples/libraries/entityPropertyDialogBox.js @@ -11,6 +11,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +var DEGREES_TO_RADIANS = Math.PI / 180.0; +var RADIANS_TO_DEGREES = 180.0 / Math.PI; + EntityPropertyDialogBox = (function () { var that = {}; @@ -146,11 +149,12 @@ EntityPropertyDialogBox = (function () { index++; array.push({ label: "Linear Damping:", value: properties.damping.toFixed(decimals) }); index++; - array.push({ label: "Angular Pitch:", value: properties.angularVelocity.x.toFixed(decimals) }); + // NOTE: angular velocity is in radians/sec but we display degrees/sec for users + array.push({ label: "Angular Pitch:", value: (properties.angularVelocity.x * RADIANS_TO_DEGREES).toFixed(decimals) }); index++; - array.push({ label: "Angular Yaw:", value: properties.angularVelocity.y.toFixed(decimals) }); + array.push({ label: "Angular Yaw:", value: (properties.angularVelocity.y * RADIANS_TO_DEGREES).toFixed(decimals) }); index++; - array.push({ label: "Angular Roll:", value: properties.angularVelocity.z.toFixed(decimals) }); + array.push({ label: "Angular Roll:", value: (properties.angularVelocity.z * RADIANS_TO_DEGREES).toFixed(decimals) }); index++; array.push({ label: "Angular Damping:", value: properties.angularDamping.toFixed(decimals) }); index++; @@ -343,9 +347,10 @@ EntityPropertyDialogBox = (function () { properties.velocity.z = array[index++].value; properties.damping = array[index++].value; - properties.angularVelocity.x = array[index++].value; - properties.angularVelocity.y = array[index++].value; - properties.angularVelocity.z = array[index++].value; + // NOTE: angular velocity is in radians/sec but we display degrees/sec for users + properties.angularVelocity.x = array[index++].value * DEGREES_TO_RADIANS; + properties.angularVelocity.y = array[index++].value * DEGREES_TO_RADIANS; + properties.angularVelocity.z = array[index++].value * DEGREES_TO_RADIANS; properties.angularDamping = array[index++].value; properties.gravity.x = array[index++].value; diff --git a/examples/planets.js b/examples/planets.js index 87ed774c93..650119feda 100644 --- a/examples/planets.js +++ b/examples/planets.js @@ -35,13 +35,15 @@ var NUM_INITIAL_PARTICLES = 200; var PARTICLE_MIN_SIZE = 0.50; var PARTICLE_MAX_SIZE = 1.50; var INITIAL_VELOCITY = 5.0; +var DEGREES_TO_RADIANS = Math.PI / 180.0; var planets = []; var particles = []; // Create planets that will extert gravity on test particles for (var i = 0; i < planetTypes.length; i++) { - var rotationalVelocity = 10 + Math.random() * 60; + // NOTE: rotationalVelocity is in radians/sec + var rotationalVelocity = (10 + Math.random() * 60) * DEGREES_TO_RADIANS; var position = { x: planetTypes[i].x, y: planetTypes[i].y, z: planetTypes[i].z }; position = Vec3.multiply(MAX_RANGE / 2, position); position = Vec3.sum(center, position); @@ -118,4 +120,4 @@ function update(deltaTime) { } } -Script.scriptEnding.connect(scriptEnding); \ No newline at end of file +Script.scriptEnding.connect(scriptEnding); diff --git a/examples/popcorn.js b/examples/popcorn.js index 567953ac60..265cc00257 100644 --- a/examples/popcorn.js +++ b/examples/popcorn.js @@ -20,6 +20,8 @@ var GRAVITY = -1.0; var LIFETIME = 600; var DAMPING = 0.50; +var TWO_PI = 2.0 * Math.PI; + var center = Vec3.sum(MyAvatar.position, Vec3.multiply(SCALE * 3.0, Quat.getFront(Camera.getOrientation()))); var floor = Entities.addEntity( @@ -122,7 +124,8 @@ var spinner = Entities.addEntity( position: center, dimensions: { x: SCALE / 1.5, y: SCALE / 3.0, z: SCALE / 8.0 }, color: { red: 255, green: 0, blue: 0 }, - angularVelocity: { x: 0, y: 360, z: 0 }, + // NOTE: angularVelocity is in radians/sec + angularVelocity: { x: 0, y: TWO_PI, z: 0 }, angularDamping: 0.0, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, @@ -179,4 +182,4 @@ function scriptEnding() { } Script.scriptEnding.connect(scriptEnding); -Script.update.connect(update); \ No newline at end of file +Script.update.connect(update); diff --git a/examples/walk.js b/examples/walk.js index be2a1584d4..f0f42c0b4c 100644 --- a/examples/walk.js +++ b/examples/walk.js @@ -849,4 +849,4 @@ function animateAvatar(deltaTime, speed) { MyAvatar.setJointData(jointName, Quat.fromVec3Degrees(jointRotations)); } } -} \ No newline at end of file +} From 61649ee0a59efafe72d2235eb0c0b64b42566b1f Mon Sep 17 00:00:00 2001 From: Atlante45 <clement.brisset@gmail.com> Date: Mon, 9 Mar 2015 13:42:14 +0100 Subject: [PATCH 51/56] Fix dialog labels --- interface/src/ui/DiskCacheEditor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/DiskCacheEditor.cpp b/interface/src/ui/DiskCacheEditor.cpp index 38fd1cb383..2f2b924e13 100644 --- a/interface/src/ui/DiskCacheEditor.cpp +++ b/interface/src/ui/DiskCacheEditor.cpp @@ -62,12 +62,12 @@ void DiskCacheEditor::makeDialog() { path->setAlignment(Qt::AlignRight); layout->addWidget(path, 0, 0); - QLabel* size = new QLabel("Max Size : ", _dialog); + QLabel* size = new QLabel("Current Size : ", _dialog); Q_CHECK_PTR(size); size->setAlignment(Qt::AlignRight); layout->addWidget(size, 1, 0); - QLabel* maxSize = new QLabel("Current Size : ", _dialog); + QLabel* maxSize = new QLabel("Max Size : ", _dialog); Q_CHECK_PTR(maxSize); maxSize->setAlignment(Qt::AlignRight); layout->addWidget(maxSize, 2, 0); From c0ed3edbbbb8d2f76a0e844dfa7a05a4e767be01 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Mon, 9 Mar 2015 09:38:26 -0700 Subject: [PATCH 52/56] remove exception when connecting to old server --- interface/src/octree/OctreePacketProcessor.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index 92eb7f7f31..e735239331 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -1,4 +1,4 @@ -// +/Merge branch 'master' of ssh://github.com/highfidelity/hifi into isentropic/ // OctreePacketProcessor.cpp // interface/src/octree // @@ -59,9 +59,7 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, PacketVersion expectedVersion = versionForPacketType(voxelPacketType); // check version of piggyback packet against expected version - if (packetVersion != expectedVersion - // TODO: remove the temporary exception below when everyone is using meters instead of DomainUnits - && !(PacketTypeEntityData == voxelPacketType && packetVersion < VERSION_ENTITIES_USE_METERS_AND_RADIANS)) { + if (packetVersion != expectedVersion) { static QMultiMap<QUuid, PacketType> versionDebugSuppressMap; QUuid senderUUID = uuidFromPacketHeader(packet); From c3a8c445453a8b0b4bda4fb60c893afe60f06786 Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Mon, 9 Mar 2015 09:55:35 -0700 Subject: [PATCH 53/56] oops, removing a typo --- interface/src/octree/OctreePacketProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index e735239331..34aae97446 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -1,4 +1,4 @@ -/Merge branch 'master' of ssh://github.com/highfidelity/hifi into isentropic/ +//Merge branch 'master' of ssh://github.com/highfidelity/hifi into isentropic/ // OctreePacketProcessor.cpp // interface/src/octree // From e418872f7be52a83d3f1ae7f0d0d76bc286d185a Mon Sep 17 00:00:00 2001 From: Andrew Meadows <andrew@highfidelity.io> Date: Mon, 9 Mar 2015 09:56:15 -0700 Subject: [PATCH 54/56] namechanges: setFooInMeters() --> setFoo() also fixed some warnings, made code abide to standard, and moved some variables to be closer to where they're used --- .../src/RenderableParticleEffectEntityItem.cpp | 8 +++----- .../entities/src/ParticleEffectEntityItem.cpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 9cb8c3912e..b4dd5b4c64 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -31,9 +31,6 @@ RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const Ent void RenderableParticleEffectEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableParticleEffectEntityItem::render"); assert(getType() == EntityTypes::ParticleEffect); - glm::vec3 position = getPositionInMeters(); - glm::vec3 center = getCenterInMeters(); - glm::quat rotation = getRotation(); float pa_rad = getParticleRadius(); const float MAX_COLOR = 255.0f; @@ -75,13 +72,14 @@ void RenderableParticleEffectEntityItem::render(RenderArgs* args) { DependencyManager::get<GeometryCache>()->updateVertices(_cacheID, *pointVec, paColor); glPushMatrix(); + glm::vec3 position = getPosition(); glTranslatef(position.x, position.y, position.z); + glm::quat rotation = getRotation(); glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; + glm::vec3 positionToCenter = getCenter() - position; glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); DependencyManager::get<GeometryCache>()->renderVertices(gpu::QUADS, _cacheID); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 31b002b23f..b902dd63b8 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -268,10 +268,10 @@ void ParticleEffectEntityItem::update(const quint64& now) { // update the dimensions glm::vec3 dims; - dims.x = glm::max(glm::abs(_paXmin), glm::abs(_paXmax)) * 2.0; - dims.y = glm::max(glm::abs(_paYmin), glm::abs(_paYmax)) * 2.0; - dims.z = glm::max(glm::abs(_paZmin), glm::abs(_paZmax)) * 2.0; - setDimensionsInMeters(dims); + dims.x = glm::max(glm::abs(_paXmin), glm::abs(_paXmax)) * 2.0f; + dims.y = glm::max(glm::abs(_paYmin), glm::abs(_paYmax)) * 2.0f; + dims.z = glm::max(glm::abs(_paZmin), glm::abs(_paZmax)) * 2.0f; + setDimensions(dims); EntityItem::update(now); // let our base class handle it's updates... } @@ -418,8 +418,8 @@ QString ParticleEffectEntityItem::getAnimationSettings() const { } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { - _paXmin = _paYmin = _paZmin = -1.0; - _paXmax = _paYmax = _paZmax = 1.0; + _paXmin = _paYmin = _paZmin = -1.0f; + _paXmax = _paYmax = _paZmax = 1.0f; // update particles quint32 updateIter = _paHead; @@ -493,8 +493,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } void ParticleEffectEntityItem::resetSimulation() { - for (int i = 0; i < _maxParticles; i++) { - int j = i * XYZ_STRIDE; + for (quint32 i = 0; i < _maxParticles; i++) { + quint32 j = i * XYZ_STRIDE; _paLife[i] = -1.0f; _paPosition[j] = 0.0f; _paPosition[j+1] = 0.0f; From 559945c0c6ac34118f0af1c3f14d15d302670da3 Mon Sep 17 00:00:00 2001 From: ZappoMan <bradh@konamoxt.com> Date: Mon, 9 Mar 2015 10:50:09 -0700 Subject: [PATCH 55/56] temporarily remove skeleton check from upload --- interface/src/ModelUploader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 9a56a75798..f1c5def149 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -178,6 +178,7 @@ bool ModelUploader::zip() { QByteArray fbxContents = fbx.readAll(); FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); + #if 0 /// Temporarily remove this check until CtrlAltDavid can come up with a fix. // Make sure that a skeleton model has a skeleton if (_modelType == SKELETON_MODEL) { if (geometry.rootJointIndex == -1) { @@ -193,6 +194,7 @@ bool ModelUploader::zip() { return false; } } + #endif // make sure we have some basic mappings populateBasicMapping(mapping, filename, geometry); From 9ccd0a5afa5dbb67fcb1872592d82f6b2baadd4e Mon Sep 17 00:00:00 2001 From: Leonardo Murillo <leo@highfidelity.io> Date: Mon, 9 Mar 2015 14:12:47 -0600 Subject: [PATCH 56/56] Fixing updater --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b4e6f82fde..6bb4a20095 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -151,7 +151,7 @@ static QTimer* billboardPacketTimer = NULL; static QTimer* checkFPStimer = NULL; static QTimer* idleTimer = NULL; -const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; +const QString CHECK_VERSION_URL = "https://highfidelity.com/latestVersion.xml"; const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";