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);
}
void EntityItem::computeShapeInfo(ShapeInfo& info) const {
void EntityItem::getReadyToComputeShape() {
emit entityShapeReady(getID());
}
void EntityItem::computeShapeInfo(ShapeInfo& info) {
info.setParams(getShapeType(), 0.5f * getDimensions());
}
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
/// 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.
class EntityItem {
class EntityItem : public QObject {
Q_OBJECT
friend class EntityTreeElement;
public:
enum EntityDirtyFlags {
@ -256,7 +258,7 @@ public:
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
virtual bool containsInDomainUnits(const glm::vec3& point) const { return getAABoxInDomainUnits().contains(point); }
virtual void computeShapeInfo(ShapeInfo& info) const;
virtual void computeShapeInfo(ShapeInfo& info);
/// return preferred shape type (actual physical shape may differ)
virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; }
@ -295,6 +297,10 @@ public:
static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; }
static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; }
virtual void getReadyToComputeShape();
signals:
void entityShapeReady(QUuid entityId) const;
protected:

View file

@ -66,6 +66,9 @@ public:
signals:
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
public slots:
// virtual void entityShapeComputed(QUuid entityId) { }
protected:
// 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;
// default property values
const quint8 MAX_COLOR = 255;
// const quint8 MAX_COLOR = 255;
_color[RED_INDEX] = _color[GREEN_INDEX] = _color[BLUE_INDEX] = 0;
_intensity = 1.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_CUTOFF, float, _cutoff);
(void) ignoredAttenuation; // suppress compiler warning
} else {
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight);
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);

View file

@ -413,17 +413,26 @@ QString ModelEntityItem::getAnimationSettings() const {
return jsonByteString;
}
void ModelEntityItem::computeShapeInfo(ShapeInfo& info) const {
if (_collisionModelURL != "") {
QSharedPointer<NetworkGeometry> networkGeometry =
DependencyManager::get<GeometryCache>()->getGeometry (_collisionModelURL, QUrl(), false);
void ModelEntityItem::getReadyToComputeShape() {
qDebug() << "ModelEntityItem::getReadyToComputeShape for " << getID().toString();
if (_collisionModelURL != "" && _collisionNetworkGeometry.isNull()) {
qDebug() << " yes";
// QSharedPointer<NetworkGeometry> networkGeometry =
_collisionNetworkGeometry = DependencyManager::get<GeometryCache>()->getGeometry (_collisionModelURL, QUrl(), false);
// XXX does this do an unneeded copy?
FBXGeometry _collisionModel = networkGeometry->getFBXGeometry();
// FBXGeometry _collisionModel = networkGeometry->getFBXGeometry();
FBXGeometry _collisionModel = _collisionNetworkGeometry->getFBXGeometry();
// 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 void debugDump() const;
virtual void computeShapeInfo(ShapeInfo& info) const;
virtual void computeShapeInfo(ShapeInfo& info);
void updateShapeType(ShapeType type);
virtual ShapeType getShapeType() const {
@ -132,6 +132,8 @@ public:
void setTextures(const QString& textures) { _textures = textures; }
static void cleanupLoadedAnimations();
void getReadyToComputeShape();
protected:

View file

@ -59,25 +59,43 @@ void PhysicsEngine::updateEntitiesInternal(const quint64& now) {
void PhysicsEngine::addEntityInternal(EntityItem* entity) {
assert(entity);
void* physicsInfo = entity->getPhysicsInfo();
if (!physicsInfo) {
if (!physicsInfo && !_busyComputingShape.contains(entity->getID())) {
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);
_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";
}
qDebug() << "in addEntityInternal ID is" << entity->getID().toString();
QPointer<EntityItem> entityWptr(entity);
_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;
class PhysicsEngine : public EntitySimulation {
Q_OBJECT
public:
// TODO: find a good way to make this a non-static method
static uint32_t getNumSubsteps();
@ -90,6 +92,9 @@ public:
void setAvatarData(AvatarData *avatarData);
public slots:
void entityShapeReady(QUuid entityId);
private:
/// \param motionState pointer to Object's MotionState
void removeObjectFromBullet(ObjectMotionState* motionState);
@ -126,6 +131,8 @@ private:
btCharacterControllerInterface* _characterController = 0;
class btPairCachingGhostObject* _avatarGhostObject = 0;
AvatarData *_avatarData = 0;
QMap<QUuid, QPointer<EntityItem>> _busyComputingShape;
};
#endif // hifi_PhysicsEngine_h