Merge pull request #4471 from sethalves/avatars-can-collide

Avatars can collide redux
This commit is contained in:
Brad Hefta-Gaub 2015-03-19 16:31:26 -07:00
commit 46fb9cd615
7 changed files with 52 additions and 33 deletions

View file

@ -410,13 +410,30 @@ const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityI
if (entityItem->getType() == EntityTypes::Model) {
const RenderableModelEntityItem* constModelEntityItem = dynamic_cast<const RenderableModelEntityItem*>(entityItem);
RenderableModelEntityItem* modelEntityItem = const_cast<RenderableModelEntityItem*>(constModelEntityItem);
assert(modelEntityItem); // we need this!!!
result = modelEntityItem->getModel(this);
}
return result;
}
const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(const EntityItem* entityItem) {
const FBXGeometry* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
const RenderableModelEntityItem* constModelEntityItem = dynamic_cast<const RenderableModelEntityItem*>(entityItem);
if (constModelEntityItem->hasCollisionModel()) {
RenderableModelEntityItem* modelEntityItem = const_cast<RenderableModelEntityItem*>(constModelEntityItem);
Model* model = modelEntityItem->getModel(this);
if (model) {
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = model->getCollisionGeometry();
if (!collisionNetworkGeometry.isNull()) {
result = &collisionNetworkGeometry->getFBXGeometry();
}
}
}
}
return result;
}
void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement) {
glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter();
float elementSize = entityTreeElement->getScale();
@ -591,7 +608,7 @@ void EntityTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, co
static_cast<EntityTree*>(_tree)->processEraseMessage(dataByteArray, sourceNode);
}
Model* EntityTreeRenderer::allocateModel(const QString& url) {
Model* EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) {
Model* model = NULL;
// Make sure we only create and delete models on the thread that owns the EntityTreeRenderer
if (QThread::currentThread() != thread()) {
@ -604,10 +621,11 @@ Model* EntityTreeRenderer::allocateModel(const QString& url) {
model = new Model();
model->init();
model->setURL(QUrl(url));
model->setCollisionModelURL(QUrl(collisionUrl));
return model;
}
Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl) {
Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl, const QString& collisionUrl) {
Model* model = NULL;
// The caller shouldn't call us if the URL doesn't need to change. But if they
@ -636,6 +654,7 @@ Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl) {
model = new Model();
model->init();
model->setURL(QUrl(newUrl));
model->setCollisionModelURL(QUrl(collisionUrl));
return model;
}

View file

@ -59,15 +59,16 @@ public:
virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem);
virtual const Model* getModelForEntityItem(const EntityItem* entityItem);
virtual const FBXGeometry* getCollisionGeometryForEntity(const EntityItem* entityItem);
/// clears the tree
virtual void clear();
/// if a renderable entity item needs a model, we will allocate it for them
Q_INVOKABLE Model* allocateModel(const QString& url);
Q_INVOKABLE Model* allocateModel(const QString& url, const QString& collisionUrl);
/// if a renderable entity item needs to update the URL of a model, we will handle that for the entity
Q_INVOKABLE Model* updateModel(Model* original, const QString& newUrl);
Q_INVOKABLE Model* updateModel(Model* original, const QString& newUrl, const QString& collisionUrl);
/// if a renderable entity item is done with a model, it should return it to us
void releaseModel(Model* model);

View file

@ -223,10 +223,10 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
// if we have a previously allocated model, but it's URL doesn't match
// then we need to let our renderer update our model for us.
if (_model && QUrl(getModelURL()) != _model->getURL()) {
result = _model = _myRenderer->updateModel(_model, getModelURL());
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL());
_needsInitialSimulation = true;
} else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one
result = _model = _myRenderer->allocateModel(getModelURL());
result = _model = _myRenderer->allocateModel(getModelURL(), getCollisionModelURL());
_needsInitialSimulation = true;
} else { // we already have the model we want...
result = _model;
@ -267,36 +267,32 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
}
bool RenderableModelEntityItem::isReadyToComputeShape() {
if (_collisionModelURL == "") {
if (!_model) {
return false; // hmm...
}
if (_model->getCollisionURL().isEmpty()) {
// no model url, so we're ready to compute a shape.
return true;
}
if (! _collisionNetworkGeometry.isNull() && _collisionNetworkGeometry->isLoadedWithTextures()) {
// we have a _collisionModelURL AND a _collisionNetworkGeometry AND it's fully loaded.
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
if (! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoadedWithTextures()) {
// we have a _collisionModelURL AND a collisionNetworkGeometry AND it's fully loaded.
return true;
}
if (_collisionNetworkGeometry.isNull()) {
// we have a _collisionModelURL but we don't yet have a _collisionNetworkGeometry.
_collisionNetworkGeometry =
DependencyManager::get<GeometryCache>()->getGeometry(_collisionModelURL, QUrl(), false, false);
if (! _collisionNetworkGeometry.isNull() && _collisionNetworkGeometry->isLoadedWithTextures()) {
// shortcut in case it's already loaded.
return true;
}
}
// the model is still being downloaded.
return false;
}
void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
if (_collisionModelURL == "") {
if (_model->getCollisionURL().isEmpty()) {
info.setParams(getShapeType(), 0.5f * getDimensions());
} else {
const FBXGeometry& fbxGeometry = _collisionNetworkGeometry->getFBXGeometry();
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry();
_points.clear();
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
@ -310,9 +306,9 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
ShapeType RenderableModelEntityItem::getShapeType() const {
// XXX make hull an option in edit.js ?
if (_collisionModelURL != "") {
return SHAPE_TYPE_CONVEX_HULL;
} else {
if (!_model || _model->getCollisionURL().isEmpty()) {
return _shapeType;
} else {
return SHAPE_TYPE_CONVEX_HULL;
}
}

View file

@ -30,8 +30,7 @@ public:
_needsInitialSimulation(true),
_needsModelReload(true),
_myRenderer(NULL),
_originalTexturesRead(false),
_collisionNetworkGeometry(QSharedPointer<NetworkGeometry>()) { }
_originalTexturesRead(false) { }
virtual ~RenderableModelEntityItem();
@ -67,8 +66,6 @@ private:
QString _currentTextures;
QStringList _originalTextures;
bool _originalTexturesRead;
QSharedPointer<NetworkGeometry> _collisionNetworkGeometry;
QVector<glm::vec3> _points;
};

View file

@ -31,6 +31,7 @@ class EntityItemFBXService {
public:
virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem) = 0;
virtual const Model* getModelForEntityItem(const EntityItem* entityItem) = 0;
virtual const FBXGeometry* getCollisionGeometryForEntity(const EntityItem* entityItem) = 0;
};

View file

@ -298,6 +298,7 @@ void PhysicsEngine::stepSimulation() {
_clock.reset();
float timeStep = btMin(dt, MAX_TIMESTEP);
_avatarData->lockForRead();
if (_avatarData->isPhysicsEnabled()) {
// update character controller
glm::quat rotation = _avatarData->getOrientation();
@ -307,6 +308,7 @@ void PhysicsEngine::stepSimulation() {
btVector3 walkVelocity = glmToBullet(_avatarData->getVelocity());
_characterController->setVelocityForTimeInterval(walkVelocity, timeStep);
}
_avatarData->unlock();
// This is step (2).
int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP);

View file

@ -106,11 +106,11 @@ public:
/// \param delayLoad if true, don't load the model immediately; wait until actually requested
Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(),
bool retainCurrent = false, bool delayLoad = false);
const QUrl& getURL() const { return _url; }
// Set the model to use for collisions
Q_INVOKABLE void setCollisionModelURL(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false);
const QUrl& getURL() const { return _url; }
const QUrl& getCollisionURL() const { return _collisionUrl; }
/// Sets the distance parameter used for LOD computations.
void setLODDistance(float distance) { _lodDistance = distance; }
@ -132,6 +132,9 @@ public:
/// Returns a reference to the shared geometry.
const QSharedPointer<NetworkGeometry>& getGeometry() const { return _geometry; }
/// Returns a reference to the shared collision geometry.
const QSharedPointer<NetworkGeometry> getCollisionGeometry() {return _collisionGeometry; }
/// Returns the number of joint states in the model.
int getJointStateCount() const { return _jointStates.size(); }