diff --git a/examples/butterflies.js b/examples/butterflies.js index 069a0d6792..edc33f7625 100644 --- a/examples/butterflies.js +++ b/examples/butterflies.js @@ -103,6 +103,9 @@ function updateButterflies(deltaTime) { var CHANCE_OF_IMPULSE = 0.04; for (var i = 0; i < numButterflies; i++) { if (Math.random() < CHANCE_OF_IMPULSE) { + if (!butterflies[i].isKnownID) { + butterflies[i] = Entities.identifyEntity(butterflies[i]); + } var properties = Entities.getEntityProperties(butterflies[i]); if (Vec3.length(Vec3.subtract(properties.position, flockPosition)) > range) { Entities.editEntity(butterflies[i], { position: flockPosition } ); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 22d956886a..8ab2992659 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -160,7 +160,7 @@ public: float getLargestDimension() 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 - void setDimensions(const glm::vec3& value) { _dimensions = value; recalculateCollisionShape(); } + virtual void setDimensions(const glm::vec3& value) { _dimensions = value; recalculateCollisionShape(); } /// 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); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d3d9e2da53..5f9aa4a159 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -19,9 +19,13 @@ #include "MovingEntitiesOperator.h" #include "UpdateEntityOperator.h" -EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _simulation(NULL) { +EntityTree::EntityTree(bool shouldReaverage) : + Octree(shouldReaverage), + _fbxService(NULL), + _lightsArePickable(true), + _simulation(NULL) +{ _rootElement = createNewElement(); - _lightsArePickable = true; // assume they are by default } EntityTree::~EntityTree() { diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 20f28cd98c..a24fe58c2a 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -47,6 +47,13 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI _emptyShape.setRadius(0.0f); } +void LightEntityItem::setDimensions(const glm::vec3& value) { + float maxDimension = glm::max(value.x, value.y, value.z); + _dimensions = glm::vec3(maxDimension, maxDimension, maxDimension); + recalculateCollisionShape(); +} + + EntityItemProperties LightEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 2006efb896..eb9a2ed051 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -22,6 +22,9 @@ public: LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); 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); // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 1960d9623e..b0df310ad2 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -10,9 +10,12 @@ // +#include + #include #include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -97,18 +100,24 @@ void SphereEntityItem::recalculateCollisionShape() { bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { - - // NOTE: origin and direction are in tree units. But our _sphereShape is in meters, so we need to - // do a little math to make these match each other. - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin * (float)TREE_SCALE; - rayInfo._rayDirection = direction; + // determine the ray in the frame of the entity transformed from a unit sphere + glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 rotation = glm::mat4_cast(getRotation()); + 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); + glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 entityFrameDirection = glm::normalize(glm::vec3(worldToEntityMatrix * glm::vec4(direction, 1.0f))); - // TODO: Note this is really doing ray intersections against a sphere, which is fine except in cases - // where our dimensions actually make us an ellipsoid. But we'll live with this for now until we - // get a more full fledged physics library - if (_sphereShape.findRayIntersection(rayInfo)) { - distance = rayInfo._hitDistance / (float)TREE_SCALE; + float localDistance; + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, localDistance)) { + // determine where on the unit sphere the hit point occured + glm::vec3 entityFrameHitAt = entityFrameOrigin + (entityFrameDirection * localDistance); + // then translate back to work coordinates + glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f)); + distance = glm::distance(origin,hitAt); return true; } return false; diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index 5769498229..74cc7d1635 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -60,7 +60,7 @@ public: virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; - + protected: virtual void recalculateCollisionShape(); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index f8f518a581..bb76a2e690 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -40,6 +40,13 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityIte setProperties(properties, true); } +void TextEntityItem::setDimensions(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); + recalculateCollisionShape(); +} + EntityItemProperties TextEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index c980969bb1..83143b1134 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -21,6 +21,9 @@ public: TextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); 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); // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const;