mirror of
https://github.com/overte-org/overte.git
synced 2025-07-10 21:38:40 +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;
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
Loading…
Reference in a new issue