mirror of
https://github.com/overte-org/overte.git
synced 2025-04-15 17:20:12 +02:00
Merge pull request #7251 from sethalves/fix-hulls-for-non-default-registration
fix collisions with non-default registration
This commit is contained in:
commit
592d29fc7c
7 changed files with 78 additions and 29 deletions
|
@ -336,6 +336,33 @@ bool RenderableModelEntityItem::getAnimationFrame() {
|
|||
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
|
||||
// the per frame simulation/update that might be required if the models properties changed.
|
||||
void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||
|
@ -414,27 +441,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
updateModelBounds();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -598,7 +605,9 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
if (type != SHAPE_TYPE_COMPOUND) {
|
||||
ModelEntityItem::computeShapeInfo(info);
|
||||
info.setParams(type, 0.5f * getDimensions());
|
||||
adjustShapeInfoByRegistration(info);
|
||||
} else {
|
||||
updateModelBounds();
|
||||
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
|
||||
|
||||
// should never fall in here when collision model not fully loaded
|
||||
|
@ -690,10 +699,13 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
AABox box;
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
for (int j = 0; j < _points[i].size(); j++) {
|
||||
// compensate for registraion
|
||||
// compensate for registration
|
||||
_points[i][j] += _model->getOffset();
|
||||
// scale so the collision points match the model points
|
||||
_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];
|
||||
}
|
||||
}
|
||||
|
@ -701,6 +713,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
glm::vec3 collisionModelDimensions = box.getDimensions();
|
||||
info.setParams(type, collisionModelDimensions, _compoundShapeURL);
|
||||
info.setConvexHulls(_points);
|
||||
info.setOffset(_model->getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override;
|
||||
|
||||
|
||||
void updateModelBounds();
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
|
|
@ -142,7 +142,7 @@ glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const {
|
|||
glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
|
||||
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
|
||||
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 positionToCenter = center - position;
|
||||
|
||||
|
@ -430,6 +430,13 @@ ShapeType RenderablePolyVoxEntityItem::getShapeType() const {
|
|||
return SHAPE_TYPE_COMPOUND;
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::updateRegistrationPoint(const glm::vec3& value) {
|
||||
if (value != _registrationPoint) {
|
||||
_meshDirty = true;
|
||||
EntityItem::updateRegistrationPoint(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderablePolyVoxEntityItem::isReadyToComputeShape() {
|
||||
_meshLock.lockForRead();
|
||||
if (_meshDirty) {
|
||||
|
@ -1224,10 +1231,16 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorkerAsync() {
|
|||
}
|
||||
|
||||
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();
|
||||
_shapeInfo.setParams(SHAPE_TYPE_COMPOUND, collisionModelDimensions, QString(b64));
|
||||
_shapeInfo.setParams(SHAPE_TYPE_COMPOUND, collisionModelDimensions, shapeKey);
|
||||
_shapeInfo.setConvexHulls(points);
|
||||
// adjustShapeInfoByRegistration(_shapeInfo);
|
||||
_shapeInfoLock.unlock();
|
||||
|
||||
_meshLock.lockForWrite();
|
||||
|
|
|
@ -116,6 +116,8 @@ public:
|
|||
|
||||
virtual void rebakeMesh();
|
||||
|
||||
virtual void updateRegistrationPoint(const glm::vec3& value);
|
||||
|
||||
private:
|
||||
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions
|
||||
// may not match _voxelVolumeSize.
|
||||
|
|
|
@ -677,7 +677,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
|
||||
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_VISIBLE, bool, setVisible);
|
||||
|
@ -1120,7 +1120,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
// these (along with "position" above) affect tree structure
|
||||
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
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, updateDensity);
|
||||
|
@ -1340,6 +1340,15 @@ float EntityItem::getRadius() const {
|
|||
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 {
|
||||
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||
bool success;
|
||||
|
@ -1348,12 +1357,21 @@ bool EntityItem::contains(const glm::vec3& point) const {
|
|||
} else {
|
||||
ShapeInfo info;
|
||||
info.setParams(getShapeType(), glm::vec3(0.5f));
|
||||
adjustShapeInfoByRegistration(info);
|
||||
return info.contains(worldToEntity(point));
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||
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) {
|
||||
|
|
|
@ -305,6 +305,7 @@ public:
|
|||
// TODO: get rid of users of getRadius()...
|
||||
float getRadius() const;
|
||||
|
||||
virtual void adjustShapeInfoByRegistration(ShapeInfo& info) const;
|
||||
virtual bool contains(const glm::vec3& point) const;
|
||||
|
||||
virtual bool isReadyToComputeShape() { return !isDead(); }
|
||||
|
@ -319,6 +320,7 @@ public:
|
|||
virtual void setRotation(glm::quat orientation) { setOrientation(orientation); }
|
||||
|
||||
// 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 updatePositionFromNetwork(const glm::vec3& value);
|
||||
void updateDimensions(const glm::vec3& value);
|
||||
|
|
|
@ -106,11 +106,11 @@ btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (shape && type != SHAPE_TYPE_COMPOUND) {
|
||||
if (shape) {
|
||||
if (glm::length2(info.getOffset()) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET) {
|
||||
// this shape has an offset, which we support by wrapping the true shape
|
||||
// in a btCompoundShape with a local transform
|
||||
auto compound = new btCompoundShape();
|
||||
auto compound = new btCompoundShape();
|
||||
btTransform trans;
|
||||
trans.setIdentity();
|
||||
trans.setOrigin(glmToBullet(info.getOffset()));
|
||||
|
|
Loading…
Reference in a new issue