attempting to figure out why physics motion object doesn't get updated when collision model url changes

This commit is contained in:
Seth Alves 2015-03-24 15:28:21 -07:00
parent bb8c83d49a
commit 6e3be26013
16 changed files with 172 additions and 40 deletions

View file

@ -22,6 +22,7 @@
#include "EntityTreeRenderer.h"
#include "RenderableModelEntityItem.h"
EntityItem* RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableModelEntityItem(entityID, properties);
}
@ -266,6 +267,50 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking);
}
// void RenderableModelEntityItem::setCollisionModelURL(const QString& url) {
// // XXX PhysicsEngine::entityChangedInternal(this);
// // EntityTree* x = this->getElement()->_myTree;
// // EntityTreeRenderer* _myRenderer;
// qDebug() << "--------------------------------";
// this->ModelEntityItem::setCollisionModelURL(url);
// if ((_dirtyFlags & (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS)) ==
// (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS)) {
// EntityTreeElement* element = this->getElement();
// if (element) {
// qDebug() << "element =" << element;
// EntityTree* tree = element->getTree();
// qDebug() << "tree =" << tree;
// tree->reconfigureEntity(this);
// }
// }
// }
void RenderableModelEntityItem::setCollisionModelURL(const QString& url) {
ModelEntityItem::setCollisionModelURL(url);
_model->setCollisionModelURL(QUrl(url));
}
bool RenderableModelEntityItem::hasCollisionModel() const {
// return !_collisionModelURL.isEmpty();
return ! _model->getCollisionURL().isEmpty();
}
const QString& RenderableModelEntityItem::getCollisionModelURL() const {
// return _collisionModelURL;
_collisionModelURL = _model->getCollisionURL().toString();
return _collisionModelURL;
}
void RenderableModelEntityItem::updateDimensions(const glm::vec3& value) {
if (glm::distance(_dimensions, value) > MIN_DIMENSIONS_DELTA) {
_dimensions = value;
@ -288,6 +333,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
if (! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoadedWithTextures()) {
// we have a _collisionModelURL AND a collisionNetworkGeometry AND it's fully loaded.
// _dirtyFlags |= (EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS);
return true;
}
@ -296,9 +342,12 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
}
void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
qDebug() << "RenderableModelEntityItem::computeShapeInfo";
if (_model->getCollisionURL().isEmpty()) {
qDebug() << " _model->getCollisionURL().isEmpty()";
info.setParams(getShapeType(), 0.5f * getDimensions());
} else {
qDebug() << " _model->getCollisionURL() wasn't empty.";
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry();

View file

@ -49,9 +49,15 @@ public:
void** intersectedObject, bool precisionPicking) const;
Model* getModel(EntityTreeRenderer* renderer);
// virtual void setCollisionModelURL(const QString& url);
bool needsToCallUpdate() const;
virtual void setCollisionModelURL(const QString& url);
virtual bool hasCollisionModel() const;
virtual const QString& getCollisionModelURL() const;
virtual void updateDimensions(const glm::vec3& value);
bool isReadyToComputeShape();

View file

@ -126,11 +126,11 @@ void EntitySimulation::addEntity(EntityItem* entity) {
if (entity->needsToCallUpdate()) {
_updateableEntities.insert(entity);
}
addEntityInternal(entity);
// DirtyFlags are used to signal changes to entities that have already been added,
// so we can clear them for this entity which has just been added.
entity->clearDirtyFlags();
if (addEntityInternal(entity)) {
// DirtyFlags are used to signal changes to entities that have already been added,
// so we can clear them for this entity which has just been added.
entity->clearDirtyFlags();
}
}
void EntitySimulation::removeEntity(EntityItem* entity) {

View file

@ -63,6 +63,10 @@ public:
EntityTree* getEntityTree() { return _entityTree; }
/* virtual void reconfigureEntity(EntityItem* entity) { */
/* qDebug() << "EntitySimulation::reconfigureEntity"; */
/* } */
signals:
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
@ -74,7 +78,7 @@ protected:
// NOTE: updateEntitiesInternal() should clear all dirty flags on each changed entity as side effect
virtual void updateEntitiesInternal(const quint64& now) = 0;
virtual void addEntityInternal(EntityItem* entity) = 0;
virtual bool addEntityInternal(EntityItem* entity) = 0;
virtual void removeEntityInternal(EntityItem* entity) = 0;

View file

@ -315,6 +315,12 @@ void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool i
}
}
void EntityTree::reconfigureEntity(EntityItem* entity) {
qDebug() << "EntityTree::reconfigureEntity";
// _simulation->reconfigureEntity(entity);
_simulation->entityChanged(entity);
}
void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) {
const RemovedEntities& entities = theOperator.getEntities();
if (_simulation) {

View file

@ -95,7 +95,8 @@ public:
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = false);
void deleteEntities(QSet<EntityItemID> entityIDs, bool force = false, bool ignoreWarnings = false);
void removeEntityFromSimulation(EntityItem* entity);
// void removeEntityFromSimulation(EntityItem* entity);
void reconfigureEntity(EntityItem* entity);
/// \param position point of query in world-frame (meters)
/// \param targetRadius radius of query (meters)
@ -161,6 +162,7 @@ public:
void emitEntityScriptChanging(const EntityItemID& entityItemID);
void setSimulation(EntitySimulation* simulation);
EntitySimulation* getSimulation() { return _simulation; }
bool wantEditLogging() const { return _wantEditLogging; }
void setWantEditLogging(bool value) { _wantEditLogging = value; }

View file

@ -147,6 +147,7 @@ public:
bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; }
void setTree(EntityTree* tree) { _myTree = tree; }
EntityTree* getTree() { return _myTree; }
bool updateEntity(const EntityItem& entity);
void addEntityItem(EntityItem* entity);

View file

@ -74,7 +74,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType);
if (somethingChanged) {
bool wantDebug = false;
bool wantDebug = true;
if (wantDebug) {
uint64_t now = usecTimestampNow();
int elapsed = now - getLastEdited();
@ -281,6 +281,18 @@ void ModelEntityItem::updateShapeType(ShapeType type) {
}
}
void ModelEntityItem::setCollisionModelURL(const QString& url)
{
if (_collisionModelURL != url) {
qDebug() << "\n\n----";
qDebug() << "ModelEntityItem::setCollisionModelURL";
_collisionModelURL = url;
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
}
}
void ModelEntityItem::setAnimationURL(const QString& url) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationURL = url;

View file

@ -57,13 +57,13 @@ public:
const rgbColor& getColor() const { return _color; }
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
bool hasModel() const { return !_modelURL.isEmpty(); }
bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); }
virtual bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); }
static const QString DEFAULT_MODEL_URL;
const QString& getModelURL() const { return _modelURL; }
static const QString DEFAULT_COLLISION_MODEL_URL;
const QString& getCollisionModelURL() const { return _collisionModelURL; }
virtual const QString& getCollisionModelURL() const { return _collisionModelURL; }
bool hasAnimation() const { return !_animationURL.isEmpty(); }
static const QString DEFAULT_ANIMATION_URL;
@ -78,7 +78,7 @@ public:
// model related properties
void setModelURL(const QString& url) { _modelURL = url; }
void setCollisionModelURL(const QString& url) { _collisionModelURL = url; }
virtual void setCollisionModelURL(const QString& url);
void setAnimationURL(const QString& url);
static const float DEFAULT_ANIMATION_FRAME_INDEX;
void setAnimationFrameIndex(float value);

View file

@ -29,12 +29,13 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) {
}
}
void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) {
bool SimpleEntitySimulation::addEntityInternal(EntityItem* entity) {
if (entity->isMoving()) {
_movingEntities.insert(entity);
} else if (entity->getCollisionsWillMove()) {
_movableButStoppedEntities.insert(entity);
}
return true;
}
void SimpleEntitySimulation::removeEntityInternal(EntityItem* entity) {

View file

@ -23,7 +23,7 @@ public:
protected:
virtual void updateEntitiesInternal(const quint64& now);
virtual void addEntityInternal(EntityItem* entity);
virtual bool addEntityInternal(EntityItem* entity);
virtual void removeEntityInternal(EntityItem* entity);
virtual void entityChangedInternal(EntityItem* entity);
virtual void clearEntitiesInternal();

View file

@ -168,8 +168,12 @@ void EntityMotionState::updateObjectVelocities() {
}
}
void EntityMotionState::computeShapeInfo(ShapeInfo& shapeInfo) {
_entity->computeShapeInfo(shapeInfo);
bool EntityMotionState::computeShapeInfo(ShapeInfo& shapeInfo) {
if (_entity->isReadyToComputeShape()) {
_entity->computeShapeInfo(shapeInfo);
return true;
}
return false;
}
float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const {

View file

@ -53,7 +53,7 @@ public:
virtual void updateObjectEasy(uint32_t flags, uint32_t frame);
virtual void updateObjectVelocities();
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
virtual bool computeShapeInfo(ShapeInfo& shapeInfo);
virtual float computeMass(const ShapeInfo& shapeInfo) const;
virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame);

View file

@ -67,7 +67,7 @@ public:
MotionStateType getType() const { return _type; }
virtual MotionType getMotionType() const { return _motionType; }
virtual void computeShapeInfo(ShapeInfo& info) = 0;
virtual bool computeShapeInfo(ShapeInfo& info) = 0;
virtual float computeMass(const ShapeInfo& shapeInfo) const = 0;
void setFriction(float friction);

View file

@ -58,31 +58,49 @@ void PhysicsEngine::updateEntitiesInternal(const quint64& now) {
}
}
void PhysicsEngine::addEntityInternal(EntityItem* entity) {
bool PhysicsEngine::addEntityInternal(EntityItem* entity) {
qDebug() << "PhysicsEngine::addEntityInternal";
assert(entity);
void* physicsInfo = entity->getPhysicsInfo();
if (!physicsInfo) {
if (entity->isReadyToComputeShape()) {
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() << " PhysicsEngine::addEntityInternal no physicsInfo";
if (! entity->isReadyToComputeShape()) {
qDebug() << " PhysicsEngine::addEntityInternal not ready to compute";
return false;
}
qDebug() << " PhysicsEngine::addEntityInternal ready to compute";
ShapeInfo shapeInfo;
entity->computeShapeInfo(shapeInfo);
DoubleHashKey hkey = shapeInfo.getHash();
qDebug() << " shapeInfo hash:" << hkey.getHash() << hkey.getHash2();
btCollisionShape* shape = _shapeManager.getShape(shapeInfo);
if (shape) {
qDebug() << " got a shape";
EntityMotionState* motionState = new EntityMotionState(entity);
entity->setPhysicsInfo(static_cast<void*>(motionState));
_entityMotionStates.insert(motionState);
addObject(shapeInfo, shape, motionState);
} else if (entity->isMoving()) {
qDebug() << " no shape but is moving";
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";
} else {
qDebug() << " no shape and not moving";
}
} else {
qDebug() << " PhysicsEngine::addEntityInternal already had physicsInfo";
}
return true;
}
void PhysicsEngine::removeEntityInternal(EntityItem* entity) {
@ -105,18 +123,28 @@ void PhysicsEngine::removeEntityInternal(EntityItem* entity) {
}
void PhysicsEngine::entityChangedInternal(EntityItem* entity) {
qDebug() << "PhysicsEngine::entityChangedInternal";
// queue incoming changes: from external sources (script, EntityServer, etc) to physics engine
assert(entity);
void* physicsInfo = entity->getPhysicsInfo();
if (physicsInfo) {
qDebug() << " PhysicsEngine::entityChangedInternal had physicsInfo";
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
_incomingChanges.insert(motionState);
} else {
qDebug() << " PhysicsEngine::entityChangedInternal had no physicsInfo";
// try to add this entity again (maybe something changed such that it will work this time)
addEntity(entity);
}
}
// void PhysicsEngine::reconfigureEntity(EntityItem* entity) {
// qDebug() << "PhysicsEngine::reconfigureEntity";
// entityChangedInternal(entity);
// }
void PhysicsEngine::sortEntitiesThatMovedInternal() {
// entities that have been simulated forward (hence in the _entitiesToBeSorted list)
// also need to be put in the outgoingPackets list
@ -509,8 +537,20 @@ bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio
// get new shape
btCollisionShape* oldShape = body->getCollisionShape();
ShapeInfo shapeInfo;
motionState->computeShapeInfo(shapeInfo);
bool computeShapeInfoResult = motionState->computeShapeInfo(shapeInfo);
qDebug() << "\n\n---";
qDebug() << "PhysicsEngine::updateObjectHard #1 computeShapeInfoResult =" << computeShapeInfoResult;
btCollisionShape* newShape = _shapeManager.getShape(shapeInfo);
DoubleHashKey hkey = shapeInfo.getHash();
qDebug() << " shapeInfo hash:" << hkey.getHash() << hkey.getHash2();
qDebug() << " newShape =" << newShape;
if (!newShape) {
// FAIL! we are unable to support these changes!
_shapeManager.releaseShape(oldShape);
@ -563,7 +603,12 @@ bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio
if (! (flags & EntityItem::DIRTY_MASS)) {
// always update mass properties when going dynamic (unless it's already been done above)
ShapeInfo shapeInfo;
motionState->computeShapeInfo(shapeInfo);
bool computeShapeInfoResult = motionState->computeShapeInfo(shapeInfo);
qDebug() << "\n\n---";
qDebug() << "PhysicsEngine::updateObjectHard #2 computeShapeInfoResult =" << computeShapeInfoResult;
float mass = motionState->computeMass(shapeInfo);
btVector3 inertia(0.0f, 0.0f, 0.0f);
body->getCollisionShape()->calculateLocalInertia(mass, inertia);

View file

@ -60,7 +60,7 @@ public:
// overrides for EntitySimulation
void updateEntitiesInternal(const quint64& now);
void addEntityInternal(EntityItem* entity);
bool addEntityInternal(EntityItem* entity);
void removeEntityInternal(EntityItem* entity);
void entityChangedInternal(EntityItem* entity);
void sortEntitiesThatMovedInternal();
@ -88,6 +88,8 @@ public:
void setAvatarData(AvatarData *avatarData);
// virtual void reconfigureEntity(EntityItem* entity);
private:
/// \param motionState pointer to Object's MotionState
void removeObjectFromBullet(ObjectMotionState* motionState);