Merge pull request #7251 from sethalves/fix-hulls-for-non-default-registration

fix collisions with non-default registration
This commit is contained in:
Andrew Meadows 2016-03-07 15:46:13 -08:00
commit 592d29fc7c
7 changed files with 78 additions and 29 deletions

View file

@ -336,6 +336,33 @@ bool RenderableModelEntityItem::getAnimationFrame() {
return newFrame; return newFrame;
} }
void RenderableModelEntityItem::updateModelBounds() {
if (!hasModel() || !_model) {
return;
}
bool movingOrAnimating = isMovingRelativeToParent() || isAnimatingSomething();
if ((movingOrAnimating ||
_needsInitialSimulation ||
_model->getTranslation() != getPosition() ||
_model->getRotation() != getRotation() ||
_model->getRegistrationPoint() != getRegistrationPoint())
&& _model->isActive() && _dimensionsInitialized) {
_model->setScaleToFit(true, getDimensions());
_model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
_model->setRotation(getRotation());
_model->setTranslation(getPosition());
// make sure to simulate so everything gets set up correctly for rendering
{
PerformanceTimer perfTimer("_model->simulate");
_model->simulate(0.0f);
}
_needsInitialSimulation = false;
}
}
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles
// the per frame simulation/update that might be required if the models properties changed. // the per frame simulation/update that might be required if the models properties changed.
void RenderableModelEntityItem::render(RenderArgs* args) { void RenderableModelEntityItem::render(RenderArgs* args) {
@ -414,27 +441,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
} }
} }
}); });
updateModelBounds();
bool movingOrAnimating = isMovingRelativeToParent() || isAnimatingSomething();
if ((movingOrAnimating ||
_needsInitialSimulation ||
_model->getTranslation() != getPosition() ||
_model->getRotation() != getRotation() ||
_model->getRegistrationPoint() != getRegistrationPoint())
&& _model->isActive() && _dimensionsInitialized) {
_model->setScaleToFit(true, getDimensions());
_model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
_model->setRotation(getRotation());
_model->setTranslation(getPosition());
// make sure to simulate so everything gets set up correctly for rendering
{
PerformanceTimer perfTimer("_model->simulate");
_model->simulate(0.0f);
}
_needsInitialSimulation = false;
}
} }
} }
} else { } else {
@ -598,7 +605,9 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
if (type != SHAPE_TYPE_COMPOUND) { if (type != SHAPE_TYPE_COMPOUND) {
ModelEntityItem::computeShapeInfo(info); ModelEntityItem::computeShapeInfo(info);
info.setParams(type, 0.5f * getDimensions()); info.setParams(type, 0.5f * getDimensions());
adjustShapeInfoByRegistration(info);
} else { } else {
updateModelBounds();
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry(); const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
// should never fall in here when collision model not fully loaded // should never fall in here when collision model not fully loaded
@ -690,10 +699,13 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
AABox box; AABox box;
for (int i = 0; i < _points.size(); i++) { for (int i = 0; i < _points.size(); i++) {
for (int j = 0; j < _points[i].size(); j++) { for (int j = 0; j < _points[i].size(); j++) {
// compensate for registraion // compensate for registration
_points[i][j] += _model->getOffset(); _points[i][j] += _model->getOffset();
// scale so the collision points match the model points // scale so the collision points match the model points
_points[i][j] *= scale; _points[i][j] *= scale;
// this next subtraction is done so we can give info the offset, which will cause
// the shape-key to change.
_points[i][j] -= _model->getOffset();
box += _points[i][j]; box += _points[i][j];
} }
} }
@ -701,6 +713,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
glm::vec3 collisionModelDimensions = box.getDimensions(); glm::vec3 collisionModelDimensions = box.getDimensions();
info.setParams(type, collisionModelDimensions, _compoundShapeURL); info.setParams(type, collisionModelDimensions, _compoundShapeURL);
info.setConvexHulls(_points); info.setConvexHulls(_points);
info.setOffset(_model->getOffset());
} }
} }

View file

@ -49,6 +49,7 @@ public:
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override; virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override;
void updateModelBounds();
virtual void render(RenderArgs* args) override; virtual void render(RenderArgs* args) override;
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,

View file

@ -142,7 +142,7 @@ glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const {
glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
bool success; // TODO -- Does this actually have to happen in world space? bool success; // TODO -- Does this actually have to happen in world space?
glm::vec3 center = getCenterPosition(success); glm::vec3 center = getCenterPosition(success); // this handles registrationPoint changes
glm::vec3 position = getPosition(success); glm::vec3 position = getPosition(success);
glm::vec3 positionToCenter = center - position; glm::vec3 positionToCenter = center - position;
@ -430,6 +430,13 @@ ShapeType RenderablePolyVoxEntityItem::getShapeType() const {
return SHAPE_TYPE_COMPOUND; return SHAPE_TYPE_COMPOUND;
} }
void RenderablePolyVoxEntityItem::updateRegistrationPoint(const glm::vec3& value) {
if (value != _registrationPoint) {
_meshDirty = true;
EntityItem::updateRegistrationPoint(value);
}
}
bool RenderablePolyVoxEntityItem::isReadyToComputeShape() { bool RenderablePolyVoxEntityItem::isReadyToComputeShape() {
_meshLock.lockForRead(); _meshLock.lockForRead();
if (_meshDirty) { if (_meshDirty) {
@ -1224,10 +1231,16 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorkerAsync() {
} }
glm::vec3 collisionModelDimensions = box.getDimensions(); glm::vec3 collisionModelDimensions = box.getDimensions();
QByteArray b64 = _voxelData.toBase64(); // include the registrationPoint in the shape key, because the offset is already
// included in the points and the shapeManager wont know that the shape has changed.
QString shapeKey = QString(_voxelData.toBase64()) + "," +
QString::number(_registrationPoint.x) + "," +
QString::number(_registrationPoint.y) + "," +
QString::number(_registrationPoint.z);
_shapeInfoLock.lockForWrite(); _shapeInfoLock.lockForWrite();
_shapeInfo.setParams(SHAPE_TYPE_COMPOUND, collisionModelDimensions, QString(b64)); _shapeInfo.setParams(SHAPE_TYPE_COMPOUND, collisionModelDimensions, shapeKey);
_shapeInfo.setConvexHulls(points); _shapeInfo.setConvexHulls(points);
// adjustShapeInfoByRegistration(_shapeInfo);
_shapeInfoLock.unlock(); _shapeInfoLock.unlock();
_meshLock.lockForWrite(); _meshLock.lockForWrite();

View file

@ -116,6 +116,8 @@ public:
virtual void rebakeMesh(); virtual void rebakeMesh();
virtual void updateRegistrationPoint(const glm::vec3& value);
private: private:
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions
// may not match _voxelVolumeSize. // may not match _voxelVolumeSize.

View file

@ -677,7 +677,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp); READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint); READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, updateRegistrationPoint);
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping); READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping);
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
@ -1120,7 +1120,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
// these (along with "position" above) affect tree structure // these (along with "position" above) affect tree structure
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensions); SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensions);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, updateRegistrationPoint);
// these (along with all properties above) affect the simulation // these (along with all properties above) affect the simulation
SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, updateDensity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, updateDensity);
@ -1340,6 +1340,15 @@ float EntityItem::getRadius() const {
return 0.5f * glm::length(getDimensions()); return 0.5f * glm::length(getDimensions());
} }
void EntityItem::adjustShapeInfoByRegistration(ShapeInfo& info) const {
if (_registrationPoint != ENTITY_ITEM_DEFAULT_REGISTRATION_POINT) {
glm::mat4 scale = glm::scale(getDimensions());
glm::mat4 registration = scale * glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint());
glm::vec3 regTransVec = glm::vec3(registration[3]); // extract position component from matrix
info.setOffset(regTransVec);
}
}
bool EntityItem::contains(const glm::vec3& point) const { bool EntityItem::contains(const glm::vec3& point) const {
if (getShapeType() == SHAPE_TYPE_COMPOUND) { if (getShapeType() == SHAPE_TYPE_COMPOUND) {
bool success; bool success;
@ -1348,12 +1357,21 @@ bool EntityItem::contains(const glm::vec3& point) const {
} else { } else {
ShapeInfo info; ShapeInfo info;
info.setParams(getShapeType(), glm::vec3(0.5f)); info.setParams(getShapeType(), glm::vec3(0.5f));
adjustShapeInfoByRegistration(info);
return info.contains(worldToEntity(point)); return info.contains(worldToEntity(point));
} }
} }
void EntityItem::computeShapeInfo(ShapeInfo& info) { void EntityItem::computeShapeInfo(ShapeInfo& info) {
info.setParams(getShapeType(), 0.5f * getDimensions()); info.setParams(getShapeType(), 0.5f * getDimensions());
adjustShapeInfoByRegistration(info);
}
void EntityItem::updateRegistrationPoint(const glm::vec3& value) {
if (value != _registrationPoint) {
setRegistrationPoint(value);
_dirtyFlags |= Simulation::DIRTY_SHAPE;
}
} }
void EntityItem::updatePosition(const glm::vec3& value) { void EntityItem::updatePosition(const glm::vec3& value) {

View file

@ -305,6 +305,7 @@ public:
// TODO: get rid of users of getRadius()... // TODO: get rid of users of getRadius()...
float getRadius() const; float getRadius() const;
virtual void adjustShapeInfoByRegistration(ShapeInfo& info) const;
virtual bool contains(const glm::vec3& point) const; virtual bool contains(const glm::vec3& point) const;
virtual bool isReadyToComputeShape() { return !isDead(); } virtual bool isReadyToComputeShape() { return !isDead(); }
@ -319,6 +320,7 @@ public:
virtual void setRotation(glm::quat orientation) { setOrientation(orientation); } virtual void setRotation(glm::quat orientation) { setOrientation(orientation); }
// updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags // updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags
virtual void updateRegistrationPoint(const glm::vec3& value);
void updatePosition(const glm::vec3& value); void updatePosition(const glm::vec3& value);
void updatePositionFromNetwork(const glm::vec3& value); void updatePositionFromNetwork(const glm::vec3& value);
void updateDimensions(const glm::vec3& value); void updateDimensions(const glm::vec3& value);

View file

@ -106,11 +106,11 @@ btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) {
} }
break; break;
} }
if (shape && type != SHAPE_TYPE_COMPOUND) { if (shape) {
if (glm::length2(info.getOffset()) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET) { if (glm::length2(info.getOffset()) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET) {
// this shape has an offset, which we support by wrapping the true shape // this shape has an offset, which we support by wrapping the true shape
// in a btCompoundShape with a local transform // in a btCompoundShape with a local transform
auto compound = new btCompoundShape(); auto compound = new btCompoundShape();
btTransform trans; btTransform trans;
trans.setIdentity(); trans.setIdentity();
trans.setOrigin(glmToBullet(info.getOffset())); trans.setOrigin(glmToBullet(info.getOffset()));