From 5bc38bd7f07869f3392a8babbda49b75a63cc773 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 7 Jul 2017 11:15:42 -0400 Subject: [PATCH 1/7] [WL21389] Collision Shapes need to be updated (details below). Revised approach involves creating a helper function within ShapeFactory to aid in devising the ShapeType to be used by an ShapeEntityItem for collision. The ShapeFactory is currently doing this for creating the actual Bullet Library collision shapes. ShapeEntityItem overrides its virtually inherited computeShapeInfo which in turn calls the new ShapeFactory helper function. ShapeEntityItem has a new memvar _collisionShapeType to cache its actual ShapeType used by the physics system. This memvar is returned via the getShapeType accessor which is expected to return an object's ShapeType. Note(s): This is similar to the original approach save translation between entity::Shape and ShapeType isn't tied to the EntityItemProperties shapeTypeNames or shapeType. This approach more directly solves the issue of getting the actual ShapeType used by the time it's needed to determine the bullet collision object type created when initializing the physic information. Translation of the ShapeEntityItem's entity::Shape to its ShapeType is handled by ShapeFactory which handles creating the bullet collision objects when setting up physics on the ShapeEntityItems. Known Issue(s): This doesn't compile. It appears that the Entity Library needs to know about the Physics Library. The naive attempt at providing that link failed to resolve all compilation issues. Current Error: C1083: Cannot open include file: btBulletDynamicsCommon.h: No such file or directory (C:\projects\cusack\libraries\entities\src\ShapeEntityItem.cpp) C:\projects\cusack\libraries\physics\src\ShapeFactory.h 15 1 entities modified: libraries/entities-renderer/src/RenderableShapeEntityItem.cpp modified: libraries/entities/CMakeLists.txt modified: libraries/entities/src/ShapeEntityItem.cpp modified: libraries/entities/src/ShapeEntityItem.h modified: libraries/physics/src/ShapeFactory.cpp modified: libraries/physics/src/ShapeFactory.h modified: libraries/physics/src/ShapeInfo.cpp modified: scripts/developer/tests/basicEntityTest/entitySpawner.js new file: scripts/developer/tests/basicEntityTest/shapeSpawner.js --- .../src/RenderableShapeEntityItem.cpp | 10 +- libraries/entities/CMakeLists.txt | 3 +- libraries/entities/src/ShapeEntityItem.cpp | 54 ++++- libraries/entities/src/ShapeEntityItem.h | 4 +- libraries/physics/src/ShapeFactory.cpp | 203 ++++++++++++++++-- libraries/physics/src/ShapeFactory.h | 3 + libraries/shared/src/ShapeInfo.cpp | 5 +- .../tests/basicEntityTest/entitySpawner.js | 4 +- .../tests/basicEntityTest/shapeSpawner.js | 33 +++ 9 files changed, 286 insertions(+), 33 deletions(-) create mode 100644 scripts/developer/tests/basicEntityTest/shapeSpawner.js diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 62ab3377a8..b197e0b9e6 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -48,18 +48,22 @@ RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const } EntityItemPointer RenderableShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return baseFactory(entityID, properties); + auto result = baseFactory(entityID, properties); + + qCDebug(entities) << "Creating RenderableShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; + + return result; } EntityItemPointer RenderableShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { auto result = baseFactory(entityID, properties); - result->setShape(entity::Cube); + result->setShape(entity::Shape::Cube); return result; } EntityItemPointer RenderableShapeEntityItem::sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { auto result = baseFactory(entityID, properties); - result->setShape(entity::Sphere); + result->setShape(entity::Shape::Sphere); return result; } diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 19341ec3e2..90de43b5f8 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,3 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) -link_hifi_libraries(shared networking octree avatars) +link_hifi_libraries(shared networking octree avatars physics) + diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 018d8c568a..d9c48f8593 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -12,6 +12,7 @@ #include #include +#include #include "EntitiesLogging.h" #include "EntityItemProperties.h" @@ -58,7 +59,11 @@ ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entity } EntityItemPointer ShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return baseFactory(entityID, properties); + auto result = baseFactory(entityID, properties); + + qCDebug(entities) << "Creating ShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; + + return result; } EntityItemPointer ShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -101,6 +106,11 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) { } } +//TODO_CUSACK: Move back to header prior to PN +void ShapeEntityItem::setShape( const QString &shape ) { + setShape(entity::shapeFromString(shape)); +} + bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class @@ -160,10 +170,46 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); } +void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { + + if ( _collisionShapeType == ShapeType::SHAPE_TYPE_NONE ) { + if (_shape == entity::Shape::NUM_SHAPES) + { + EntityItem::computeShapeInfo(info); + + //--EARLY EXIT--( allow default handling to process ) + return; + } + + _collisionShapeType = ShapeFactory::computeShapeType(getShape(), getDimensions()); + } + + return EntityItem::computeShapeInfo(info); +} + // This value specifes how the shape should be treated by physics calculations. // For now, all polys will act as spheres ShapeType ShapeEntityItem::getShapeType() const { - return (_shape == entity::Shape::Cube) ? SHAPE_TYPE_BOX : SHAPE_TYPE_ELLIPSOID; + //TODO_CUSACK: This needs to be retrieved from properties if possible + // or stored within a new member and set during parsing of + // the properties like setShape via set/get/readEntityProperties. + // Perhaps if the _actual_ collisionShapeType is needed (the version that's in use + // based on analysis of the shape's halfExtents when BulletLibrary collision shape was + // created as opposed to the desired ShapeType is it possible to retrieve that information)? + //if (_shape == entity::Shape::Cylinder) { + // return SHAPE_TYPE_CYLINDER_Y; + //} + + //// Original functionality: Everything not a cube, is treated like an ellipsoid/sphere + //return (_shape == entity::Shape::Cube) ? SHAPE_TYPE_BOX : SHAPE_TYPE_ELLIPSOID; + + if (_collisionShapeType == ShapeType::SHAPE_TYPE_NONE) + { + //--EARLY EXIT--( Maintain previous behavior of treating invalid as Ellipsoid/Sphere ) + return SHAPE_TYPE_ELLIPSOID; + } + + return _collisionShapeType; } void ShapeEntityItem::setColor(const rgbColor& value) { @@ -223,10 +269,12 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const void ShapeEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << "SHAPE EntityItem id:" << getEntityItemID() << "---------------------------------------------"; - qCDebug(entities) << " shape:" << stringFromShape(_shape); + qCDebug(entities) << " name:" << _name; + qCDebug(entities) << " shape:" << stringFromShape(_shape) << " (EnumId: " << _shape << " )"; qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getPosition()); qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << "SHAPE EntityItem Ptr:" << this; } diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 96f69deb0c..f021fcf957 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -70,7 +70,7 @@ public: entity::Shape getShape() const { return _shape; } void setShape(const entity::Shape& shape); - void setShape(const QString& shape) { setShape(entity::shapeFromString(shape)); } + void setShape(const QString& shape); float getAlpha() const { return _alpha; }; void setAlpha(float alpha) { _alpha = alpha; } @@ -84,6 +84,7 @@ public: QColor getQColor() const; void setColor(const QColor& value); + void computeShapeInfo(ShapeInfo& info); ShapeType getShapeType() const override; bool shouldBePhysical() const override { return !isDead(); } @@ -100,6 +101,7 @@ protected: float _alpha { 1 }; rgbColor _color; entity::Shape _shape { entity::Shape::Sphere }; + ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_NONE }; }; #endif // hifi_ShapeEntityItem_h diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index d209667966..a9bc8b2e05 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -17,7 +17,7 @@ #include "BulletUtil.h" // These are the same normalized directions used by the btShapeHull class. -// 12 points for the face centers of a duodecohedron plus another 30 points +// 12 points for the face centers of a dodecahedron plus another 30 points // for the midpoints the edges, for a total of 42. const uint32_t NUM_UNIT_SPHERE_DIRECTIONS = 42; static const btVector3 _unitSphereDirections[NUM_UNIT_SPHERE_DIRECTIONS] = { @@ -247,6 +247,124 @@ void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray) { delete dataArray; } +ShapeType validateShapeType(ShapeType type, const glm::vec3 &halfExtents, btCollisionShape *outCollisionShape = nullptr) +{ + if ((type == SHAPE_TYPE_SPHERE) || (type == SHAPE_TYPE_ELLIPSOID)) + { + float radius = halfExtents.x; + const float MIN_RADIUS = 0.001f; + const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; + if (radius > MIN_RADIUS + && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR + && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { + // close enough to true sphere + if (outCollisionShape) { + outCollisionShape = new btSphereShape(radius); + } + + return SHAPE_TYPE_SPHERE; + } + else { + ShapeInfo::PointList points; + points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); + for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { + points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); + } + if (outCollisionShape) { + outCollisionShape = createConvexHull(points); + } + + return SHAPE_TYPE_ELLIPSOID; + } + } + else if ((type == SHAPE_TYPE_CYLINDER_X) || (type == SHAPE_TYPE_CYLINDER_Y) || (type == SHAPE_TYPE_CYLINDER_Z)) + { + const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); + if ((halfExtents.y > halfExtents.x) && (halfExtents.y > halfExtents.z)) { + if (outCollisionShape) { + outCollisionShape = new btCylinderShape(btHalfExtents); + } + + return SHAPE_TYPE_CYLINDER_Y; + } + else if (halfExtents.x > halfExtents.z) { + if (outCollisionShape) { + outCollisionShape = new btCylinderShapeX(btHalfExtents); + } + + return SHAPE_TYPE_CYLINDER_X; + } + else if (halfExtents.z > halfExtents.x) { + if (outCollisionShape) { + outCollisionShape = new btCylinderShapeZ(btHalfExtents); + } + + return SHAPE_TYPE_CYLINDER_Z; + } + else //...there was no major axis, treat as a sphere + { + ShapeType cylinderFallback = validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, outCollisionShape); + return cylinderFallback; + } + } + + //Got here, then you are what you are along with outCollisionShape + return type; +} + +ShapeType ShapeFactory::computeShapeType(entity::Shape shape, const glm::vec3 &entityDimensions) { + if ( shape == entity::Shape::NUM_SHAPES ) { + //--EARLY EXIT-- + return SHAPE_TYPE_NONE; + } + + const glm::vec3 halfExtents = entityDimensions * 0.5f; + switch (shape){ + case entity::Shape::Triangle: { + //TODO_CUSACK: Implement this + return validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents); + } + + //Note: Intentional Fallthrough from Quad to Cube + case entity::Shape::Quad: + case entity::Shape::Cube: { + return SHAPE_TYPE_BOX; + } + + //Note: Intentional Fallthrough from Hexagon to Sphere + case entity::Shape::Hexagon: + case entity::Shape::Octagon: + case entity::Shape::Circle: + case entity::Shape::Sphere: { + return validateShapeType(SHAPE_TYPE_SPHERE, halfExtents); + } + + case entity::Shape::Cylinder: { + return validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents); + } + + //Note: Intentional Fallthrough from Tetrahedron to Icosahedron + case entity::Shape::Tetrahedron: + case entity::Shape::Octahedron: + case entity::Shape::Dodecahedron: + case entity::Shape::Icosahedron: { + + //TODO_CUSACK: Implement the hedrons + return validateShapeType( SHAPE_TYPE_ELLIPSOID, halfExtents ); + } + + //Note: Intentional Fallthrough from Torus to default. + case entity::Shape::Torus: + case entity::Shape::Cone: { + + // These types are currently unsupported + } + default: + return SHAPE_TYPE_NONE; + } + +} + const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; int type = info.getType(); @@ -255,30 +373,33 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) shape = new btBoxShape(glmToBullet(info.getHalfExtents())); } break; - case SHAPE_TYPE_SPHERE: { - glm::vec3 halfExtents = info.getHalfExtents(); - float radius = glm::max(halfExtents.x, glm::max(halfExtents.y, halfExtents.z)); - shape = new btSphereShape(radius); - } - break; + //case SHAPE_TYPE_SPHERE: { + // glm::vec3 halfExtents = info.getHalfExtents(); + // float radius = glm::max(halfExtents.x, glm::max(halfExtents.y, halfExtents.z)); + // shape = new btSphereShape(radius); + //} + //break; + case SHAPE_TYPE_SPHERE: case SHAPE_TYPE_ELLIPSOID: { glm::vec3 halfExtents = info.getHalfExtents(); - float radius = halfExtents.x; - const float MIN_RADIUS = 0.001f; - const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; - if (radius > MIN_RADIUS - && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR - && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { - // close enough to true sphere - shape = new btSphereShape(radius); - } else { - ShapeInfo::PointList points; - points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); - for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { - points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); - } - shape = createConvexHull(points); - } + //float radius = halfExtents.x; + //const float MIN_RADIUS = 0.001f; + //const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; + //if (radius > MIN_RADIUS + // && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR + // && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { + // // close enough to true sphere + // shape = new btSphereShape(radius); + //} else { + // ShapeInfo::PointList points; + // points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); + // for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { + // points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); + // } + // shape = createConvexHull(points); + //} + + validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, shape); } break; case SHAPE_TYPE_CAPSULE_Y: { @@ -288,6 +409,42 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) shape = new btCapsuleShape(radius, height); } break; + case SHAPE_TYPE_CAPSULE_X: { + glm::vec3 halfExtents = info.getHalfExtents(); + float radius = halfExtents.y; + float height = 2.0f * halfExtents.x; + shape = new btCapsuleShapeX(radius, height); + } + break; + case SHAPE_TYPE_CAPSULE_Z: { + glm::vec3 halfExtents = info.getHalfExtents(); + float radius = halfExtents.x; + float height = 2.0f * halfExtents.z; + shape = new btCapsuleShapeZ(radius, height); + } + break; + case SHAPE_TYPE_CYLINDER_X: + case SHAPE_TYPE_CYLINDER_Z: + case SHAPE_TYPE_CYLINDER_Y: { + // TODO_CUSACK: Should allow for minor variance along axes. + const glm::vec3 halfExtents = info.getHalfExtents(); + //const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); + //if ((halfExtents.y > halfExtents.x) && (halfExtents.y > halfExtents.z)) { + // shape = new btCylinderShape(btHalfExtents); + //} + //else if (halfExtents.x > halfExtents.z) { + // shape = new btCylinderShapeX(btHalfExtents); + //} + //else if (halfExtents.z > halfExtents.x) { + // shape = new btCylinderShapeZ(btHalfExtents); + //} + //else //...there was no major axis, treat as a sphere + //{ + // //TODO_CUSACK: Shunt to ELLIPSOID handling + //} + validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents, shape); + } + break; case SHAPE_TYPE_COMPOUND: case SHAPE_TYPE_SIMPLE_HULL: { const ShapeInfo::PointCollection& pointCollection = info.getPointCollection(); diff --git a/libraries/physics/src/ShapeFactory.h b/libraries/physics/src/ShapeFactory.h index 2bf79f390c..52b448ee1d 100644 --- a/libraries/physics/src/ShapeFactory.h +++ b/libraries/physics/src/ShapeFactory.h @@ -15,11 +15,14 @@ #include #include +#include //< Needed for entity::Shape #include // translates between ShapeInfo and btShape namespace ShapeFactory { + + ShapeType computeShapeType( entity::Shape shape, const glm::vec3 &entityDimensions); const btCollisionShape* createShapeFromInfo(const ShapeInfo& info); void deleteShape(const btCollisionShape* shape); diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 496e94f8bd..e40d91379c 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -136,7 +136,10 @@ float ShapeInfo::computeVolume() const { } case SHAPE_TYPE_CAPSULE_Y: { float radius = _halfExtents.x; - volume = PI * radius * radius * (2.0f * (_halfExtents.y - _halfExtents.x) + 4.0f * radius / 3.0f); + // Need to offset halfExtents.y by x to account for the system treating + // the y extent of the capsule as the cylindrical height + spherical radius. + float cylinderHeight = 2.0f * (_halfExtents.y - _halfExtents.x); + volume = PI * radius * radius * (cylinderHeight + 4.0f * radius / 3.0f); break; } default: diff --git a/scripts/developer/tests/basicEntityTest/entitySpawner.js b/scripts/developer/tests/basicEntityTest/entitySpawner.js index 538e9145f5..fa5c9291cb 100644 --- a/scripts/developer/tests/basicEntityTest/entitySpawner.js +++ b/scripts/developer/tests/basicEntityTest/entitySpawner.js @@ -8,7 +8,9 @@ var SCRIPT_URL = Script.resolvePath("myEntityScript.js") var myEntity = Entities.addEntity({ - type: "Sphere", + name: "Cusack_Testing", + type: "Shape", + shapeType: "Cylinder", color: { red: 200, green: 10, diff --git a/scripts/developer/tests/basicEntityTest/shapeSpawner.js b/scripts/developer/tests/basicEntityTest/shapeSpawner.js new file mode 100644 index 0000000000..f93072a582 --- /dev/null +++ b/scripts/developer/tests/basicEntityTest/shapeSpawner.js @@ -0,0 +1,33 @@ + var orientation = Camera.getOrientation(); + orientation = Quat.safeEulerAngles(orientation); + orientation.x = 0; + orientation = Quat.fromVec3Degrees(orientation); + var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getForward(orientation))); + + // Math.random ensures no caching of script + var SCRIPT_URL = Script.resolvePath("myEntityScript.js") + + var myEntity = Entities.addEntity({ + name: "ShapeSpawnTest", + type: "Shape", + shape: "Cylinder", + color: { + red: 200, + green: 10, + blue: 200 + }, + position: center, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + script: SCRIPT_URL + }) + + + function cleanup() { + // Entities.deleteEntity(myEntity); + } + + Script.scriptEnding.connect(cleanup); From 75403124b621835b1bb2c4b9a060980324ab7e1b Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Tue, 18 Jul 2017 17:15:02 -0400 Subject: [PATCH 2/7] [WL21389] Addresses physics library dependency and has some other fixes (details below). * Addresses physics library dependency by moving computeShapeInfo override from ShapeEntityItem (which is within Entities Library) to RenderableShapeEntityItem (which is in Entities-Renderer Library). ** Entities-Renderer library already links against the physic library. ** Per discussion with Andrew Meadows: In order to ShapeEntityItem to be utilized the library dependency between the Entity and Physics library would need to be resolved to avoid the cyclical reliance which isn't in the scope of this ticket. * Updates shapeSpawner test script from the default clone of basicEntityTest\entitySpawner.js ** Objects now have a finite lifetime ** Script now cleans up the objects created when the script ends ** Also moved some adjustable properties out into var aliases at the top of the file for easier/less error prone tweaking. Should probably add one for the shapeType. * Fixes some issues with validateShapeType helper function * Removed naive attempt at including physics library within entities library. * Transferred some todos from notes * Fixed some formatting NOTE(s): This compiles and runs. Cylinder is spawned and treated as CYLINDER_Y. TODO(s): * Add tweakable var for shapeType within shapeSpawner.js * Vet and verify other shapes. * Add in edge case handling. * Add in support for other shapes to ShapeInfo infrastructure. Changes to be committed: modified: libraries/entities-renderer/src/RenderableShapeEntityItem.cpp modified: libraries/entities-renderer/src/RenderableShapeEntityItem.h modified: libraries/entities/CMakeLists.txt modified: libraries/entities/src/ShapeEntityItem.cpp modified: libraries/entities/src/ShapeEntityItem.h modified: libraries/physics/src/ShapeFactory.cpp modified: libraries/shared/src/ShapeInfo.cpp modified: scripts/developer/tests/basicEntityTest/shapeSpawner.js --- .../src/RenderableShapeEntityItem.cpp | 25 +- .../src/RenderableShapeEntityItem.h | 2 + libraries/entities/CMakeLists.txt | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 61 ++-- libraries/entities/src/ShapeEntityItem.h | 1 - libraries/physics/src/ShapeFactory.cpp | 277 +++++++++--------- libraries/shared/src/ShapeInfo.cpp | 14 +- .../tests/basicEntityTest/shapeSpawner.js | 53 ++-- 8 files changed, 226 insertions(+), 209 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index b197e0b9e6..f071518b42 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -48,11 +49,12 @@ RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const } EntityItemPointer RenderableShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - auto result = baseFactory(entityID, properties); + auto result = baseFactory(entityID, properties); - qCDebug(entities) << "Creating RenderableShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; + //TODO_CUSACK: Remove this before final PN + qCDebug(entities) << "Creating RenderableShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; - return result; + return result; } EntityItemPointer RenderableShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -86,6 +88,23 @@ bool RenderableShapeEntityItem::isTransparent() { } } +void RenderableShapeEntityItem::computeShapeInfo(ShapeInfo& info) { + + if (_collisionShapeType == ShapeType::SHAPE_TYPE_NONE) { + if (_shape == entity::Shape::NUM_SHAPES) + { + EntityItem::computeShapeInfo(info); + + //--EARLY EXIT--( allow default handling to process ) + return; + } + + _collisionShapeType = ShapeFactory::computeShapeType(getShape(), getDimensions()); + } + + return EntityItem::computeShapeInfo(info); +} + void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 0cc6a54f81..96f450f523 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -28,6 +28,8 @@ public: bool isTransparent() override; + void computeShapeInfo(ShapeInfo& info); + private: std::unique_ptr _procedural { nullptr }; diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 90de43b5f8..84906a48df 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) -link_hifi_libraries(shared networking octree avatars physics) +link_hifi_libraries(shared networking octree avatars) diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index d9c48f8593..854be7df1e 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -12,7 +12,6 @@ #include #include -#include #include "EntitiesLogging.h" #include "EntityItemProperties.h" @@ -59,11 +58,12 @@ ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entity } EntityItemPointer ShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - auto result = baseFactory(entityID, properties); + auto result = baseFactory(entityID, properties); - qCDebug(entities) << "Creating ShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; + //TODO_CUSACK: Remove this before final PN + qCDebug(entities) << "Creating ShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; - return result; + return result; } EntityItemPointer ShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -96,9 +96,11 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) { switch (_shape) { case entity::Shape::Cube: _type = EntityTypes::Box; + _collisionShapeType = ShapeType::SHAPE_TYPE_BOX; break; case entity::Shape::Sphere: _type = EntityTypes::Sphere; + _collisionShapeType = ShapeType::SHAPE_TYPE_ELLIPSOID; break; default: _type = EntityTypes::Shape; @@ -170,46 +172,29 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); } -void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { - - if ( _collisionShapeType == ShapeType::SHAPE_TYPE_NONE ) { - if (_shape == entity::Shape::NUM_SHAPES) - { - EntityItem::computeShapeInfo(info); - - //--EARLY EXIT--( allow default handling to process ) - return; - } - - _collisionShapeType = ShapeFactory::computeShapeType(getShape(), getDimensions()); - } - - return EntityItem::computeShapeInfo(info); -} - // This value specifes how the shape should be treated by physics calculations. // For now, all polys will act as spheres ShapeType ShapeEntityItem::getShapeType() const { - //TODO_CUSACK: This needs to be retrieved from properties if possible - // or stored within a new member and set during parsing of - // the properties like setShape via set/get/readEntityProperties. - // Perhaps if the _actual_ collisionShapeType is needed (the version that's in use - // based on analysis of the shape's halfExtents when BulletLibrary collision shape was - // created as opposed to the desired ShapeType is it possible to retrieve that information)? - //if (_shape == entity::Shape::Cylinder) { - // return SHAPE_TYPE_CYLINDER_Y; - //} + //TODO_CUSACK: This needs to be retrieved from properties if possible + // or stored within a new member and set during parsing of + // the properties like setShape via set/get/readEntityProperties. + // Perhaps if the _actual_ collisionShapeType is needed (the version that's in use + // based on analysis of the shape's halfExtents when BulletLibrary collision shape was + // created as opposed to the desired ShapeType is it possible to retrieve that information)? + //if (_shape == entity::Shape::Cylinder) { + // return SHAPE_TYPE_CYLINDER_Y; + //} - //// Original functionality: Everything not a cube, is treated like an ellipsoid/sphere - //return (_shape == entity::Shape::Cube) ? SHAPE_TYPE_BOX : SHAPE_TYPE_ELLIPSOID; + //// Original functionality: Everything not a cube, is treated like an ellipsoid/sphere + //return (_shape == entity::Shape::Cube) ? SHAPE_TYPE_BOX : SHAPE_TYPE_ELLIPSOID; - if (_collisionShapeType == ShapeType::SHAPE_TYPE_NONE) - { - //--EARLY EXIT--( Maintain previous behavior of treating invalid as Ellipsoid/Sphere ) - return SHAPE_TYPE_ELLIPSOID; - } + //if (_collisionShapeType == ShapeType::SHAPE_TYPE_NONE) + //{ + // //--EARLY EXIT--( Maintain previous behavior of treating invalid as Ellipsoid/Sphere ) + // return SHAPE_TYPE_ELLIPSOID; + //} - return _collisionShapeType; + return _collisionShapeType; } void ShapeEntityItem::setColor(const rgbColor& value) { diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index f021fcf957..435d22a6b2 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -84,7 +84,6 @@ public: QColor getQColor() const; void setColor(const QColor& value); - void computeShapeInfo(ShapeInfo& info); ShapeType getShapeType() const override; bool shouldBePhysical() const override { return !isDead(); } diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index a9bc8b2e05..74aff45e55 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -247,121 +247,120 @@ void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray) { delete dataArray; } -ShapeType validateShapeType(ShapeType type, const glm::vec3 &halfExtents, btCollisionShape *outCollisionShape = nullptr) +ShapeType validateShapeType(ShapeType type, const glm::vec3 &halfExtents, btCollisionShape **outCollisionShape = NULL) { - if ((type == SHAPE_TYPE_SPHERE) || (type == SHAPE_TYPE_ELLIPSOID)) - { - float radius = halfExtents.x; - const float MIN_RADIUS = 0.001f; - const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; - if (radius > MIN_RADIUS - && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR - && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { - // close enough to true sphere - if (outCollisionShape) { - outCollisionShape = new btSphereShape(radius); - } + if ((type == SHAPE_TYPE_SPHERE) || (type == SHAPE_TYPE_ELLIPSOID)) + { + float radius = halfExtents.x; + const float MIN_RADIUS = 0.001f; + const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; + if (radius > MIN_RADIUS + && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR + && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { + // close enough to true sphere + if (outCollisionShape) { + (*outCollisionShape) = new btSphereShape(radius); + } - return SHAPE_TYPE_SPHERE; - } - else { - ShapeInfo::PointList points; - points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); - for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { - points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); - } - if (outCollisionShape) { - outCollisionShape = createConvexHull(points); - } + return SHAPE_TYPE_SPHERE; + } + else { + ShapeInfo::PointList points; + points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); + for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { + points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); + } + if (outCollisionShape) { + (*outCollisionShape) = createConvexHull(points); + } - return SHAPE_TYPE_ELLIPSOID; - } - } - else if ((type == SHAPE_TYPE_CYLINDER_X) || (type == SHAPE_TYPE_CYLINDER_Y) || (type == SHAPE_TYPE_CYLINDER_Z)) - { - const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); - if ((halfExtents.y > halfExtents.x) && (halfExtents.y > halfExtents.z)) { - if (outCollisionShape) { - outCollisionShape = new btCylinderShape(btHalfExtents); - } + return SHAPE_TYPE_ELLIPSOID; + } + } + else if ((type == SHAPE_TYPE_CYLINDER_X) || (type == SHAPE_TYPE_CYLINDER_Y) || (type == SHAPE_TYPE_CYLINDER_Z)) + { + // TODO_CUSACK: Should allow for minor variance along axes? + const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); + if ((halfExtents.y >= halfExtents.x) && (halfExtents.y >= halfExtents.z)) { + if (outCollisionShape) { + (*outCollisionShape) = new btCylinderShape(btHalfExtents); + } - return SHAPE_TYPE_CYLINDER_Y; - } - else if (halfExtents.x > halfExtents.z) { - if (outCollisionShape) { - outCollisionShape = new btCylinderShapeX(btHalfExtents); - } + return SHAPE_TYPE_CYLINDER_Y; + } + else if (halfExtents.x >= halfExtents.z) { + if (outCollisionShape) { + (*outCollisionShape) = new btCylinderShapeX(btHalfExtents); + } - return SHAPE_TYPE_CYLINDER_X; - } - else if (halfExtents.z > halfExtents.x) { - if (outCollisionShape) { - outCollisionShape = new btCylinderShapeZ(btHalfExtents); - } + return SHAPE_TYPE_CYLINDER_X; + } + else if (halfExtents.z > halfExtents.x) { + if (outCollisionShape) { + (*outCollisionShape) = new btCylinderShapeZ(btHalfExtents); + } - return SHAPE_TYPE_CYLINDER_Z; - } - else //...there was no major axis, treat as a sphere - { - ShapeType cylinderFallback = validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, outCollisionShape); - return cylinderFallback; - } - } + return SHAPE_TYPE_CYLINDER_Z; + } + else //...there was no major axis, treat as a sphere + { + ShapeType cylinderFallback = validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, outCollisionShape); + return cylinderFallback; + } + } - //Got here, then you are what you are along with outCollisionShape - return type; + //Got here, then you are what you are along with outCollisionShape + return type; } ShapeType ShapeFactory::computeShapeType(entity::Shape shape, const glm::vec3 &entityDimensions) { - if ( shape == entity::Shape::NUM_SHAPES ) { - //--EARLY EXIT-- - return SHAPE_TYPE_NONE; - } + if (shape == entity::Shape::NUM_SHAPES) { + //--EARLY EXIT-- + return SHAPE_TYPE_NONE; + } - const glm::vec3 halfExtents = entityDimensions * 0.5f; - switch (shape){ - case entity::Shape::Triangle: { - //TODO_CUSACK: Implement this - return validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents); - } + const glm::vec3 halfExtents = entityDimensions * 0.5f; + switch (shape){ + case entity::Shape::Triangle: { + //TODO_CUSACK: Implement this + return validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents); + } + //Note: Intentional Fallthrough from Quad to Cube + case entity::Shape::Quad: + case entity::Shape::Cube: { + return SHAPE_TYPE_BOX; + } + //Note: Intentional Fallthrough from Hexagon to Sphere + case entity::Shape::Hexagon: + case entity::Shape::Octagon: + case entity::Shape::Circle: + case entity::Shape::Sphere: { + return validateShapeType(SHAPE_TYPE_SPHERE, halfExtents); + } - //Note: Intentional Fallthrough from Quad to Cube - case entity::Shape::Quad: - case entity::Shape::Cube: { - return SHAPE_TYPE_BOX; - } + case entity::Shape::Cylinder: { + return validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents); + } - //Note: Intentional Fallthrough from Hexagon to Sphere - case entity::Shape::Hexagon: - case entity::Shape::Octagon: - case entity::Shape::Circle: - case entity::Shape::Sphere: { - return validateShapeType(SHAPE_TYPE_SPHERE, halfExtents); - } + //Note: Intentional Fallthrough from Tetrahedron to Icosahedron + case entity::Shape::Tetrahedron: + case entity::Shape::Octahedron: + case entity::Shape::Dodecahedron: + case entity::Shape::Icosahedron: { - case entity::Shape::Cylinder: { - return validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents); - } + //TODO_CUSACK: Implement the hedrons + return validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents); + } - //Note: Intentional Fallthrough from Tetrahedron to Icosahedron - case entity::Shape::Tetrahedron: - case entity::Shape::Octahedron: - case entity::Shape::Dodecahedron: - case entity::Shape::Icosahedron: { + //Note: Intentional Fallthrough from Torus to default. + case entity::Shape::Torus: + case entity::Shape::Cone: { - //TODO_CUSACK: Implement the hedrons - return validateShapeType( SHAPE_TYPE_ELLIPSOID, halfExtents ); - } - - //Note: Intentional Fallthrough from Torus to default. - case entity::Shape::Torus: - case entity::Shape::Cone: { - - // These types are currently unsupported - } - default: - return SHAPE_TYPE_NONE; - } + // These types are currently unsupported + } + default: + return SHAPE_TYPE_NONE; + } } @@ -379,7 +378,7 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) // shape = new btSphereShape(radius); //} //break; - case SHAPE_TYPE_SPHERE: + case SHAPE_TYPE_SPHERE: case SHAPE_TYPE_ELLIPSOID: { glm::vec3 halfExtents = info.getHalfExtents(); //float radius = halfExtents.x; @@ -399,9 +398,11 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) // shape = createConvexHull(points); //} - validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, shape); + validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, &shape); } break; + //TODO_CUSACK: Add Capsules to vetting/validation process for + // type checks. case SHAPE_TYPE_CAPSULE_Y: { glm::vec3 halfExtents = info.getHalfExtents(); float radius = halfExtents.x; @@ -409,42 +410,44 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) shape = new btCapsuleShape(radius, height); } break; - case SHAPE_TYPE_CAPSULE_X: { - glm::vec3 halfExtents = info.getHalfExtents(); - float radius = halfExtents.y; - float height = 2.0f * halfExtents.x; - shape = new btCapsuleShapeX(radius, height); - } - break; - case SHAPE_TYPE_CAPSULE_Z: { - glm::vec3 halfExtents = info.getHalfExtents(); - float radius = halfExtents.x; - float height = 2.0f * halfExtents.z; - shape = new btCapsuleShapeZ(radius, height); - } - break; - case SHAPE_TYPE_CYLINDER_X: - case SHAPE_TYPE_CYLINDER_Z: - case SHAPE_TYPE_CYLINDER_Y: { - // TODO_CUSACK: Should allow for minor variance along axes. - const glm::vec3 halfExtents = info.getHalfExtents(); - //const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); - //if ((halfExtents.y > halfExtents.x) && (halfExtents.y > halfExtents.z)) { - // shape = new btCylinderShape(btHalfExtents); - //} - //else if (halfExtents.x > halfExtents.z) { - // shape = new btCylinderShapeX(btHalfExtents); - //} - //else if (halfExtents.z > halfExtents.x) { - // shape = new btCylinderShapeZ(btHalfExtents); - //} - //else //...there was no major axis, treat as a sphere - //{ - // //TODO_CUSACK: Shunt to ELLIPSOID handling - //} - validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents, shape); - } - break; + case SHAPE_TYPE_CAPSULE_X: { + glm::vec3 halfExtents = info.getHalfExtents(); + float radius = halfExtents.y; + float height = 2.0f * halfExtents.x; + shape = new btCapsuleShapeX(radius, height); + } + break; + case SHAPE_TYPE_CAPSULE_Z: { + glm::vec3 halfExtents = info.getHalfExtents(); + float radius = halfExtents.x; + float height = 2.0f * halfExtents.z; + shape = new btCapsuleShapeZ(radius, height); + } + break; + case SHAPE_TYPE_CYLINDER_X: + case SHAPE_TYPE_CYLINDER_Z: + case SHAPE_TYPE_CYLINDER_Y: { + // TODO_CUSACK: Should allow for minor variance along axes. + const glm::vec3 halfExtents = info.getHalfExtents(); + //const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); + //if ((halfExtents.y > halfExtents.x) && (halfExtents.y > halfExtents.z)) { + // shape = new btCylinderShape(btHalfExtents); + //} + //else if (halfExtents.x > halfExtents.z) { + // shape = new btCylinderShapeX(btHalfExtents); + //} + //else if (halfExtents.z > halfExtents.x) { + // shape = new btCylinderShapeZ(btHalfExtents); + //} + //else //...there was no major axis, treat as a sphere + //{ + // //TODO_CUSACK: Shunt to ELLIPSOID handling + //} + validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents, &shape); + } + break; + //TODO_CUSACK: Add compound and simple hull to vetting/validation + // process for types. case SHAPE_TYPE_COMPOUND: case SHAPE_TYPE_SIMPLE_HULL: { const ShapeInfo::PointCollection& pointCollection = info.getPointCollection(); diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index e40d91379c..57e927eaf3 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -29,7 +29,8 @@ void ShapeInfo::clear() { } void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) { - _url = ""; + //TODO_CUSACK: Does this need additional cases and handling added? + _url = ""; _type = type; setHalfExtents(halfExtents); switch(type) { @@ -55,6 +56,8 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString } void ShapeInfo::setBox(const glm::vec3& halfExtents) { + //TODO_CUSACK: Should this pointlist clearance added in case + // this is a re-purposed instance? _url = ""; _type = SHAPE_TYPE_BOX; setHalfExtents(halfExtents); @@ -62,6 +65,8 @@ void ShapeInfo::setBox(const glm::vec3& halfExtents) { } void ShapeInfo::setSphere(float radius) { + //TODO_CUSACK: Should this pointlist clearance added in case + // this is a re-purposed instance? _url = ""; _type = SHAPE_TYPE_SPHERE; radius = glm::max(radius, MIN_HALF_EXTENT); @@ -70,12 +75,17 @@ void ShapeInfo::setSphere(float radius) { } void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) { + //TODO_CUSACK: Should this have protection against inadvertant clearance and type + // resetting? If for some reason this was called and point list was and is emtpy + // would we still wish to clear out everything? _pointCollection = pointCollection; _type = (_pointCollection.size() > 0) ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; _doubleHashKey.clear(); } void ShapeInfo::setCapsuleY(float radius, float halfHeight) { + //TODO_CUSACK: Should this pointlist clearance added in case + // this is a re-purposed instance? _url = ""; _type = SHAPE_TYPE_CAPSULE_Y; radius = glm::max(radius, MIN_HALF_EXTENT); @@ -117,6 +127,7 @@ int ShapeInfo::getLargestSubshapePointCount() const { } float ShapeInfo::computeVolume() const { + //TODO_CUSACK: Add support for other ShapeTypes. const float DEFAULT_VOLUME = 1.0f; float volume = DEFAULT_VOLUME; switch(_type) { @@ -150,6 +161,7 @@ float ShapeInfo::computeVolume() const { } bool ShapeInfo::contains(const glm::vec3& point) const { + //TODO_CUSACK: Add support for other ShapeTypes like Ellipsoid/Compound. switch(_type) { case SHAPE_TYPE_SPHERE: return glm::length(point) <= _halfExtents.x; diff --git a/scripts/developer/tests/basicEntityTest/shapeSpawner.js b/scripts/developer/tests/basicEntityTest/shapeSpawner.js index f93072a582..9fcaf3a3db 100644 --- a/scripts/developer/tests/basicEntityTest/shapeSpawner.js +++ b/scripts/developer/tests/basicEntityTest/shapeSpawner.js @@ -1,33 +1,30 @@ - var orientation = Camera.getOrientation(); - orientation = Quat.safeEulerAngles(orientation); - orientation.x = 0; - orientation = Quat.fromVec3Degrees(orientation); - var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getForward(orientation))); +// compute a position to create the object relative to avatar +var forwardOffset = Vec3.multiply(2.0, Quat.getFront(MyAvatar.orientation)); +var objectPosition = Vec3.sum(MyAvatar.position, forwardOffset); - // Math.random ensures no caching of script - var SCRIPT_URL = Script.resolvePath("myEntityScript.js") +var LIFETIME = 1800; //seconds +var DIM_HEIGHT = 1, DIM_WIDTH = 1, DIM_DEPTH = 1; +var COLOR_R = 100, COLOR_G = 10, COLOR_B = 200; - var myEntity = Entities.addEntity({ - name: "ShapeSpawnTest", - type: "Shape", - shape: "Cylinder", - color: { - red: 200, - green: 10, - blue: 200 - }, - position: center, - dimensions: { - x: 1, - y: 1, - z: 1 - }, - script: SCRIPT_URL - }) +var properties = { + name: "ShapeSpawnTest", + type: "Shape", + shape: "Cylinder", + dimensions: {x: DIM_WIDTH, y: DIM_HEIGHT, z: DIM_DEPTH}, + color: {red: COLOR_R, green: COLOR_G, blue: COLOR_B}, + position: objectPosition, + lifetime: LIFETIME, +}; + +// create the object +var entityId = Entities.addEntity(properties); + +function cleanup() { + Entities.deleteEntity(entityId); +} + +// delete the object when this script is stopped +Script.scriptEnding.connect(cleanup); - function cleanup() { - // Entities.deleteEntity(myEntity); - } - Script.scriptEnding.connect(cleanup); From d155c0264030c3eec0c231d7f80072b6ab63662b Mon Sep 17 00:00:00 2001 From: Leander Hasty <1p-cusack@1stplayable.com> Date: Mon, 24 Jul 2017 17:02:40 -0400 Subject: [PATCH 3/7] [WL21389] wip and modifications based on comments https://github.com/highfidelity/hifi/pull/11024#pullrequestreview-51611518 Cleans up tabs, moves new functionality out of ShapeFactory directly to RenderableShapeEntityItem's computeShapeInfo override, begins to break down where we will need pointlists. Still need to determine how rotation is handled for pointlists, and check for axis alignment on cylinders before deciding on a shape. Changes to be committed: modified: libraries/entities-renderer/src/RenderableShapeEntityItem.cpp modified: libraries/entities-renderer/src/RenderableShapeEntityItem.h modified: libraries/entities/CMakeLists.txt modified: libraries/entities/src/ShapeEntityItem.cpp modified: libraries/entities/src/ShapeEntityItem.h modified: libraries/physics/src/ShapeFactory.cpp modified: libraries/physics/src/ShapeFactory.h modified: libraries/shared/src/ShapeInfo.cpp modified: scripts/developer/tests/basicEntityTest/entitySpawner.js --- .../src/RenderableShapeEntityItem.cpp | 92 ++++++-- .../src/RenderableShapeEntityItem.h | 2 +- libraries/entities/CMakeLists.txt | 1 - libraries/entities/src/ShapeEntityItem.cpp | 37 +--- libraries/entities/src/ShapeEntityItem.h | 4 +- libraries/physics/src/ShapeFactory.cpp | 202 ++++-------------- libraries/physics/src/ShapeFactory.h | 3 - libraries/shared/src/ShapeInfo.cpp | 4 +- .../tests/basicEntityTest/entitySpawner.js | 4 +- 9 files changed, 122 insertions(+), 227 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index f071518b42..a305b201d6 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -49,23 +49,18 @@ RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const } EntityItemPointer RenderableShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - auto result = baseFactory(entityID, properties); - - //TODO_CUSACK: Remove this before final PN - qCDebug(entities) << "Creating RenderableShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; - - return result; + return baseFactory(entityID, properties); } EntityItemPointer RenderableShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { auto result = baseFactory(entityID, properties); - result->setShape(entity::Shape::Cube); + result->setShape(entity::Cube); return result; } EntityItemPointer RenderableShapeEntityItem::sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { auto result = baseFactory(entityID, properties); - result->setShape(entity::Shape::Sphere); + result->setShape(entity::Sphere); return result; } @@ -90,19 +85,84 @@ bool RenderableShapeEntityItem::isTransparent() { void RenderableShapeEntityItem::computeShapeInfo(ShapeInfo& info) { - if (_collisionShapeType == ShapeType::SHAPE_TYPE_NONE) { - if (_shape == entity::Shape::NUM_SHAPES) - { - EntityItem::computeShapeInfo(info); + // This will be called whenever DIRTY_SHAPE flag (set by dimension change, etc) + // is set. - //--EARLY EXIT--( allow default handling to process ) - return; + const glm::vec3 entityDimensions = getDimensions(); + + switch (_shape){ + case entity::Shape::Quad: + case entity::Shape::Cube: { + _collisionShapeType = SHAPE_TYPE_BOX; + } + break; + case entity::Shape::Sphere: { + + float diameter = entityDimensions.x; + const float MIN_DIAMETER = 0.001f; + const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; + if (diameter > MIN_DIAMETER + && fabsf(diameter - entityDimensions.y) / diameter < MIN_RELATIVE_SPHERICAL_ERROR + && fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) { + + _collisionShapeType = SHAPE_TYPE_SPHERE; } + else { + _collisionShapeType = SHAPE_TYPE_ELLIPSOID; + } + } + break; + case entity::Shape::Cylinder: { + _collisionShapeType = SHAPE_TYPE_CYLINDER_Y; + // TODO_CUSACK: determine if rotation is axis-aligned + //const Transform::Quat & rot = _transform.getRotation(); - _collisionShapeType = ShapeFactory::computeShapeType(getShape(), getDimensions()); +#if 0 + // TODO: some way to tell apart SHAPE_TYPE_CYLINDER_Y + // TODO_CUSACK: Should allow for minor variance along axes? + if ((entityDimensions.y >= entityDimensions.x) && (entityDimensions.y >= entityDimensions.z)) { + } + else if (entityDimensions.x >= entityDimensions.z) { + _collisionShapeType = SHAPE_TYPE_CYLINDER_X; + } + else if (entityDimensions.z >= entityDimensions.x) { + _collisionShapeType = SHAPE_TYPE_CYLINDER_Z; + } + else //...there was no major axis, treat as a hull + { + _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; + //TODO_CUSACK: pointCollection + } +#endif + } + break; + case entity::Shape::Triangle: + case entity::Shape::Hexagon: + case entity::Shape::Octagon: + case entity::Shape::Circle: + case entity::Shape::Tetrahedron: + case entity::Shape::Octahedron: + case entity::Shape::Dodecahedron: + case entity::Shape::Icosahedron: + case entity::Shape::Cone: { + _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; + //TODO_CUSACK: pointCollection + } + break; + case entity::Shape::Torus: + { + // Not in GeometryCache::buildShapes, unsupported. + _collisionShapeType = SHAPE_TYPE_NONE; + //TODO_CUSACK: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later) + } + break; + default:{ + //_collisionShapeType = SHAPE_TYPE_NONE; // Remains SHAPE_TYPE_NONE. + } + break; } - return EntityItem::computeShapeInfo(info); + EntityItem::computeShapeInfo(info); } void RenderableShapeEntityItem::render(RenderArgs* args) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 96f450f523..2a841df57e 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -28,7 +28,7 @@ public: bool isTransparent() override; - void computeShapeInfo(ShapeInfo& info); + virtual void computeShapeInfo(ShapeInfo& info); private: std::unique_ptr _procedural { nullptr }; diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 84906a48df..19341ec3e2 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,3 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) link_hifi_libraries(shared networking octree avatars) - diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 854be7df1e..58799de807 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -58,12 +58,7 @@ ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entity } EntityItemPointer ShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - auto result = baseFactory(entityID, properties); - - //TODO_CUSACK: Remove this before final PN - qCDebug(entities) << "Creating ShapeEntityItem( " << result->_name << " ): " << result.get() << " ID: " << result->_id; - - return result; + return baseFactory(entityID, properties); } EntityItemPointer ShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -93,14 +88,14 @@ EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredP void ShapeEntityItem::setShape(const entity::Shape& shape) { _shape = shape; - switch (_shape) { + switch (_shape) { // TODO_CUSACK fill out? case entity::Shape::Cube: _type = EntityTypes::Box; _collisionShapeType = ShapeType::SHAPE_TYPE_BOX; break; case entity::Shape::Sphere: _type = EntityTypes::Sphere; - _collisionShapeType = ShapeType::SHAPE_TYPE_ELLIPSOID; + _collisionShapeType = ShapeType::SHAPE_TYPE_ELLIPSOID; // TODO_CUSACK defer? Check to see if sphere is more appropriate? break; default: _type = EntityTypes::Shape; @@ -108,11 +103,6 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) { } } -//TODO_CUSACK: Move back to header prior to PN -void ShapeEntityItem::setShape( const QString &shape ) { - setShape(entity::shapeFromString(shape)); -} - bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class @@ -175,25 +165,6 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit // This value specifes how the shape should be treated by physics calculations. // For now, all polys will act as spheres ShapeType ShapeEntityItem::getShapeType() const { - //TODO_CUSACK: This needs to be retrieved from properties if possible - // or stored within a new member and set during parsing of - // the properties like setShape via set/get/readEntityProperties. - // Perhaps if the _actual_ collisionShapeType is needed (the version that's in use - // based on analysis of the shape's halfExtents when BulletLibrary collision shape was - // created as opposed to the desired ShapeType is it possible to retrieve that information)? - //if (_shape == entity::Shape::Cylinder) { - // return SHAPE_TYPE_CYLINDER_Y; - //} - - //// Original functionality: Everything not a cube, is treated like an ellipsoid/sphere - //return (_shape == entity::Shape::Cube) ? SHAPE_TYPE_BOX : SHAPE_TYPE_ELLIPSOID; - - //if (_collisionShapeType == ShapeType::SHAPE_TYPE_NONE) - //{ - // //--EARLY EXIT--( Maintain previous behavior of treating invalid as Ellipsoid/Sphere ) - // return SHAPE_TYPE_ELLIPSOID; - //} - return _collisionShapeType; } @@ -254,7 +225,7 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const void ShapeEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << "SHAPE EntityItem id:" << getEntityItemID() << "---------------------------------------------"; - qCDebug(entities) << " name:" << _name; + qCDebug(entities) << " name:" << _name; qCDebug(entities) << " shape:" << stringFromShape(_shape) << " (EnumId: " << _shape << " )"; qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getPosition()); diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 435d22a6b2..42a92f7bd7 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -70,7 +70,7 @@ public: entity::Shape getShape() const { return _shape; } void setShape(const entity::Shape& shape); - void setShape(const QString& shape); + void setShape(const QString& shape) { setShape(entity::shapeFromString(shape)); } float getAlpha() const { return _alpha; }; void setAlpha(float alpha) { _alpha = alpha; } @@ -100,7 +100,7 @@ protected: float _alpha { 1 }; rgbColor _color; entity::Shape _shape { entity::Shape::Sphere }; - ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_NONE }; + ShapeType _collisionShapeType { ShapeType::SHAPE_TYPE_NONE }; }; #endif // hifi_ShapeEntityItem_h diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index 74aff45e55..87580c6726 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -247,123 +247,6 @@ void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray) { delete dataArray; } -ShapeType validateShapeType(ShapeType type, const glm::vec3 &halfExtents, btCollisionShape **outCollisionShape = NULL) -{ - if ((type == SHAPE_TYPE_SPHERE) || (type == SHAPE_TYPE_ELLIPSOID)) - { - float radius = halfExtents.x; - const float MIN_RADIUS = 0.001f; - const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; - if (radius > MIN_RADIUS - && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR - && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { - // close enough to true sphere - if (outCollisionShape) { - (*outCollisionShape) = new btSphereShape(radius); - } - - return SHAPE_TYPE_SPHERE; - } - else { - ShapeInfo::PointList points; - points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); - for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { - points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); - } - if (outCollisionShape) { - (*outCollisionShape) = createConvexHull(points); - } - - return SHAPE_TYPE_ELLIPSOID; - } - } - else if ((type == SHAPE_TYPE_CYLINDER_X) || (type == SHAPE_TYPE_CYLINDER_Y) || (type == SHAPE_TYPE_CYLINDER_Z)) - { - // TODO_CUSACK: Should allow for minor variance along axes? - const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); - if ((halfExtents.y >= halfExtents.x) && (halfExtents.y >= halfExtents.z)) { - if (outCollisionShape) { - (*outCollisionShape) = new btCylinderShape(btHalfExtents); - } - - return SHAPE_TYPE_CYLINDER_Y; - } - else if (halfExtents.x >= halfExtents.z) { - if (outCollisionShape) { - (*outCollisionShape) = new btCylinderShapeX(btHalfExtents); - } - - return SHAPE_TYPE_CYLINDER_X; - } - else if (halfExtents.z > halfExtents.x) { - if (outCollisionShape) { - (*outCollisionShape) = new btCylinderShapeZ(btHalfExtents); - } - - return SHAPE_TYPE_CYLINDER_Z; - } - else //...there was no major axis, treat as a sphere - { - ShapeType cylinderFallback = validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, outCollisionShape); - return cylinderFallback; - } - } - - //Got here, then you are what you are along with outCollisionShape - return type; -} - -ShapeType ShapeFactory::computeShapeType(entity::Shape shape, const glm::vec3 &entityDimensions) { - if (shape == entity::Shape::NUM_SHAPES) { - //--EARLY EXIT-- - return SHAPE_TYPE_NONE; - } - - const glm::vec3 halfExtents = entityDimensions * 0.5f; - switch (shape){ - case entity::Shape::Triangle: { - //TODO_CUSACK: Implement this - return validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents); - } - //Note: Intentional Fallthrough from Quad to Cube - case entity::Shape::Quad: - case entity::Shape::Cube: { - return SHAPE_TYPE_BOX; - } - //Note: Intentional Fallthrough from Hexagon to Sphere - case entity::Shape::Hexagon: - case entity::Shape::Octagon: - case entity::Shape::Circle: - case entity::Shape::Sphere: { - return validateShapeType(SHAPE_TYPE_SPHERE, halfExtents); - } - - case entity::Shape::Cylinder: { - return validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents); - } - - //Note: Intentional Fallthrough from Tetrahedron to Icosahedron - case entity::Shape::Tetrahedron: - case entity::Shape::Octahedron: - case entity::Shape::Dodecahedron: - case entity::Shape::Icosahedron: { - - //TODO_CUSACK: Implement the hedrons - return validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents); - } - - //Note: Intentional Fallthrough from Torus to default. - case entity::Shape::Torus: - case entity::Shape::Cone: { - - // These types are currently unsupported - } - default: - return SHAPE_TYPE_NONE; - } - -} - const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; int type = info.getType(); @@ -372,37 +255,32 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) shape = new btBoxShape(glmToBullet(info.getHalfExtents())); } break; - //case SHAPE_TYPE_SPHERE: { - // glm::vec3 halfExtents = info.getHalfExtents(); - // float radius = glm::max(halfExtents.x, glm::max(halfExtents.y, halfExtents.z)); - // shape = new btSphereShape(radius); - //} - //break; - case SHAPE_TYPE_SPHERE: - case SHAPE_TYPE_ELLIPSOID: { + case SHAPE_TYPE_SPHERE: { glm::vec3 halfExtents = info.getHalfExtents(); - //float radius = halfExtents.x; - //const float MIN_RADIUS = 0.001f; - //const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; - //if (radius > MIN_RADIUS - // && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR - // && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { - // // close enough to true sphere - // shape = new btSphereShape(radius); - //} else { - // ShapeInfo::PointList points; - // points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); - // for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { - // points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); - // } - // shape = createConvexHull(points); - //} - - validateShapeType(SHAPE_TYPE_ELLIPSOID, halfExtents, &shape); + float radius = glm::max(halfExtents.x, glm::max(halfExtents.y, halfExtents.z)); + shape = new btSphereShape(radius); + } + break; + case SHAPE_TYPE_ELLIPSOID: { + glm::vec3 halfExtents = info.getHalfExtents(); + float radius = halfExtents.x; + const float MIN_RADIUS = 0.001f; + const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; + if (radius > MIN_RADIUS + && fabsf(radius - halfExtents.y) / radius < MIN_RELATIVE_SPHERICAL_ERROR + && fabsf(radius - halfExtents.z) / radius < MIN_RELATIVE_SPHERICAL_ERROR) { + // close enough to true sphere + shape = new btSphereShape(radius); + } else { + ShapeInfo::PointList points; + points.reserve(NUM_UNIT_SPHERE_DIRECTIONS); + for (uint32_t i = 0; i < NUM_UNIT_SPHERE_DIRECTIONS; ++i) { + points.push_back(bulletToGLM(_unitSphereDirections[i]) * halfExtents); + } + shape = createConvexHull(points); + } } break; - //TODO_CUSACK: Add Capsules to vetting/validation process for - // type checks. case SHAPE_TYPE_CAPSULE_Y: { glm::vec3 halfExtents = info.getHalfExtents(); float radius = halfExtents.x; @@ -424,30 +302,22 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) shape = new btCapsuleShapeZ(radius, height); } break; - case SHAPE_TYPE_CYLINDER_X: - case SHAPE_TYPE_CYLINDER_Z: - case SHAPE_TYPE_CYLINDER_Y: { - // TODO_CUSACK: Should allow for minor variance along axes. + case SHAPE_TYPE_CYLINDER_X: { const glm::vec3 halfExtents = info.getHalfExtents(); - //const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); - //if ((halfExtents.y > halfExtents.x) && (halfExtents.y > halfExtents.z)) { - // shape = new btCylinderShape(btHalfExtents); - //} - //else if (halfExtents.x > halfExtents.z) { - // shape = new btCylinderShapeX(btHalfExtents); - //} - //else if (halfExtents.z > halfExtents.x) { - // shape = new btCylinderShapeZ(btHalfExtents); - //} - //else //...there was no major axis, treat as a sphere - //{ - // //TODO_CUSACK: Shunt to ELLIPSOID handling - //} - validateShapeType(SHAPE_TYPE_CYLINDER_Y, halfExtents, &shape); + const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); + shape = new btCylinderShapeX(btHalfExtents); + } + case SHAPE_TYPE_CYLINDER_Z: { + const glm::vec3 halfExtents = info.getHalfExtents(); + const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); + shape = new btCylinderShapeZ(btHalfExtents); + } + case SHAPE_TYPE_CYLINDER_Y: { + const glm::vec3 halfExtents = info.getHalfExtents(); + const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); + shape = new btCylinderShape(btHalfExtents); } break; - //TODO_CUSACK: Add compound and simple hull to vetting/validation - // process for types. case SHAPE_TYPE_COMPOUND: case SHAPE_TYPE_SIMPLE_HULL: { const ShapeInfo::PointCollection& pointCollection = info.getPointCollection(); diff --git a/libraries/physics/src/ShapeFactory.h b/libraries/physics/src/ShapeFactory.h index 52b448ee1d..2bf79f390c 100644 --- a/libraries/physics/src/ShapeFactory.h +++ b/libraries/physics/src/ShapeFactory.h @@ -15,14 +15,11 @@ #include #include -#include //< Needed for entity::Shape #include // translates between ShapeInfo and btShape namespace ShapeFactory { - - ShapeType computeShapeType( entity::Shape shape, const glm::vec3 &entityDimensions); const btCollisionShape* createShapeFromInfo(const ShapeInfo& info); void deleteShape(const btCollisionShape* shape); diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 57e927eaf3..5d6b4ece7a 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -29,8 +29,8 @@ void ShapeInfo::clear() { } void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) { - //TODO_CUSACK: Does this need additional cases and handling added? - _url = ""; + //TODO_CUSACK: Does this need additional cases and handling added? + _url = ""; _type = type; setHalfExtents(halfExtents); switch(type) { diff --git a/scripts/developer/tests/basicEntityTest/entitySpawner.js b/scripts/developer/tests/basicEntityTest/entitySpawner.js index fa5c9291cb..538e9145f5 100644 --- a/scripts/developer/tests/basicEntityTest/entitySpawner.js +++ b/scripts/developer/tests/basicEntityTest/entitySpawner.js @@ -8,9 +8,7 @@ var SCRIPT_URL = Script.resolvePath("myEntityScript.js") var myEntity = Entities.addEntity({ - name: "Cusack_Testing", - type: "Shape", - shapeType: "Cylinder", + type: "Sphere", color: { red: 200, green: 10, From ef1e426273b3412e63ee511495f8013375250245 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Tue, 25 Jul 2017 14:09:46 -0400 Subject: [PATCH 4/7] [WL21389] Some code and todo cleanup in prep for PR1. Changes to be committed: modified: libraries/entities-renderer/src/RenderableShapeEntityItem.cpp modified: libraries/entities/src/ShapeEntityItem.cpp modified: libraries/physics/src/ShapeFactory.cpp modified: libraries/shared/src/ShapeInfo.cpp --- .../src/RenderableShapeEntityItem.cpp | 29 +++++-------------- libraries/entities/src/ShapeEntityItem.cpp | 7 ++--- libraries/physics/src/ShapeFactory.cpp | 2 ++ libraries/shared/src/ShapeInfo.cpp | 20 ++++++------- 4 files changed, 22 insertions(+), 36 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index a305b201d6..5fa2354bd5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -114,26 +114,13 @@ void RenderableShapeEntityItem::computeShapeInfo(ShapeInfo& info) { break; case entity::Shape::Cylinder: { _collisionShapeType = SHAPE_TYPE_CYLINDER_Y; - // TODO_CUSACK: determine if rotation is axis-aligned + // TODO WL21389: determine if rotation is axis-aligned //const Transform::Quat & rot = _transform.getRotation(); -#if 0 - // TODO: some way to tell apart SHAPE_TYPE_CYLINDER_Y - // TODO_CUSACK: Should allow for minor variance along axes? - if ((entityDimensions.y >= entityDimensions.x) && (entityDimensions.y >= entityDimensions.z)) { - } - else if (entityDimensions.x >= entityDimensions.z) { - _collisionShapeType = SHAPE_TYPE_CYLINDER_X; - } - else if (entityDimensions.z >= entityDimensions.x) { - _collisionShapeType = SHAPE_TYPE_CYLINDER_Z; - } - else //...there was no major axis, treat as a hull - { - _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; - //TODO_CUSACK: pointCollection - } -#endif + // TODO WL21389: some way to tell apart SHAPE_TYPE_CYLINDER_Y, _X, _Z based on rotation and + // hull ( or dimensions, need circular cross section) + // Should allow for minor variance along axes? + } break; case entity::Shape::Triangle: @@ -145,15 +132,15 @@ void RenderableShapeEntityItem::computeShapeInfo(ShapeInfo& info) { case entity::Shape::Dodecahedron: case entity::Shape::Icosahedron: case entity::Shape::Cone: { - _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; - //TODO_CUSACK: pointCollection + //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later) + //_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; } break; case entity::Shape::Torus: { // Not in GeometryCache::buildShapes, unsupported. _collisionShapeType = SHAPE_TYPE_NONE; - //TODO_CUSACK: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later) + //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later if desired support) } break; default:{ diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 58799de807..157e3afab3 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -88,14 +88,14 @@ EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredP void ShapeEntityItem::setShape(const entity::Shape& shape) { _shape = shape; - switch (_shape) { // TODO_CUSACK fill out? + switch (_shape) { // TODO WL21389: fill out with other shapes? case entity::Shape::Cube: _type = EntityTypes::Box; _collisionShapeType = ShapeType::SHAPE_TYPE_BOX; break; case entity::Shape::Sphere: _type = EntityTypes::Sphere; - _collisionShapeType = ShapeType::SHAPE_TYPE_ELLIPSOID; // TODO_CUSACK defer? Check to see if sphere is more appropriate? + _collisionShapeType = ShapeType::SHAPE_TYPE_ELLIPSOID; break; default: _type = EntityTypes::Shape; @@ -162,8 +162,7 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); } -// This value specifes how the shape should be treated by physics calculations. -// For now, all polys will act as spheres +// This value specifes how the shape should be treated by physics calculations. ShapeType ShapeEntityItem::getShapeType() const { return _collisionShapeType; } diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index 87580c6726..97174b2216 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -307,11 +307,13 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); shape = new btCylinderShapeX(btHalfExtents); } + break; case SHAPE_TYPE_CYLINDER_Z: { const glm::vec3 halfExtents = info.getHalfExtents(); const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); shape = new btCylinderShapeZ(btHalfExtents); } + break; case SHAPE_TYPE_CYLINDER_Y: { const glm::vec3 halfExtents = info.getHalfExtents(); const btVector3 btHalfExtents(halfExtents.x, halfExtents.y, halfExtents.z); diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 5d6b4ece7a..5930880859 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -29,7 +29,7 @@ void ShapeInfo::clear() { } void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) { - //TODO_CUSACK: Does this need additional cases and handling added? + //TODO WL21389: Does this need additional cases and handling added? _url = ""; _type = type; setHalfExtents(halfExtents); @@ -56,8 +56,9 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString } void ShapeInfo::setBox(const glm::vec3& halfExtents) { - //TODO_CUSACK: Should this pointlist clearance added in case + //TODO WL21389: Should this pointlist clearance added in case // this is a re-purposed instance? + // See https://github.com/highfidelity/hifi/pull/11024#discussion_r128885491 _url = ""; _type = SHAPE_TYPE_BOX; setHalfExtents(halfExtents); @@ -65,8 +66,7 @@ void ShapeInfo::setBox(const glm::vec3& halfExtents) { } void ShapeInfo::setSphere(float radius) { - //TODO_CUSACK: Should this pointlist clearance added in case - // this is a re-purposed instance? + //TODO WL21389: See comment in setBox regarding clearance _url = ""; _type = SHAPE_TYPE_SPHERE; radius = glm::max(radius, MIN_HALF_EXTENT); @@ -75,17 +75,14 @@ void ShapeInfo::setSphere(float radius) { } void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) { - //TODO_CUSACK: Should this have protection against inadvertant clearance and type - // resetting? If for some reason this was called and point list was and is emtpy - // would we still wish to clear out everything? + //TODO WL21389: May need to skip resetting type here. _pointCollection = pointCollection; _type = (_pointCollection.size() > 0) ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; _doubleHashKey.clear(); } void ShapeInfo::setCapsuleY(float radius, float halfHeight) { - //TODO_CUSACK: Should this pointlist clearance added in case - // this is a re-purposed instance? + //TODO WL21389: See comment in setBox regarding clearance _url = ""; _type = SHAPE_TYPE_CAPSULE_Y; radius = glm::max(radius, MIN_HALF_EXTENT); @@ -127,7 +124,7 @@ int ShapeInfo::getLargestSubshapePointCount() const { } float ShapeInfo::computeVolume() const { - //TODO_CUSACK: Add support for other ShapeTypes. + //TODO WL21389: Add support for other ShapeTypes. const float DEFAULT_VOLUME = 1.0f; float volume = DEFAULT_VOLUME; switch(_type) { @@ -161,7 +158,7 @@ float ShapeInfo::computeVolume() const { } bool ShapeInfo::contains(const glm::vec3& point) const { - //TODO_CUSACK: Add support for other ShapeTypes like Ellipsoid/Compound. + //TODO WL21389: Add support for other ShapeTypes like Ellipsoid/Compound. switch(_type) { case SHAPE_TYPE_SPHERE: return glm::length(point) <= _halfExtents.x; @@ -206,6 +203,7 @@ bool ShapeInfo::contains(const glm::vec3& point) const { } const DoubleHashKey& ShapeInfo::getHash() const { + //TODO WL21389: Need to include the pointlist for SIMPLE_HULL in hash // NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance. if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) { bool useOffset = glm::length2(_offset) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET; From 6b5cabf00af08e4278828da0ac3fceec45a6f717 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper <1p-cusack@1stplayable.com> Date: Tue, 25 Jul 2017 18:12:07 -0400 Subject: [PATCH 5/7] [WL21389] Minor: Mark RenderableShapeEntityItem::computeShapeInfo as an override. Changes Committed: modified: libraries/entities-renderer/src/RenderableShapeEntityItem.h --- libraries/entities-renderer/src/RenderableShapeEntityItem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 2a841df57e..f93e4b991e 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -28,7 +28,7 @@ public: bool isTransparent() override; - virtual void computeShapeInfo(ShapeInfo& info); + virtual void computeShapeInfo(ShapeInfo& info) override; private: std::unique_ptr _procedural { nullptr }; From cc4fbc97cdab663701315f823e928e9fd2429646 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper <1p-cusack@1stplayable.com> Date: Fri, 28 Jul 2017 15:59:17 -0400 Subject: [PATCH 6/7] [WL21389] PR1 Update based on code review discussion & feedback (details below). * Removed some left overs from prior approach. * Moved _collisionShapeType & getShapeType override from ShapeEntityItem to RenderableShapeEntityItem (see thread: https://github.com/highfidelity/hifi/pull/11048#discussion_r130154903) * Switched _collisionShapeType default from SHAPE_TYPE_NONE to SHAPE_TYPE_ELLIPSOID ** see thread: https://github.com/highfidelity/hifi/pull/11048#discussion_r129982909 Note(s): * Retested and the cylinder behaves as expected along with the Box & Sphere shapes save from the previously mentioned caveats in the PR notes (https://github.com/highfidelity/hifi/pull/11048) * Confirmed that currently unsupported shapes (hedrons, polygons, & cone) fallback to ellipsoid behavior given default change. Changes Committed: modified: libraries/entities-renderer/src/RenderableShapeEntityItem.cpp modified: libraries/entities-renderer/src/RenderableShapeEntityItem.h modified: libraries/entities/src/ShapeEntityItem.cpp modified: libraries/entities/src/ShapeEntityItem.h modified: libraries/shared/src/ShapeInfo.cpp --- .../src/RenderableShapeEntityItem.cpp | 112 +++++++++--------- .../src/RenderableShapeEntityItem.h | 7 ++ libraries/entities/src/ShapeEntityItem.cpp | 9 +- libraries/entities/src/ShapeEntityItem.h | 2 - libraries/shared/src/ShapeInfo.cpp | 2 +- 5 files changed, 67 insertions(+), 65 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 5fa2354bd5..c853335915 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -91,67 +90,72 @@ void RenderableShapeEntityItem::computeShapeInfo(ShapeInfo& info) { const glm::vec3 entityDimensions = getDimensions(); switch (_shape){ - case entity::Shape::Quad: - case entity::Shape::Cube: { - _collisionShapeType = SHAPE_TYPE_BOX; - } - break; - case entity::Shape::Sphere: { - - float diameter = entityDimensions.x; - const float MIN_DIAMETER = 0.001f; - const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; - if (diameter > MIN_DIAMETER - && fabsf(diameter - entityDimensions.y) / diameter < MIN_RELATIVE_SPHERICAL_ERROR - && fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) { - - _collisionShapeType = SHAPE_TYPE_SPHERE; + case entity::Shape::Quad: + case entity::Shape::Cube: { + _collisionShapeType = SHAPE_TYPE_BOX; } - else { + break; + case entity::Shape::Sphere: { + + float diameter = entityDimensions.x; + const float MIN_DIAMETER = 0.001f; + const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; + if (diameter > MIN_DIAMETER + && fabsf(diameter - entityDimensions.y) / diameter < MIN_RELATIVE_SPHERICAL_ERROR + && fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) { + + _collisionShapeType = SHAPE_TYPE_SPHERE; + } + else { + _collisionShapeType = SHAPE_TYPE_ELLIPSOID; + } + } + break; + case entity::Shape::Cylinder: { + _collisionShapeType = SHAPE_TYPE_CYLINDER_Y; + // TODO WL21389: determine if rotation is axis-aligned + //const Transform::Quat & rot = _transform.getRotation(); + + // TODO WL21389: some way to tell apart SHAPE_TYPE_CYLINDER_Y, _X, _Z based on rotation and + // hull ( or dimensions, need circular cross section) + // Should allow for minor variance along axes? + + } + break; + case entity::Shape::Triangle: + case entity::Shape::Hexagon: + case entity::Shape::Octagon: + case entity::Shape::Circle: + case entity::Shape::Tetrahedron: + case entity::Shape::Octahedron: + case entity::Shape::Dodecahedron: + case entity::Shape::Icosahedron: + case entity::Shape::Cone: { + //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later) + //_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; + } + break; + case entity::Shape::Torus: + { + // Not in GeometryCache::buildShapes, unsupported. + _collisionShapeType = SHAPE_TYPE_ELLIPSOID; + //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later if desired support) + } + break; + default:{ _collisionShapeType = SHAPE_TYPE_ELLIPSOID; } - } - break; - case entity::Shape::Cylinder: { - _collisionShapeType = SHAPE_TYPE_CYLINDER_Y; - // TODO WL21389: determine if rotation is axis-aligned - //const Transform::Quat & rot = _transform.getRotation(); - - // TODO WL21389: some way to tell apart SHAPE_TYPE_CYLINDER_Y, _X, _Z based on rotation and - // hull ( or dimensions, need circular cross section) - // Should allow for minor variance along axes? - - } - break; - case entity::Shape::Triangle: - case entity::Shape::Hexagon: - case entity::Shape::Octagon: - case entity::Shape::Circle: - case entity::Shape::Tetrahedron: - case entity::Shape::Octahedron: - case entity::Shape::Dodecahedron: - case entity::Shape::Icosahedron: - case entity::Shape::Cone: { - //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later) - //_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; - } - break; - case entity::Shape::Torus: - { - // Not in GeometryCache::buildShapes, unsupported. - _collisionShapeType = SHAPE_TYPE_NONE; - //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later if desired support) - } - break; - default:{ - //_collisionShapeType = SHAPE_TYPE_NONE; // Remains SHAPE_TYPE_NONE. - } - break; + break; } EntityItem::computeShapeInfo(info); } +// This value specifes how the shape should be treated by physics calculations. +ShapeType RenderableShapeEntityItem::getShapeType() const { + return _collisionShapeType; +} + void RenderableShapeEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); //Q_ASSERT(getType() == EntityTypes::Shape); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index f93e4b991e..d603cdedef 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -29,10 +29,17 @@ public: bool isTransparent() override; virtual void computeShapeInfo(ShapeInfo& info) override; + ShapeType getShapeType() const override; + private: std::unique_ptr _procedural { nullptr }; + //! This is SHAPE_TYPE_ELLIPSOID rather than SHAPE_TYPE_NONE to maintain + //! prior functionality where new or unsupported shapes are treated as + //! ellipsoids. + ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID }; + SIMPLE_RENDERABLE(); }; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 157e3afab3..eb1bed503c 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -88,14 +88,12 @@ EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredP void ShapeEntityItem::setShape(const entity::Shape& shape) { _shape = shape; - switch (_shape) { // TODO WL21389: fill out with other shapes? + switch (_shape) { case entity::Shape::Cube: _type = EntityTypes::Box; - _collisionShapeType = ShapeType::SHAPE_TYPE_BOX; break; case entity::Shape::Sphere: _type = EntityTypes::Sphere; - _collisionShapeType = ShapeType::SHAPE_TYPE_ELLIPSOID; break; default: _type = EntityTypes::Shape; @@ -162,11 +160,6 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); } -// This value specifes how the shape should be treated by physics calculations. -ShapeType ShapeEntityItem::getShapeType() const { - return _collisionShapeType; -} - void ShapeEntityItem::setColor(const rgbColor& value) { memcpy(_color, value, sizeof(rgbColor)); } diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 42a92f7bd7..60fcfd628a 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -84,7 +84,6 @@ public: QColor getQColor() const; void setColor(const QColor& value); - ShapeType getShapeType() const override; bool shouldBePhysical() const override { return !isDead(); } bool supportsDetailedRayIntersection() const override; @@ -100,7 +99,6 @@ protected: float _alpha { 1 }; rgbColor _color; entity::Shape _shape { entity::Shape::Sphere }; - ShapeType _collisionShapeType { ShapeType::SHAPE_TYPE_NONE }; }; #endif // hifi_ShapeEntityItem_h diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 5930880859..a556548b25 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -124,7 +124,7 @@ int ShapeInfo::getLargestSubshapePointCount() const { } float ShapeInfo::computeVolume() const { - //TODO WL21389: Add support for other ShapeTypes. + //TODO WL21389: Add support for other ShapeTypes( CYLINDER_X, CYLINDER_Y, etc). const float DEFAULT_VOLUME = 1.0f; float volume = DEFAULT_VOLUME; switch(_type) { From 0b79809f547c9ec90c3b611a02972feabdaa3584 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper <1p-cusack@1stplayable.com> Date: Mon, 31 Jul 2017 17:08:30 -0400 Subject: [PATCH 7/7] [WL21389] PR1 Feedback: Small change missed last commit (details below). Until they're properly implemented, default the hedrons and polygons to SHAPE_TYPE_ELLIPSOID within RenderableShapeEntity::computeShapeInfo. Changes committed: modified: libraries/entities-renderer/src/RenderableShapeEntityItem.cpp --- libraries/entities-renderer/src/RenderableShapeEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index c853335915..3f9497741f 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -132,7 +132,7 @@ void RenderableShapeEntityItem::computeShapeInfo(ShapeInfo& info) { case entity::Shape::Icosahedron: case entity::Shape::Cone: { //TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later) - //_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; + _collisionShapeType = SHAPE_TYPE_ELLIPSOID; } break; case entity::Shape::Torus: