diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 08fbb1cea8..84a8d23a74 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -155,6 +155,7 @@ var elModelAnimationSettings = document.getElementById("property-model-animation-settings"); var elModelTextures = document.getElementById("property-model-textures"); var elModelOriginalTextures = document.getElementById("property-model-original-textures"); + var elModelShapeType = document.getElementById("property-model-shape"); var elTextSections = document.querySelectorAll(".text-section"); var elTextText = document.getElementById("property-text-text"); @@ -258,6 +259,7 @@ elModelAnimationSettings.value = properties.animationSettings; elModelTextures.value = properties.textures; elModelOriginalTextures.value = properties.originalTextures; + elModelShapeType.value = properties.shapeType; } if (properties.type != "Text") { @@ -404,6 +406,7 @@ elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex')); elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings')); elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); + elModelShapeType.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeType')); elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); @@ -664,6 +667,17 @@ +
+
Shape Type
+
+ +
+
+
Text
diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 296ff6fee9..6e207f9703 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -760,19 +760,19 @@ void SkeletonModel::buildShapes() { Shape::Type type = joint.shapeType; int parentIndex = joint.parentIndex; if (parentIndex == -1 || radius < EPSILON) { - type = SHAPE_TYPE_UNKNOWN; - } else if (type == SHAPE_TYPE_CAPSULE && halfHeight < EPSILON) { + type = INVALID_SHAPE; + } else if (type == CAPSULE_SHAPE && halfHeight < EPSILON) { // this shape is forced to be a sphere - type = SHAPE_TYPE_SPHERE; + type = SPHERE_SHAPE; } Shape* shape = NULL; - if (type == SHAPE_TYPE_SPHERE) { + if (type == SPHERE_SHAPE) { shape = new VerletSphereShape(radius, &(points[i])); shape->setEntity(this); float mass = massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume()); points[i].setMass(mass); totalMass += mass; - } else if (type == SHAPE_TYPE_CAPSULE) { + } else if (type == CAPSULE_SHAPE) { assert(parentIndex != -1); shape = new VerletCapsuleShape(radius, &(points[parentIndex]), &(points[i])); shape->setEntity(this); diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index 25ef2e6aaf..1e8c811122 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -96,11 +96,6 @@ void BoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); } -void BoxEntityItem::computeShapeInfo(ShapeInfo& info) const { - glm::vec3 halfExtents = 0.5f * getDimensionsInMeters(); - info.setBox(halfExtents); -} - void BoxEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qDebug() << " BOX EntityItem id:" << getEntityItemID() << "---------------------------------------------"; diff --git a/libraries/entities/src/BoxEntityItem.h b/libraries/entities/src/BoxEntityItem.h index 8d68a13158..e8459e7dbb 100644 --- a/libraries/entities/src/BoxEntityItem.h +++ b/libraries/entities/src/BoxEntityItem.h @@ -51,7 +51,7 @@ public: _color[BLUE_INDEX] = value.blue; } - void computeShapeInfo(ShapeInfo& info) const; + virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } virtual void debugDump() const; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 9717143ec0..15d46603b5 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -57,8 +57,6 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _collisionsWillMove = ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE; _locked = ENTITY_ITEM_DEFAULT_LOCKED; _userData = ENTITY_ITEM_DEFAULT_USER_DATA; - - recalculateCollisionShape(); } EntityItem::EntityItem(const EntityItemID& entityItemID) { @@ -70,7 +68,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; _created = UNKNOWN_CREATED_TIME; - _physicsInfo = NULL; _dirtyFlags = 0; _changedOnServer = 0; _element = NULL; @@ -86,7 +83,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert _lastEditedFromRemote = 0; _lastEditedFromRemoteInRemoteTime = 0; _created = UNKNOWN_CREATED_TIME; - _physicsInfo = NULL; _dirtyFlags = 0; _changedOnServer = 0; _element = NULL; @@ -541,7 +537,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData); - recalculateCollisionShape(); if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY))) { // NOTE: This code is attempting to "repair" the old data we just got from the server to make it more // closely match where the entities should be if they'd stepped forward in time to "now". The server @@ -1003,14 +998,7 @@ float EntityItem::getRadius() const { } void EntityItem::computeShapeInfo(ShapeInfo& info) const { - info.clear(); -} - -void EntityItem::recalculateCollisionShape() { - AACube entityAACube = getMinimumAACube(); - entityAACube.scale(TREE_SCALE); // scale to meters - _collisionShape.setTranslation(entityAACube.calcCenter()); - _collisionShape.setScale(entityAACube.getScale()); + info.setParams(getShapeType(), 0.5f * getDimensionsInMeters()); } const float MIN_POSITION_DELTA = 0.0001f; @@ -1023,7 +1011,6 @@ const float MIN_SPIN_DELTA = 0.0003f; void EntityItem::updatePosition(const glm::vec3& value) { if (glm::distance(_position, value) * (float)TREE_SCALE > MIN_POSITION_DELTA) { _position = value; - recalculateCollisionShape(); _dirtyFlags |= EntityItem::DIRTY_POSITION; } } @@ -1032,7 +1019,6 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) { glm::vec3 position = glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f); if (glm::distance(_position, position) * (float)TREE_SCALE > MIN_POSITION_DELTA) { _position = position; - recalculateCollisionShape(); _dirtyFlags |= EntityItem::DIRTY_POSITION; } } @@ -1040,7 +1026,6 @@ void EntityItem::updatePositionInMeters(const glm::vec3& value) { void EntityItem::updateDimensions(const glm::vec3& value) { if (_dimensions != value) { _dimensions = glm::abs(value); - recalculateCollisionShape(); _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); } } @@ -1049,7 +1034,6 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { glm::vec3 dimensions = glm::abs(value) / (float) TREE_SCALE; if (_dimensions != dimensions) { _dimensions = dimensions; - recalculateCollisionShape(); _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS); } } @@ -1057,7 +1041,6 @@ void EntityItem::updateDimensionsInMeters(const glm::vec3& value) { void EntityItem::updateRotation(const glm::quat& rotation) { if (glm::dot(_rotation, rotation) < MIN_ALIGNMENT_DOT) { _rotation = rotation; - recalculateCollisionShape(); _dirtyFlags |= EntityItem::DIRTY_POSITION; } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 27aba8e148..a26783fc7c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -16,7 +16,6 @@ #include -#include #include // for Animation, AnimationCache, and AnimationPointer classes #include #include // for EncodeBitstreamParams class @@ -150,7 +149,7 @@ public: glm::vec3 getPositionInMeters() const { return _position * (float) TREE_SCALE; } /// get position in meters /// set position in domain scale units (0.0 - 1.0) - void setPosition(const glm::vec3& value) { _position = value; recalculateCollisionShape(); } + void setPosition(const glm::vec3& value) { _position = value; } void setPositionInMeters(const glm::vec3& value) /// set position in meter units (0.0 - TREE_SCALE) { setPosition(glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f)); } @@ -162,13 +161,13 @@ 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 - virtual void setDimensions(const glm::vec3& value) { _dimensions = value; recalculateCollisionShape(); } + virtual void setDimensions(const glm::vec3& value) { _dimensions = value; } /// set dimensions in meter units (0.0 - TREE_SCALE) this will also reset radius appropriately void setDimensionsInMeters(const glm::vec3& value) { setDimensions(value / (float) TREE_SCALE); } const glm::quat& getRotation() const { return _rotation; } - void setRotation(const glm::quat& rotation) { _rotation = rotation; recalculateCollisionShape(); } + void setRotation(const glm::quat& rotation) { _rotation = rotation; } float getGlowLevel() const { return _glowLevel; } void setGlowLevel(float glowLevel) { _glowLevel = glowLevel; } @@ -225,7 +224,7 @@ public: /// registration point as ratio of entity void setRegistrationPoint(const glm::vec3& value) - { _registrationPoint = glm::clamp(value, 0.0f, 1.0f); recalculateCollisionShape(); } + { _registrationPoint = glm::clamp(value, 0.0f, 1.0f); } const glm::vec3& getAngularVelocity() const { return _angularVelocity; } void setAngularVelocity(const glm::vec3& value) { _angularVelocity = value; } @@ -254,11 +253,12 @@ public: // TODO: We need to get rid of these users of getRadius()... float getRadius() const; - void applyHardCollision(const CollisionInfo& collisionInfo); - virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; } virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } virtual void computeShapeInfo(ShapeInfo& info) const; + /// return preferred shape type (actual physical shape may differ) + virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; } + // updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags void updatePosition(const glm::vec3& value); void updatePositionInMeters(const glm::vec3& value); @@ -277,6 +277,7 @@ public: void updateIgnoreForCollisions(bool value); void updateCollisionsWillMove(bool value); void updateLifetime(float value); + virtual void updateShapeType(ShapeType type) { /* do nothing */ } uint32_t getDirtyFlags() const { return _dirtyFlags; } void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; } @@ -297,7 +298,6 @@ protected: static bool _sendPhysicsUpdates; virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init - virtual void recalculateCollisionShape(); EntityTypes::EntityType _type; QUuid _id; @@ -353,11 +353,9 @@ protected: /// set radius in domain scale units (0.0 - 1.0) this will also reset dimensions to be equal for each axis void setRadius(float value); - AACubeShape _collisionShape; - // _physicsInfo is a hook reserved for use by the EntitySimulation, which is guaranteed to set _physicsInfo // to a non-NULL value when the EntityItem has a representation in the physics engine. - void* _physicsInfo; // only set by EntitySimulation + void* _physicsInfo = NULL; // only set by EntitySimulation // DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about. uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4da903f6ba..353aab0a64 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -64,6 +64,7 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(lineHeight, TextEntityItem::DEFAULT_LINE_HEIGHT), CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR), CONSTRUCT_PROPERTY(backgroundColor, TextEntityItem::DEFAULT_BACKGROUND_COLOR), + CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE), _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -210,6 +211,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_LINE_HEIGHT, lineHeight); CHECK_PROPERTY_CHANGE(PROP_TEXT_COLOR, textColor); CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_COLOR, backgroundColor); + CHECK_PROPERTY_CHANGE(PROP_SHAPE_TYPE, shapeType); return changedProperties; } @@ -268,6 +270,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); + COPY_PROPERTY_TO_QSCRIPTVALUE(shapeType); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); @@ -347,6 +350,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(shapeType, setShapeType, ShapeType); _lastEdited = usecTimestampNow(); } @@ -510,6 +514,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, properties.getAnimationIsPlaying()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings()); + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)(properties.getShapeType())); } if (properties.getType() == EntityTypes::Light) { @@ -731,6 +736,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType); } if (properties.getType() == EntityTypes::Light) { @@ -820,6 +826,7 @@ void EntityItemProperties::markAllChanged() { _lineHeightChanged = true; _textColorChanged = true; _backgroundColorChanged = true; + _shapeTypeChanged = true; } AACube EntityItemProperties::getMaximumAACubeInTreeUnits() const { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 8d4bf98862..4db6cd5d79 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -26,7 +26,7 @@ #include // for SittingPoint #include #include - +#include #include "EntityItemID.h" #include "EntityItemPropertiesMacros.h" @@ -82,8 +82,10 @@ enum EntityPropertyList { PROP_TEXTURES, PROP_ANIMATION_SETTINGS, PROP_USER_DATA, - - PROP_LAST_ITEM = PROP_USER_DATA, + PROP_SHAPE_TYPE, + + // NOTE: add new properties ABOVE this line and then modify PROP_LAST_ITEM below + PROP_LAST_ITEM = PROP_SHAPE_TYPE, // These properties of TextEntity piggy back off of properties of ModelEntities, the type doesn't matter // since the derived class knows how to interpret it's own properties and knows the types it expects @@ -179,6 +181,7 @@ public: DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); + DEFINE_PROPERTY_REF(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); public: float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 9f86156422..518035c0d3 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -180,6 +180,15 @@ #define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \ properties.setProperty(#P, _##P); +#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S, E) \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + E newValue = (E)(P.toVariant().toInt()); \ + if (_defaultSettings || newValue != _##P) { \ + S(newValue); \ + } \ + } + #define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \ QScriptValue P = object.property(#P); \ if (P.isValid()) { \ diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index aff6e64f57..ecd90e5942 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -11,9 +11,6 @@ #include -#include -#include - #include #include @@ -570,33 +567,6 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad return false; } -bool EntityTreeElement::findShapeCollisions(const Shape* shape, CollisionList& collisions) const { - bool atLeastOneCollision = false; - QList::iterator entityItr = _entityItems->begin(); - QList::const_iterator entityEnd = _entityItems->end(); - while(entityItr != entityEnd) { - EntityItem* entity = (*entityItr); - - // entities that are set for ignore for collisions then don't consider them for collision - const Shape* otherCollisionShape = &entity->getCollisionShapeInMeters(); - - bool ignoreForCollisions = entity->getIgnoreForCollisions(); - if (shape != otherCollisionShape && !ignoreForCollisions) { - if (ShapeCollider::collideShapes(shape, otherCollisionShape, collisions)) { - CollisionInfo* lastCollision = collisions.getLastCollision(); - if (lastCollision) { - lastCollision->_extraData = entity; - atLeastOneCollision = true; - } else { - qDebug() << "UNEXPECTED - ShapeCollider::collideShapes() returned true, but no lastCollision."; - } - } - } - ++entityItr; - } - return atLeastOneCollision; -} - void EntityTreeElement::updateEntityItemID(const EntityItemID& creatorTokenEntityID, const EntityItemID& knownIDEntityID) { uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index 4fbe9db323..0b28dd30d0 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -142,8 +142,6 @@ public: virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; - virtual bool findShapeCollisions(const Shape* shape, CollisionList& collisions) const; - const QList& getEntities() const { return *_entityItems; } QList& getEntities() { return *_entityItems; } bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; } diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index c125364e63..4a8dc2d582 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -42,16 +42,11 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI _cutoff = PI; setProperties(properties); - - // a light is not collide-able so we make it's shape be a tiny sphere at origin - _emptyShape.setTranslation(glm::vec3(0.0f, 0.0f, 0.0f)); - _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(); } diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 249a4c8472..5e39ba26a2 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -12,7 +12,6 @@ #ifndef hifi_LightEntityItem_h #define hifi_LightEntityItem_h -#include #include "EntityItem.h" class LightEntityItem : public EntityItem { @@ -98,13 +97,10 @@ public: float getCutoff() const { return _cutoff; } void setCutoff(float value) { _cutoff = value; } - virtual const Shape& getCollisionShapeInMeters() const { return _emptyShape; } - static bool getLightsArePickable() { return _lightsArePickable; } static void setLightsArePickable(bool value) { _lightsArePickable = value; } protected: - virtual void recalculateCollisionShape() { /* nothing to do */ } // properties of a light rgbColor _ambientColor; @@ -117,9 +113,6 @@ protected: float _exponent; float _cutoff; - // used for collision detection - SphereShape _emptyShape; - static bool _lightsArePickable; }; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index bfab8871a5..4d8e741cc6 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -51,6 +51,7 @@ EntityItemProperties ModelEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); return properties; } @@ -66,6 +67,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType); if (somethingChanged) { bool wantDebug = false; @@ -116,6 +118,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY_STRING(PROP_TEXTURES, setTextures); READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings); + READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType); return bytesRead; } @@ -131,6 +134,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_ANIMATION_PLAYING; requestedProperties += PROP_ANIMATION_SETTINGS; requestedProperties += PROP_TEXTURES; + requestedProperties += PROP_SHAPE_TYPE; return requestedProperties; } @@ -153,6 +157,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, getTextures()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings()); + APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType()); } @@ -245,21 +250,6 @@ bool ModelEntityItem::needsToCallUpdate() const { return isAnimatingSomething() ? true : EntityItem::needsToCallUpdate(); } -void ModelEntityItem::computeShapeInfo(ShapeInfo& info) const { - // HACK: Default first first approximation is to boxify the entity... but only if it is small enough. - // The limit here is chosen to something that most avatars could not comfortably fit inside - // to prevent houses from getting boxified... we don't want the things inside houses to - // collide with a house as if it were a giant solid block. - const float MAX_SIZE_FOR_BOXIFICATION_HACK = 3.0f; - float diagonal = glm::length(getDimensionsInMeters()); - if (diagonal < MAX_SIZE_FOR_BOXIFICATION_HACK) { - glm::vec3 halfExtents = 0.5f * getDimensionsInMeters(); - info.setBox(halfExtents); - } else { - info.clear(); - } -} - void ModelEntityItem::update(const quint64& now) { // only advance the frame index if we're playing if (getAnimationIsPlaying()) { @@ -280,6 +270,13 @@ void ModelEntityItem::debugDump() const { qDebug() << " model URL:" << getModelURL(); } +void ModelEntityItem::updateShapeType(ShapeType type) { + if (type != _shapeType) { + _shapeType = type; + _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; + } +} + void ModelEntityItem::setAnimationURL(const QString& url) { _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; _animationURL = url; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 3db2a40db0..94d262fc9f 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -46,9 +46,10 @@ public: virtual void update(const quint64& now); virtual bool needsToCallUpdate() const; - void computeShapeInfo(ShapeInfo& info) const; virtual void debugDump() const; + void updateShapeType(ShapeType type); + virtual ShapeType getShapeType() const { return _shapeType; } // TODO: Move these to subclasses, or other appropriate abstraction // getters/setters applicable to models and particles @@ -126,6 +127,7 @@ protected: AnimationLoop _animationLoop; QString _animationSettings; QString _textures; + ShapeType _shapeType = SHAPE_TYPE_NONE; // used on client side bool _jointMappingCompleted; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 181e5851f6..7d5fb83a4e 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -94,19 +94,6 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); } -void SphereEntityItem::recalculateCollisionShape() { - _sphereShape.setTranslation(getCenterInMeters()); - glm::vec3 dimensionsInMeters = getDimensionsInMeters(); - float largestDiameter = glm::max(dimensionsInMeters.x, dimensionsInMeters.y, dimensionsInMeters.z); - _sphereShape.setRadius(largestDiameter / 2.0f); -} - -void SphereEntityItem::computeShapeInfo(ShapeInfo& info) const { - glm::vec3 halfExtents = 0.5f * getDimensionsInMeters(); - // TODO: support ellipsoid shapes - info.setSphere(halfExtents.x); -} - bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index f76c9f5600..f79a2db7ff 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -12,7 +12,6 @@ #ifndef hifi_SphereEntityItem_h #define hifi_SphereEntityItem_h -#include #include "EntityItem.h" class SphereEntityItem : public EntityItem { @@ -51,12 +50,10 @@ public: _color[BLUE_INDEX] = value.blue; } - virtual const Shape& getCollisionShapeInMeters() const { return _sphereShape; } - // TODO: implement proper contains for 3D ellipsoid //virtual bool contains(const glm::vec3& point) const; - void computeShapeInfo(ShapeInfo& info) const; + virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; } virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -66,10 +63,8 @@ public: virtual void debugDump() const; protected: - virtual void recalculateCollisionShape(); rgbColor _color; - SphereShape _sphereShape; }; #endif // hifi_SphereEntityItem_h diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index c43638f827..ac9a080119 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -44,7 +44,6 @@ 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 { diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 1f0bd7d85e..d57b5442d6 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -24,6 +24,7 @@ public: /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately virtual void setDimensions(const glm::vec3& value); + virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 043bd43115..3502dd219f 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "FBXReader.h" @@ -1950,7 +1951,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, joint.inverseBindRotation = joint.inverseDefaultRotation; joint.name = model.name; joint.shapePosition = glm::vec3(0.0f); - joint.shapeType = SHAPE_TYPE_UNKNOWN; + joint.shapeType = INVALID_SHAPE; foreach (const QString& childID, childMap.values(modelID)) { QString type = typeFlags.value(childID); @@ -2374,10 +2375,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, if (collideLikeCapsule) { joint.shapeRotation = rotationBetween(defaultCapsuleAxis, jointShapeInfo.boneBegin); joint.shapePosition = 0.5f * jointShapeInfo.boneBegin; - joint.shapeType = SHAPE_TYPE_CAPSULE; + joint.shapeType = CAPSULE_SHAPE; } else { // collide the joint like a sphere - joint.shapeType = SHAPE_TYPE_SPHERE; + joint.shapeType = SPHERE_SHAPE; if (jointShapeInfo.numVertices > 0) { jointShapeInfo.averageVertex /= (float)jointShapeInfo.numVertices; joint.shapePosition = jointShapeInfo.averageVertex; @@ -2397,8 +2398,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, if (distanceFromEnd > joint.distanceToParent && distanceFromBegin > joint.distanceToParent) { // The shape is further from both joint endpoints than the endpoints are from each other // which probably means the model has a bad transform somewhere. We disable this shape - // by setting its type to SHAPE_TYPE_UNKNOWN. - joint.shapeType = SHAPE_TYPE_UNKNOWN; + // by setting its type to INVALID_SHAPE. + joint.shapeType = INVALID_SHAPE; } } } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index b706549c3e..3f6f836950 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -18,12 +18,13 @@ #include #include -#include -#include - #include #include +#include +#include +#include + #include #include @@ -53,12 +54,6 @@ public: QVector normals; }; -enum ShapeType { - SHAPE_TYPE_SPHERE = 0, - SHAPE_TYPE_CAPSULE = 1, - SHAPE_TYPE_UNKNOWN = 2 -}; - /// A single joint (transformation node) extracted from an FBX document. class FBXJoint { public: @@ -83,7 +78,7 @@ public: QString name; glm::vec3 shapePosition; // in joint frame glm::quat shapeRotation; // in joint frame - ShapeType shapeType; + quint8 shapeType; bool isSkeletonJoint; }; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index d2806f3db5..2eee540fff 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME; + return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index f0d21ca9f8..e593955b51 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -127,6 +127,7 @@ const PacketVersion VERSION_ENTITIES_SUPPORT_DIMENSIONS = 4; const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5; const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6; const PacketVersion VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME = 7; +const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE = 8; const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 9abf0ec7a1..e925ea5aba 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include "CoverageMap.h" #include "OctreeConstants.h" @@ -856,26 +855,6 @@ bool findCapsulePenetrationOp(OctreeElement* element, void* extraData) { return false; } -bool findShapeCollisionsOp(OctreeElement* element, void* extraData) { - ShapeArgs* args = static_cast(extraData); - // coarse check against bounds - AACube cube = element->getAACube(); - cube.scale(TREE_SCALE); - if (!cube.expandedContains(args->shape->getTranslation(), args->shape->getBoundingRadius())) { - return false; - } - if (element->hasContent()) { - if (element->findShapeCollisions(args->shape, args->collisions)) { - args->found = true; - return true; - } - } - if (!element->isLeaf()) { - return true; // recurse on children - } - return false; -} - uint qHash(const glm::vec3& point) { // NOTE: TREE_SCALE = 16384 (15 bits) and multiplier is 1024 (11 bits), // so each component (26 bits) uses more than its alloted 21 bits. @@ -947,37 +926,6 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end return args.found; } -bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions, - Octree::lockType lockType, bool* accurateResult) { - - ShapeArgs args = { shape, collisions, false }; - - bool gotLock = false; - if (lockType == Octree::Lock) { - lockForRead(); - gotLock = true; - } else if (lockType == Octree::TryLock) { - gotLock = tryLockForRead(); - if (!gotLock) { - if (accurateResult) { - *accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate - } - return args.found; // if we wanted to tryLock, and we couldn't then just bail... - } - } - - recurseTreeWithOperation(findShapeCollisionsOp, &args); - - if (gotLock) { - unlock(); - } - - if (accurateResult) { - *accurateResult = true; // if user asked to accuracy or result, let them know this is accurate - } - return args.found; -} - bool Octree::findContentInCube(const AACube& cube, CubeList& cubes) { if (!tryLockForRead()) { return false; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index cde8565ca2..870e18983e 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -308,9 +308,6 @@ public: bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration, Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); - bool findShapeCollisions(const Shape* shape, CollisionList& collisions, - Octree::lockType = Octree::TryLock, bool* accurateResult = NULL); - bool findContentInCube(const AACube& cube, CubeList& cubes); OctreeElement* getElementEnclosingPoint(const glm::vec3& point, diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e74b6619bd..93792678e2 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include "AACube.h" #include "OctalCode.h" @@ -1396,12 +1395,6 @@ bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, return _cube.findSpherePenetration(center, radius, penetration); } -bool OctreeElement::findShapeCollisions(const Shape* shape, CollisionList& collisions) const { - AACube cube = getAACube(); - cube.scale(TREE_SCALE); - return ShapeCollider::collideShapeWithAACubeLegacy(shape, cube.calcCenter(), cube.getScale(), collisions); -} - // TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)... OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) { OctreeElement* child = NULL; diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 434342372f..8c83d9976e 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -128,8 +128,6 @@ public: virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const; - virtual bool findShapeCollisions(const Shape* shape, CollisionList& collisions) const; - // Base class methods you don't need to implement const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode.pointer : &_octalCode.buffer[0]; } OctreeElement* getChildAtIndex(int childIndex) const; diff --git a/libraries/physics/src/ShapeInfoUtil.cpp b/libraries/physics/src/ShapeInfoUtil.cpp index 0e9dc55a8c..e98bb07052 100644 --- a/libraries/physics/src/ShapeInfoUtil.cpp +++ b/libraries/physics/src/ShapeInfoUtil.cpp @@ -9,7 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include // for FOO_SHAPE types #include // for MILLIMETERS_PER_METER #include "ShapeInfoUtil.h" @@ -18,36 +17,30 @@ int ShapeInfoUtil::toBulletShapeType(int shapeInfoType) { int bulletShapeType = INVALID_SHAPE_PROXYTYPE; switch(shapeInfoType) { - case BOX_SHAPE: + case SHAPE_TYPE_BOX: bulletShapeType = BOX_SHAPE_PROXYTYPE; break; - case SPHERE_SHAPE: + case SHAPE_TYPE_SPHERE: bulletShapeType = SPHERE_SHAPE_PROXYTYPE; break; - case CAPSULE_SHAPE: + case SHAPE_TYPE_CAPSULE_Y: bulletShapeType = CAPSULE_SHAPE_PROXYTYPE; break; - case CYLINDER_SHAPE: - bulletShapeType = CYLINDER_SHAPE_PROXYTYPE; - break; } return bulletShapeType; } int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) { - int shapeInfoType = INVALID_SHAPE; + int shapeInfoType = SHAPE_TYPE_NONE; switch(bulletShapeType) { case BOX_SHAPE_PROXYTYPE: - shapeInfoType = BOX_SHAPE; + shapeInfoType = SHAPE_TYPE_BOX; break; case SPHERE_SHAPE_PROXYTYPE: - shapeInfoType = SPHERE_SHAPE; + shapeInfoType = SHAPE_TYPE_SPHERE; break; case CAPSULE_SHAPE_PROXYTYPE: - shapeInfoType = CAPSULE_SHAPE; - break; - case CYLINDER_SHAPE_PROXYTYPE: - shapeInfoType = CYLINDER_SHAPE; + shapeInfoType = SHAPE_TYPE_CAPSULE_Y; break; } return shapeInfoType; @@ -57,29 +50,16 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf if (shape) { int type = ShapeInfoUtil::fromBulletShapeType(shape->getShapeType()); switch(type) { - case BOX_SHAPE: { + case SHAPE_TYPE_BOX: { const btBoxShape* boxShape = static_cast(shape); info.setBox(bulletToGLM(boxShape->getHalfExtentsWithMargin())); } break; - case SPHERE_SHAPE: { + case SHAPE_TYPE_SPHERE: { const btSphereShape* sphereShape = static_cast(shape); info.setSphere(sphereShape->getRadius()); } break; - case CYLINDER_SHAPE: { - // NOTE: we only support cylinders along yAxis - const btCylinderShape* cylinderShape = static_cast(shape); - btVector3 halfExtents = cylinderShape->getHalfExtentsWithMargin(); - info.setCylinder(halfExtents.getX(), halfExtents.getY()); - } - break; - case CAPSULE_SHAPE: { - // NOTE: we only support capsules along yAxis - const btCapsuleShape* capsuleShape = static_cast(shape); - info.setCapsule(capsuleShape->getRadius(), capsuleShape->getHalfHeight()); - } - break; default: info.clear(); break; @@ -91,77 +71,23 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; - const QVector& data = info.getData(); switch(info.getType()) { - case BOX_SHAPE: { - // data[0] is halfExtents - shape = new btBoxShape(glmToBullet(data[0])); + case SHAPE_TYPE_BOX: { + shape = new btBoxShape(glmToBullet(info.getHalfExtents())); } break; - case SPHERE_SHAPE: { - float radius = data[0].z; + case SHAPE_TYPE_SPHERE: { + float radius = info.getHalfExtents().x; shape = new btSphereShape(radius); } break; - case CYLINDER_SHAPE: { - // NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X - // data[0] = btVector3(radius, halfHeight, unused) - shape = new btCylinderShape(glmToBullet(data[0])); - } - break; - case CAPSULE_SHAPE: { - float radius = data[0].x; - float height = 2.0f * data[0].y; + case SHAPE_TYPE_CAPSULE_Y: { + glm::vec3 halfExtents = info.getHalfExtents(); + float radius = halfExtents.x; + float height = 2.0f * halfExtents.y; shape = new btCapsuleShape(radius, height); } break; } return shape; } - -DoubleHashKey ShapeInfoUtil::computeHash(const ShapeInfo& info) { - DoubleHashKey key; - // compute hash - // scramble the bits of the type - // TODO?: provide lookup table for hash of info._type rather than recompute? - int primeIndex = 0; - unsigned int hash = DoubleHashKey::hashFunction((unsigned int)info.getType(), primeIndex++); - const QVector& data = info.getData(); - - glm::vec3 tmpData; - int numData = data.size(); - for (int i = 0; i < numData; ++i) { - tmpData = data[i]; - for (int j = 0; j < 3; ++j) { - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - unsigned int floatHash = - DoubleHashKey::hashFunction((int)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f), primeIndex++); - hash ^= floatHash; - } - } - key._hash = (int)hash; - - // compute hash2 - // scramble the bits of the type - // TODO?: provide lookup table for hash2 of info._type rather than recompute? - hash = DoubleHashKey::hashFunction2((unsigned int)info.getType()); - - for (int i = 0; i < numData; ++i) { - tmpData = data[i]; - for (int j = 0; j < 3; ++j) { - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - unsigned int floatHash = - DoubleHashKey::hashFunction2((int)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f)); - hash += ~(floatHash << 17); - hash ^= (floatHash >> 11); - hash += (floatHash << 4); - hash ^= (floatHash >> 7); - hash += ~(floatHash << 10); - hash = (hash << 16) | (hash >> 16); - } - } - key._hash2 = (int)hash; - return key; -} diff --git a/libraries/physics/src/ShapeInfoUtil.h b/libraries/physics/src/ShapeInfoUtil.h index 438e3df715..fb59f30c69 100644 --- a/libraries/physics/src/ShapeInfoUtil.h +++ b/libraries/physics/src/ShapeInfoUtil.h @@ -17,8 +17,6 @@ #include -#include "DoubleHashKey.h" - // translates between ShapeInfo and btShape namespace ShapeInfoUtil { @@ -26,8 +24,6 @@ namespace ShapeInfoUtil { btCollisionShape* createShapeFromInfo(const ShapeInfo& info); - DoubleHashKey computeHash(const ShapeInfo& info); - // TODO? just use bullet shape types everywhere? int toBulletShapeType(int shapeInfoType); int fromBulletShapeType(int bulletShapeType); diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index b153150ce6..02228bf7aa 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -27,14 +27,17 @@ ShapeManager::~ShapeManager() { } btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { + if (info.getType() == SHAPE_TYPE_NONE) { + return NULL; + } // Very small or large objects are not supported. - float diagonal = glm::length2(info.getBoundingBoxDiagonal()); + float diagonal = 4.0f * glm::length2(info.getHalfExtents()); const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e4f; // 100 m cube if (diagonal < MIN_SHAPE_DIAGONAL_SQUARED || diagonal > MAX_SHAPE_DIAGONAL_SQUARED) { return NULL; } - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { shapeRef->_refCount++; @@ -51,7 +54,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { } bool ShapeManager::releaseShape(const ShapeInfo& info) { - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { if (shapeRef->_refCount > 0) { @@ -95,7 +98,7 @@ void ShapeManager::collectGarbage() { } int ShapeManager::getNumReferences(const ShapeInfo& info) const { - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); const ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { return shapeRef->_refCount; diff --git a/libraries/physics/src/DoubleHashKey.cpp b/libraries/shared/src/DoubleHashKey.cpp similarity index 66% rename from libraries/physics/src/DoubleHashKey.cpp rename to libraries/shared/src/DoubleHashKey.cpp index fae1d715fb..794604d21b 100644 --- a/libraries/physics/src/DoubleHashKey.cpp +++ b/libraries/shared/src/DoubleHashKey.cpp @@ -1,6 +1,6 @@ // // DoubleHashKey.cpp -// libraries/physcis/src +// libraries/shared/src // // Created by Andrew Meadows 2014.11.02 // Copyright 2014 High Fidelity, Inc. @@ -11,8 +11,8 @@ #include "DoubleHashKey.h" -const int NUM_PRIMES = 64; -const unsigned int PRIMES[] = { +const uint32_t NUM_PRIMES = 64; +const uint32_t PRIMES[] = { 4194301U, 4194287U, 4194277U, 4194271U, 4194247U, 4194217U, 4194199U, 4194191U, 4194187U, 4194181U, 4194173U, 4194167U, 4194143U, 4194137U, 4194131U, 4194107U, 4194103U, 4194023U, 4194011U, 4194007U, 4193977U, 4193971U, 4193963U, 4193957U, @@ -23,8 +23,8 @@ const unsigned int PRIMES[] = { 4193353U, 4193327U, 4193309U, 4193303U, 4193297U, 4193279U, 4193269U, 4193263U }; -unsigned int DoubleHashKey::hashFunction(unsigned int value, int primeIndex) { - unsigned int hash = PRIMES[primeIndex % NUM_PRIMES] * (value + 1U); +uint32_t DoubleHashKey::hashFunction(uint32_t value, uint32_t primeIndex) { + uint32_t hash = PRIMES[primeIndex % NUM_PRIMES] * (value + 1U); hash += ~(hash << 15); hash ^= (hash >> 10); hash += (hash << 3); @@ -33,11 +33,16 @@ unsigned int DoubleHashKey::hashFunction(unsigned int value, int primeIndex) { return hash ^ (hash >> 16); } -unsigned int DoubleHashKey::hashFunction2(unsigned int value) { - unsigned hash = 0x811c9dc5U; - for (int i = 0; i < 4; i++ ) { - unsigned int byte = (value << (i * 8)) >> (24 - i * 8); +uint32_t DoubleHashKey::hashFunction2(uint32_t value) { + uint32_t hash = 0x811c9dc5U; + for (uint32_t i = 0; i < 4; i++ ) { + uint32_t byte = (value << (i * 8)) >> (24 - i * 8); hash = ( hash ^ byte ) * 0x01000193U; } return hash; } + +void DoubleHashKey::computeHash(uint32_t value, uint32_t primeIndex) { + _hash = DoubleHashKey::hashFunction(value, primeIndex); + _hash2 = DoubleHashKey::hashFunction2(value); +} diff --git a/libraries/physics/src/DoubleHashKey.h b/libraries/shared/src/DoubleHashKey.h similarity index 51% rename from libraries/physics/src/DoubleHashKey.h rename to libraries/shared/src/DoubleHashKey.h index ebacf6c96a..3b08bf7c1a 100644 --- a/libraries/physics/src/DoubleHashKey.h +++ b/libraries/shared/src/DoubleHashKey.h @@ -1,6 +1,6 @@ // // DoubleHashKey.h -// libraries/physcis/src +// libraries/shared/src // // Created by Andrew Meadows 2014.11.02 // Copyright 2014 High Fidelity, Inc. @@ -12,27 +12,38 @@ #ifndef hifi_DoubleHashKey_h #define hifi_DoubleHashKey_h +#include + // DoubleHashKey for use with btHashMap class DoubleHashKey { public: - static unsigned int hashFunction(unsigned int value, int primeIndex); - static unsigned int hashFunction2(unsigned int value); + static uint32_t hashFunction(uint32_t value, uint32_t primeIndex); + static uint32_t hashFunction2(uint32_t value); DoubleHashKey() : _hash(0), _hash2(0) { } - DoubleHashKey(unsigned int value, int primeIndex = 0) : + DoubleHashKey(uint32_t value, uint32_t primeIndex = 0) : _hash(hashFunction(value, primeIndex)), _hash2(hashFunction2(value)) { } + void clear() { _hash = 0; _hash2 = 0; } + bool isNull() const { return _hash == 0 && _hash2 == 0; } + bool equals(const DoubleHashKey& other) const { return _hash == other._hash && _hash2 == other._hash2; } - unsigned int getHash() const { return (unsigned int)_hash; } + void computeHash(uint32_t value, uint32_t primeIndex = 0); + uint32_t getHash() const { return _hash; } + uint32_t getHash2() const { return _hash2; } - int _hash; - int _hash2; + void setHash(uint32_t hash) { _hash = hash; } + void setHash2(uint32_t hash2) { _hash2 = hash2; } + +private: + uint32_t _hash; + uint32_t _hash2; }; #endif // hifi_DoubleHashKey_h diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index a1e72cdca0..8b2a3e3a73 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -13,78 +13,82 @@ #include "SharedUtil.h" // for MILLIMETERS_PER_METER -//#include "DoubleHashKey.h" #include "ShapeInfo.h" void ShapeInfo::clear() { - _type = INVALID_SHAPE; - _data.clear(); + _type = SHAPE_TYPE_NONE; + _halfExtents = glm::vec3(0.0f); + _doubleHashKey.clear(); + _externalData = NULL; +} + +void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QVector* data) { + _type = type; + switch(type) { + case SHAPE_TYPE_NONE: + _halfExtents = glm::vec3(0.0f); + break; + case SHAPE_TYPE_BOX: + _halfExtents = halfExtents; + break; + case SHAPE_TYPE_SPHERE: { + // sphere radius is max of halfExtents + float radius = glm::max(glm::max(halfExtents.x, halfExtents.y), halfExtents.z); + _halfExtents = glm::vec3(radius); + break; + } + default: + _halfExtents = halfExtents; + } + _externalData = data; } void ShapeInfo::setBox(const glm::vec3& halfExtents) { - _type = BOX_SHAPE; - _data.clear(); - // _data[0] = < halfX, halfY, halfZ > - _data.push_back(halfExtents); + _type = SHAPE_TYPE_BOX; + _halfExtents = halfExtents; + _doubleHashKey.clear(); } void ShapeInfo::setSphere(float radius) { - _type = SPHERE_SHAPE; - _data.clear(); - // _data[0] = < radius, radius, radius > - _data.push_back(glm::vec3(radius)); + _type = SHAPE_TYPE_SPHERE; + _halfExtents = glm::vec3(radius, radius, radius); + _doubleHashKey.clear(); } -void ShapeInfo::setCylinder(float radius, float halfHeight) { - _type = CYLINDER_SHAPE; - _data.clear(); - // _data[0] = < radius, halfHeight, radius > - // NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X - _data.push_back(glm::vec3(radius, halfHeight, radius)); +void ShapeInfo::setEllipsoid(const glm::vec3& halfExtents) { + _type = SHAPE_TYPE_ELLIPSOID; + _halfExtents = halfExtents; + _doubleHashKey.clear(); } -void ShapeInfo::setCapsule(float radius, float halfHeight) { - _type = CAPSULE_SHAPE; - _data.clear(); - // _data[0] = < radius, halfHeight, radius > - _data.push_back(glm::vec3(radius, halfHeight, radius)); -} - -glm::vec3 ShapeInfo::getBoundingBoxDiagonal() const { - switch(_type) { - case BOX_SHAPE: - case SPHERE_SHAPE: - case CYLINDER_SHAPE: - case CAPSULE_SHAPE: - return 2.0f * _data[0]; - default: - break; - } - return glm::vec3(0.0f); +void ShapeInfo::setCapsuleY(float radius, float halfHeight) { + _type = SHAPE_TYPE_CAPSULE_Y; + _halfExtents = glm::vec3(radius, halfHeight, radius); + _doubleHashKey.clear(); } float ShapeInfo::computeVolume() const { const float DEFAULT_VOLUME = 1.0f; float volume = DEFAULT_VOLUME; switch(_type) { - case BOX_SHAPE: { - // factor of 8.0 because the components of _data[0] are all halfExtents - volume = 8.0f * _data[0].x * _data[0].y * _data[0].z; + case SHAPE_TYPE_BOX: { + // factor of 8.0 because the components of _halfExtents are all halfExtents + volume = 8.0f * _halfExtents.x * _halfExtents.y * _halfExtents.z; break; } - case SPHERE_SHAPE: { - float radius = _data[0].x; + case SHAPE_TYPE_SPHERE: { + float radius = _halfExtents.x; volume = 4.0f * PI * radius * radius * radius / 3.0f; break; } - case CYLINDER_SHAPE: { - float radius = _data[0].x; - volume = PI * radius * radius * 2.0f * _data[0].y; + case SHAPE_TYPE_CYLINDER_Y: { + float radius = _halfExtents.x; + volume = PI * radius * radius * 2.0f * _halfExtents.y; break; } - case CAPSULE_SHAPE: { - float radius = _data[0].x; - volume = PI * radius * radius * (2.0f * _data[0].y + 4.0f * radius / 3.0f); + case SHAPE_TYPE_CAPSULE_Y: { + float radius = _halfExtents.x; + volume = PI * radius * radius * (2.0f * _halfExtents.y + 4.0f * radius / 3.0f); break; } default: @@ -93,3 +97,85 @@ float ShapeInfo::computeVolume() const { assert(volume > 0.0f); return volume; } + +const DoubleHashKey& ShapeInfo::getHash() const { + // NOTE: we cache the hash so we only ever need to compute it once for any valid ShapeInfo instance. + if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) { + // cast this to non-const pointer so we can do our dirty work + ShapeInfo* thisPtr = const_cast(this); + // compute hash1 + // TODO?: provide lookup table for hash/hash2 of _type rather than recompute? + uint32_t primeIndex = 0; + thisPtr->_doubleHashKey.computeHash((uint32_t)_type, primeIndex++); + + const QVector* data = getData(); + if (data) { + // if externalData exists we use it to continue the hash + + // compute hash + uint32_t hash = _doubleHashKey.getHash(); + + glm::vec3 tmpData; + int numData = data->size(); + for (int i = 0; i < numData; ++i) { + tmpData = (*data)[i]; + for (int j = 0; j < 3; ++j) { + // NOTE: 0.49f is used to bump the float up almost half a millimeter + // so the cast to int produces a round() effect rather than a floor() + uint32_t floatHash = + DoubleHashKey::hashFunction((uint32_t)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f), primeIndex++); + hash ^= floatHash; + } + } + thisPtr->_doubleHashKey.setHash(hash); + + // compute hash2 + hash = _doubleHashKey.getHash2(); + for (int i = 0; i < numData; ++i) { + tmpData = (*data)[i]; + for (int j = 0; j < 3; ++j) { + // NOTE: 0.49f is used to bump the float up almost half a millimeter + // so the cast to int produces a round() effect rather than a floor() + uint32_t floatHash = + DoubleHashKey::hashFunction2((uint32_t)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f)); + hash += ~(floatHash << 17); + hash ^= (floatHash >> 11); + hash += (floatHash << 4); + hash ^= (floatHash >> 7); + hash += ~(floatHash << 10); + hash = (hash << 16) | (hash >> 16); + } + } + thisPtr->_doubleHashKey.setHash2(hash); + } else { + // this shape info has no external data so type+extents should be enough to generate a unique hash + // compute hash1 + uint32_t hash = _doubleHashKey.getHash(); + for (int j = 0; j < 3; ++j) { + // NOTE: 0.49f is used to bump the float up almost half a millimeter + // so the cast to int produces a round() effect rather than a floor() + uint32_t floatHash = + DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++); + hash ^= floatHash; + } + thisPtr->_doubleHashKey.setHash(hash); + + // compute hash2 + hash = _doubleHashKey.getHash2(); + for (int j = 0; j < 3; ++j) { + // NOTE: 0.49f is used to bump the float up almost half a millimeter + // so the cast to int produces a round() effect rather than a floor() + uint32_t floatHash = + DoubleHashKey::hashFunction2((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f)); + hash += ~(floatHash << 17); + hash ^= (floatHash >> 11); + hash += (floatHash << 4); + hash ^= (floatHash >> 7); + hash += ~(floatHash << 10); + hash = (hash << 16) | (hash >> 16); + } + thisPtr->_doubleHashKey.setHash2(hash); + } + } + return _doubleHashKey; +} diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index 9b4c587c3f..b6dc88e4b7 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -15,28 +15,51 @@ #include #include -#include "Shape.h" +#include "DoubleHashKey.h" + +enum ShapeType { + SHAPE_TYPE_NONE, + SHAPE_TYPE_BOX, + SHAPE_TYPE_SPHERE, + SHAPE_TYPE_ELLIPSOID, + SHAPE_TYPE_HULL, + SHAPE_TYPE_PLANE, + SHAPE_TYPE_COMPOUND, + SHAPE_TYPE_CAPSULE_X, + SHAPE_TYPE_CAPSULE_Y, + SHAPE_TYPE_CAPSULE_Z, + SHAPE_TYPE_CYLINDER_X, + SHAPE_TYPE_CYLINDER_Y, + SHAPE_TYPE_CYLINDER_Z +}; class ShapeInfo { public: - ShapeInfo() : _type(INVALID_SHAPE) {} - void clear(); + void setParams(ShapeType type, const glm::vec3& halfExtents, QVector* data = NULL); void setBox(const glm::vec3& halfExtents); void setSphere(float radius); - void setCylinder(float radius, float halfHeight); - void setCapsule(float radius, float halfHeight); + void setEllipsoid(const glm::vec3& halfExtents); + //void setHull(); // TODO: implement this + void setCapsuleY(float radius, float halfHeight); const int getType() const { return _type; } - const QVector& getData() const { return _data; } - glm::vec3 getBoundingBoxDiagonal() const; + const glm::vec3& getHalfExtents() const { return _halfExtents; } + + void setData(const QVector* data) { _externalData = data; } + const QVector* getData() const { return _externalData; } + float computeVolume() const; + const DoubleHashKey& getHash() const; + protected: - int _type; - QVector _data; + ShapeType _type = SHAPE_TYPE_NONE; + glm::vec3 _halfExtents = glm::vec3(0.0f); + DoubleHashKey _doubleHashKey; + const QVector* _externalData = NULL; }; #endif // hifi_ShapeInfo_h diff --git a/tests/physics/src/ShapeInfoTests.cpp b/tests/physics/src/ShapeInfoTests.cpp index cbef53f2eb..bf2a98eb10 100644 --- a/tests/physics/src/ShapeInfoTests.cpp +++ b/tests/physics/src/ShapeInfoTests.cpp @@ -24,10 +24,10 @@ void ShapeInfoTests::testHashFunctions() { int maxTests = 10000000; ShapeInfo info; - btHashMap hashes; + btHashMap hashes; - int bits[32]; - unsigned int masks[32]; + uint32_t bits[32]; + uint32_t masks[32]; for (int i = 0; i < 32; ++i) { bits[i] = 0; masks[i] = 1U << i; @@ -45,26 +45,27 @@ void ShapeInfoTests::testHashFunctions() { // test sphere info.setSphere(radiusX); ++testCount; - DoubleHashKey key = ShapeInfoUtil::computeHash(info); - int* hashPtr = hashes.find(key._hash); - if (hashPtr && *hashPtr == key._hash2) { + DoubleHashKey key = info.getHash(); + uint32_t* hashPtr = hashes.find(key.getHash()); + if (hashPtr && *hashPtr == key.getHash2()) { std::cout << testCount << " hash collision radiusX = " << radiusX - << " h1 = 0x" << std::hex << (unsigned int)(key._hash) - << " h2 = 0x" << std::hex << (unsigned int)(key._hash2) + << " h1 = 0x" << std::hex << key.getHash() + << " h2 = 0x" << std::hex << key.getHash2() << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key._hash, key._hash2); + hashes.insert(key.getHash(), key.getHash2()); } for (int k = 0; k < 32; ++k) { - if (masks[k] & key._hash2) { + if (masks[k] & key.getHash2()) { ++bits[k]; } } for (int y = 1; y < numSteps && testCount < maxTests; ++y) { float radiusY = (float)y * deltaLength; + /* TODO: reimplement Cylinder and Capsule shapes // test cylinder and capsule int types[] = { CYLINDER_SHAPE_PROXYTYPE, CAPSULE_SHAPE_PROXYTYPE }; for (int i = 0; i < 2; ++i) { @@ -74,58 +75,59 @@ void ShapeInfoTests::testHashFunctions() { break; } case CAPSULE_SHAPE_PROXYTYPE: { - info.setCapsule(radiusX, radiusY); + info.setCapsuleY(radiusX, radiusY); break; } } ++testCount; - key = ShapeInfoUtil::computeHash(info); - hashPtr = hashes.find(key._hash); - if (hashPtr && *hashPtr == key._hash2) { + key = info.getHash(); + hashPtr = hashes.find(key.getHash()); + if (hashPtr && *hashPtr == key.getHash2()) { std::cout << testCount << " hash collision radiusX = " << radiusX << " radiusY = " << radiusY - << " h1 = 0x" << std::hex << (unsigned int)(key._hash) - << " h2 = 0x" << std::hex << (unsigned int)(key._hash2) + << " h1 = 0x" << std::hex << key.getHash() + << " h2 = 0x" << std::hex << key.getHash2() << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key._hash, key._hash2); + hashes.insert(key.getHash(), key.getHash2()); } for (int k = 0; k < 32; ++k) { - if (masks[k] & key._hash2) { + if (masks[k] & key.getHash2()) { ++bits[k]; } } } + */ for (int z = 1; z < numSteps && testCount < maxTests; ++z) { float radiusZ = (float)z * deltaLength; // test box info.setBox(glm::vec3(radiusX, radiusY, radiusZ)); ++testCount; - DoubleHashKey key = ShapeInfoUtil::computeHash(info); - hashPtr = hashes.find(key._hash); - if (hashPtr && *hashPtr == key._hash2) { + DoubleHashKey key = info.getHash(); + hashPtr = hashes.find(key.getHash()); + if (hashPtr && *hashPtr == key.getHash2()) { std::cout << testCount << " hash collision radiusX = " << radiusX << " radiusY = " << radiusY << " radiusZ = " << radiusZ - << " h1 = 0x" << std::hex << (unsigned int)(key._hash) - << " h2 = 0x" << std::hex << (unsigned int)(key._hash2) + << " h1 = 0x" << std::hex << key.getHash() + << " h2 = 0x" << std::hex << key.getHash2() << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key._hash, key._hash2); + hashes.insert(key.getHash(), key.getHash2()); } for (int k = 0; k < 32; ++k) { - if (masks[k] & key._hash2) { + if (masks[k] & key.getHash2()) { ++bits[k]; } } } } } - unsigned long int msec = timer.getTimeMilliseconds(); + uint64_t msec = timer.getTimeMilliseconds(); std::cout << msec << " msec with " << numCollisions << " collisions out of " << testCount << " hashes" << std::endl; // print out distribution of bits @@ -138,7 +140,7 @@ void ShapeInfoTests::testBoxShape() { ShapeInfo info; glm::vec3 halfExtents(1.23f, 4.56f, 7.89f); info.setBox(halfExtents); - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); if (!shape) { @@ -148,15 +150,15 @@ void ShapeInfoTests::testBoxShape() { ShapeInfo otherInfo; ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - DoubleHashKey otherKey = ShapeInfoUtil::computeHash(otherInfo); - if (key._hash != otherKey._hash) { + DoubleHashKey otherKey = otherInfo.getHash(); + if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Box shape hash = " << key._hash << " but found hash = " << otherKey._hash << std::endl; + << " ERROR: expected Box shape hash = " << key.getHash() << " but found hash = " << otherKey.getHash() << std::endl; } - if (key._hash2 != otherKey._hash2) { + if (key.getHash2() != otherKey.getHash2()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Box shape hash2 = " << key._hash2 << " but found hash2 = " << otherKey._hash2 << std::endl; + << " ERROR: expected Box shape hash2 = " << key.getHash2() << " but found hash2 = " << otherKey.getHash2() << std::endl; } delete shape; @@ -166,74 +168,78 @@ void ShapeInfoTests::testSphereShape() { ShapeInfo info; float radius = 1.23f; info.setSphere(radius); - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); ShapeInfo otherInfo; ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - DoubleHashKey otherKey = ShapeInfoUtil::computeHash(otherInfo); - if (key._hash != otherKey._hash) { + DoubleHashKey otherKey = otherInfo.getHash(); + if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Sphere shape hash = " << key._hash << " but found hash = " << otherKey._hash << std::endl; + << " ERROR: expected Sphere shape hash = " << key.getHash() << " but found hash = " << otherKey.getHash() << std::endl; } - if (key._hash2 != otherKey._hash2) { + if (key.getHash2() != otherKey.getHash2()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Sphere shape hash2 = " << key._hash2 << " but found hash2 = " << otherKey._hash2 << std::endl; + << " ERROR: expected Sphere shape hash2 = " << key.getHash2() << " but found hash2 = " << otherKey.getHash2() << std::endl; } delete shape; } void ShapeInfoTests::testCylinderShape() { + /* TODO: reimplement Cylinder shape ShapeInfo info; float radius = 1.23f; float height = 4.56f; info.setCylinder(radius, height); - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); ShapeInfo otherInfo; ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - DoubleHashKey otherKey = ShapeInfoUtil::computeHash(otherInfo); - if (key._hash != otherKey._hash) { + DoubleHashKey otherKey = otherInfo.getHash(); + if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Cylinder shape hash = " << key._hash << " but found hash = " << otherKey._hash << std::endl; + << " ERROR: expected Cylinder shape hash = " << key.getHash() << " but found hash = " << otherKey.getHash() << std::endl; } - if (key._hash2 != otherKey._hash2) { + if (key.getHash2() != otherKey.getHash2()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Cylinder shape hash2 = " << key._hash2 << " but found hash2 = " << otherKey._hash2 << std::endl; + << " ERROR: expected Cylinder shape hash2 = " << key.getHash2() << " but found hash2 = " << otherKey.getHash2() << std::endl; } delete shape; + */ } void ShapeInfoTests::testCapsuleShape() { + /* TODO: reimplement Capsule shape ShapeInfo info; float radius = 1.23f; float height = 4.56f; info.setCapsule(radius, height); - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); ShapeInfo otherInfo; ShapeInfoUtil::collectInfoFromShape(shape, otherInfo); - DoubleHashKey otherKey = ShapeInfoUtil::computeHash(otherInfo); - if (key._hash != otherKey._hash) { + DoubleHashKey otherKey = otherInfo.getHash(); + if (key.getHash() != otherKey.getHash()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Capsule shape hash = " << key._hash << " but found hash = " << otherKey._hash << std::endl; + << " ERROR: expected Capsule shape hash = " << key.getHash() << " but found hash = " << otherKey.getHash() << std::endl; } - if (key._hash2 != otherKey._hash2) { + if (key.getHash2() != otherKey.getHash2()) { std::cout << __FILE__ << ":" << __LINE__ - << " ERROR: expected Capsule shape hash2 = " << key._hash2 << " but found hash2 = " << otherKey._hash2 << std::endl; + << " ERROR: expected Capsule shape hash2 = " << key.getHash2() << " but found hash2 = " << otherKey.getHash2() << std::endl; } delete shape; + */ } void ShapeInfoTests::runAllTests() { diff --git a/tests/physics/src/ShapeManagerTests.cpp b/tests/physics/src/ShapeManagerTests.cpp index e49b9b8063..6dfae15e78 100644 --- a/tests/physics/src/ShapeManagerTests.cpp +++ b/tests/physics/src/ShapeManagerTests.cpp @@ -188,6 +188,7 @@ void ShapeManagerTests::addSphereShape() { } void ShapeManagerTests::addCylinderShape() { + /* TODO: reimplement Cylinder shape ShapeInfo info; float radius = 1.23f; float height = 4.56f; @@ -204,9 +205,11 @@ void ShapeManagerTests::addCylinderShape() { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: Cylinder ShapeInfo --> shape --> ShapeInfo --> shape did not work" << std::endl; } + */ } void ShapeManagerTests::addCapsuleShape() { + /* TODO: reimplement Capsule shape ShapeInfo info; float radius = 1.23f; float height = 4.56f; @@ -223,6 +226,7 @@ void ShapeManagerTests::addCapsuleShape() { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: Capsule ShapeInfo --> shape --> ShapeInfo --> shape did not work" << std::endl; } + */ } void ShapeManagerTests::runAllTests() {