break PhysicsEngine::addEntityInternal in half, making the 2nd part asynch. This is to allow a ModelEntityItem time to download its collision hull before the 2nd part runs

This commit is contained in:
Seth Alves 2015-03-12 15:58:09 -07:00
parent 3c61727a22
commit 2cf0e1ab25
8 changed files with 80 additions and 28 deletions

View file

@ -1002,8 +1002,13 @@ float EntityItem::getRadius() const {
return 0.5f * glm::length(_dimensions); return 0.5f * glm::length(_dimensions);
} }
void EntityItem::computeShapeInfo(ShapeInfo& info) const { void EntityItem::getReadyToComputeShape() {
emit entityShapeReady(getID());
}
void EntityItem::computeShapeInfo(ShapeInfo& info) {
info.setParams(getShapeType(), 0.5f * getDimensions()); info.setParams(getShapeType(), 0.5f * getDimensions());
} }
const float MIN_POSITION_DELTA = 0.0001f; const float MIN_POSITION_DELTA = 0.0001f;

View file

@ -43,7 +43,9 @@ class EntityTreeElementExtraEncodeData;
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate /// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
/// one directly, instead you must only construct one of it's derived classes with additional features. /// one directly, instead you must only construct one of it's derived classes with additional features.
class EntityItem { class EntityItem : public QObject {
Q_OBJECT
friend class EntityTreeElement; friend class EntityTreeElement;
public: public:
enum EntityDirtyFlags { enum EntityDirtyFlags {
@ -256,7 +258,7 @@ public:
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); } virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
virtual bool containsInDomainUnits(const glm::vec3& point) const { return getAABoxInDomainUnits().contains(point); } virtual bool containsInDomainUnits(const glm::vec3& point) const { return getAABoxInDomainUnits().contains(point); }
virtual void computeShapeInfo(ShapeInfo& info) const; virtual void computeShapeInfo(ShapeInfo& info);
/// return preferred shape type (actual physical shape may differ) /// return preferred shape type (actual physical shape may differ)
virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; } virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; }
@ -295,6 +297,10 @@ public:
static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; } static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; }
static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; } static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; }
virtual void getReadyToComputeShape();
signals:
void entityShapeReady(QUuid entityId) const;
protected: protected:

View file

@ -66,6 +66,9 @@ public:
signals: signals:
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
public slots:
// virtual void entityShapeComputed(QUuid entityId) { }
protected: protected:
// These pure virtual methods are protected because they are not to be called will-nilly. The base class // These pure virtual methods are protected because they are not to be called will-nilly. The base class

View file

@ -32,7 +32,7 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI
_type = EntityTypes::Light; _type = EntityTypes::Light;
// default property values // default property values
const quint8 MAX_COLOR = 255; // const quint8 MAX_COLOR = 255;
_color[RED_INDEX] = _color[GREEN_INDEX] = _color[BLUE_INDEX] = 0; _color[RED_INDEX] = _color[GREEN_INDEX] = _color[BLUE_INDEX] = 0;
_intensity = 1.0f; _intensity = 1.0f;
_exponent = 0.0f; _exponent = 0.0f;
@ -112,6 +112,8 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent); READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent);
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff); READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff);
(void) ignoredAttenuation; // suppress compiler warning
} else { } else {
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight); READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight);
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color); READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);

View file

@ -413,17 +413,26 @@ QString ModelEntityItem::getAnimationSettings() const {
return jsonByteString; return jsonByteString;
} }
void ModelEntityItem::computeShapeInfo(ShapeInfo& info) const {
if (_collisionModelURL != "") { void ModelEntityItem::getReadyToComputeShape() {
QSharedPointer<NetworkGeometry> networkGeometry = qDebug() << "ModelEntityItem::getReadyToComputeShape for " << getID().toString();
DependencyManager::get<GeometryCache>()->getGeometry (_collisionModelURL, QUrl(), false);
if (_collisionModelURL != "" && _collisionNetworkGeometry.isNull()) {
qDebug() << " yes";
// QSharedPointer<NetworkGeometry> networkGeometry =
_collisionNetworkGeometry = DependencyManager::get<GeometryCache>()->getGeometry (_collisionModelURL, QUrl(), false);
// XXX does this do an unneeded copy? // XXX does this do an unneeded copy?
FBXGeometry _collisionModel = networkGeometry->getFBXGeometry(); // FBXGeometry _collisionModel = networkGeometry->getFBXGeometry();
FBXGeometry _collisionModel = _collisionNetworkGeometry->getFBXGeometry();
// connect(networkGeometry, loaded, this, collisionGeometryLoaded); // connect(networkGeometry, loaded, this, collisionGeometryLoaded);
info.setParams(getShapeType(), 0.5f * getDimensions(), NULL, _collisionModelURL); emit entityShapeReady(getID());
} }
} }
void ModelEntityItem::computeShapeInfo(ShapeInfo& info) {
qDebug() << "ModelEntityItem::computeShapeInfo for " << getID().toString();
info.setParams(getShapeType(), 0.5f * getDimensions(), NULL, _collisionModelURL);
}

View file

@ -51,7 +51,7 @@ public:
virtual bool needsToCallUpdate() const; virtual bool needsToCallUpdate() const;
virtual void debugDump() const; virtual void debugDump() const;
virtual void computeShapeInfo(ShapeInfo& info) const; virtual void computeShapeInfo(ShapeInfo& info);
void updateShapeType(ShapeType type); void updateShapeType(ShapeType type);
virtual ShapeType getShapeType() const { virtual ShapeType getShapeType() const {
@ -132,6 +132,8 @@ public:
void setTextures(const QString& textures) { _textures = textures; } void setTextures(const QString& textures) { _textures = textures; }
static void cleanupLoadedAnimations(); static void cleanupLoadedAnimations();
void getReadyToComputeShape();
protected: protected:

View file

@ -59,25 +59,43 @@ void PhysicsEngine::updateEntitiesInternal(const quint64& now) {
void PhysicsEngine::addEntityInternal(EntityItem* entity) { void PhysicsEngine::addEntityInternal(EntityItem* entity) {
assert(entity); assert(entity);
void* physicsInfo = entity->getPhysicsInfo(); void* physicsInfo = entity->getPhysicsInfo();
if (!physicsInfo) { if (!physicsInfo && !_busyComputingShape.contains(entity->getID())) {
ShapeInfo shapeInfo; ShapeInfo shapeInfo;
entity->computeShapeInfo(shapeInfo);
btCollisionShape* shape = _shapeManager.getShape(shapeInfo);
if (shape) {
EntityMotionState* motionState = new EntityMotionState(entity);
entity->setPhysicsInfo(static_cast<void*>(motionState));
_entityMotionStates.insert(motionState);
addObject(shapeInfo, shape, motionState);
} else if (entity->isMoving()) {
EntityMotionState* motionState = new EntityMotionState(entity);
entity->setPhysicsInfo(static_cast<void*>(motionState));
_entityMotionStates.insert(motionState);
motionState->setKinematic(true, _numSubsteps); qDebug() << "in addEntityInternal ID is" << entity->getID().toString();
_nonPhysicalKinematicObjects.insert(motionState);
// We failed to add the entity to the simulation. Probably because we couldn't create a shape for it. QPointer<EntityItem> entityWptr(entity);
//qDebug() << "failed to add entity " << entity->getEntityItemID() << " to physics engine"; _busyComputingShape[entity->getID()] = entityWptr;
} connect(entity, SIGNAL(entityShapeReady(QUuid)), this, SLOT(entityShapeReady(QUuid)));
entity->getReadyToComputeShape();
}
}
void PhysicsEngine::entityShapeReady(QUuid entityId) {
qDebug() << "PhysicsEngine::entityShapeReady for" << entityId.toString();
QPointer<EntityItem> entityPtr = _busyComputingShape[entityId];
_busyComputingShape.remove(entityId);
EntityItem &entity = *entityPtr;
ShapeInfo shapeInfo;
entity.computeShapeInfo(shapeInfo);
btCollisionShape* shape = _shapeManager.getShape(shapeInfo);
EntityMotionState* motionState = new EntityMotionState(&entity);
entity.setPhysicsInfo(static_cast<void*>(motionState));
_entityMotionStates.insert(motionState);
if (shape) {
addObject(shapeInfo, shape, motionState);
} else if (entity.isMoving()) {
motionState->setKinematic(true, _numSubsteps);
_nonPhysicalKinematicObjects.insert(motionState);
// We failed to add the entity to the simulation. Probably because we couldn't create a shape for it.
//qDebug() << "failed to add entity " << entity.getEntityItemID() << " to physics engine";
} }
} }

View file

@ -51,6 +51,8 @@ typedef std::map<ContactKey, ContactInfo> ContactMap;
typedef std::pair<ContactKey, ContactInfo> ContactMapElement; typedef std::pair<ContactKey, ContactInfo> ContactMapElement;
class PhysicsEngine : public EntitySimulation { class PhysicsEngine : public EntitySimulation {
Q_OBJECT
public: public:
// TODO: find a good way to make this a non-static method // TODO: find a good way to make this a non-static method
static uint32_t getNumSubsteps(); static uint32_t getNumSubsteps();
@ -90,6 +92,9 @@ public:
void setAvatarData(AvatarData *avatarData); void setAvatarData(AvatarData *avatarData);
public slots:
void entityShapeReady(QUuid entityId);
private: private:
/// \param motionState pointer to Object's MotionState /// \param motionState pointer to Object's MotionState
void removeObjectFromBullet(ObjectMotionState* motionState); void removeObjectFromBullet(ObjectMotionState* motionState);
@ -126,6 +131,8 @@ private:
btCharacterControllerInterface* _characterController = 0; btCharacterControllerInterface* _characterController = 0;
class btPairCachingGhostObject* _avatarGhostObject = 0; class btPairCachingGhostObject* _avatarGhostObject = 0;
AvatarData *_avatarData = 0; AvatarData *_avatarData = 0;
QMap<QUuid, QPointer<EntityItem>> _busyComputingShape;
}; };
#endif // hifi_PhysicsEngine_h #endif // hifi_PhysicsEngine_h