mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
Merge pull request #11663 from AndrewMeadows/shape-sharing
fix incorrect collision shape sharing for some ModelEntityItem configurations
This commit is contained in:
commit
ef78711b7b
4 changed files with 77 additions and 41 deletions
|
@ -695,12 +695,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
void RenderableModelEntityItem::setCollisionShape(const btCollisionShape* shape) {
|
||||
const void* key = static_cast<const void*>(shape);
|
||||
if (_collisionMeshKey != key) {
|
||||
if (_collisionMeshKey) {
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
_collisionMeshKey = key;
|
||||
// toggle _showCollisionGeometry forces re-evaluation later
|
||||
_showCollisionGeometry = !_showCollisionGeometry;
|
||||
emit requestCollisionGeometryUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1103,6 +1099,10 @@ bool ModelEntityRenderer::needsRenderUpdate() const {
|
|||
if (model->getRenderItemsNeedUpdate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_needsCollisionGeometryUpdate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
@ -1169,6 +1169,15 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
return false;
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setCollisionMeshKey(const void*key) {
|
||||
if (key != _collisionMeshKey) {
|
||||
if (_collisionMeshKey) {
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
_collisionMeshKey = key;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (_hasModel != entity->hasModel()) {
|
||||
|
@ -1201,6 +1210,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
model = std::make_shared<Model>(nullptr, entity.get());
|
||||
connect(model.get(), &Model::setURLFinished, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate);
|
||||
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
||||
model->init();
|
||||
entity->setModel(model);
|
||||
|
@ -1259,6 +1269,26 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
// TODO? early exit here when not visible?
|
||||
|
||||
if (_needsCollisionGeometryUpdate) {
|
||||
setCollisionMeshKey(entity->getCollisionMeshKey());
|
||||
_needsCollisionGeometryUpdate = false;
|
||||
ShapeType type = entity->getShapeType();
|
||||
if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) {
|
||||
// NOTE: it is OK if _collisionMeshKey is nullptr
|
||||
model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey);
|
||||
// NOTE: the model will render the collisionGeometry if it has one
|
||||
_model->setCollisionMesh(mesh);
|
||||
} else {
|
||||
if (_collisionMeshKey) {
|
||||
// release mesh
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
// clear model's collision geometry
|
||||
model::MeshPointer mesh = nullptr;
|
||||
_model->setCollisionMesh(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Fixup");
|
||||
if (model->needsFixupInScene()) {
|
||||
|
@ -1297,6 +1327,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::flagForCollisionGeometryUpdate() {
|
||||
_needsCollisionGeometryUpdate = true;
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
||||
void ModelEntityRenderer::doRender(RenderArgs* args) {
|
||||
DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender");
|
||||
|
@ -1327,28 +1362,11 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
|||
// Remap textures for the next frame to avoid flicker
|
||||
// remapTextures();
|
||||
|
||||
#if 0
|
||||
// update whether the model should be showing collision mesh (this may flag for fixupInScene)
|
||||
bool showingCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS);
|
||||
if (showingCollisionGeometry != _showCollisionGeometry) {
|
||||
ShapeType type = _entity->getShapeType();
|
||||
_showCollisionGeometry = showingCollisionGeometry;
|
||||
if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) {
|
||||
// NOTE: it is OK if _collisionMeshKey is nullptr
|
||||
model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey);
|
||||
// NOTE: the model will render the collisionGeometry if it has one
|
||||
_model->setCollisionMesh(mesh);
|
||||
} else {
|
||||
// release mesh
|
||||
if (_collisionMeshKey) {
|
||||
collisionMeshCache.releaseMesh(_collisionMeshKey);
|
||||
}
|
||||
// clear model's collision geometry
|
||||
model::MeshPointer mesh = nullptr;
|
||||
_model->setCollisionMesh(mesh);
|
||||
}
|
||||
bool showCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS);
|
||||
if (showCollisionGeometry != _showCollisionGeometry) {
|
||||
_showCollisionGeometry = showCollisionGeometry;
|
||||
flagForCollisionGeometryUpdate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames) {
|
||||
|
|
|
@ -50,6 +50,8 @@ private:
|
|||
};
|
||||
|
||||
class RenderableModelEntityItem : public ModelEntityWrapper {
|
||||
Q_OBJECT
|
||||
|
||||
friend class render::entities::ModelEntityRenderer;
|
||||
using Parent = ModelEntityWrapper;
|
||||
public:
|
||||
|
@ -105,6 +107,10 @@ public:
|
|||
virtual QStringList getJointNames() const override;
|
||||
|
||||
bool getMeshes(MeshProxyList& result) override;
|
||||
const void* getCollisionMeshKey() const { return _collisionMeshKey; }
|
||||
|
||||
signals:
|
||||
void requestCollisionGeometryUpdate();
|
||||
|
||||
private:
|
||||
bool needsUpdateModelBounds() const;
|
||||
|
@ -117,7 +123,6 @@ private:
|
|||
QVariantMap _originalTextures;
|
||||
bool _dimensionsInitialized { true };
|
||||
bool _needsJointSimulation { false };
|
||||
bool _showCollisionGeometry { false };
|
||||
const void* _collisionMeshKey { nullptr };
|
||||
};
|
||||
|
||||
|
@ -141,6 +146,8 @@ protected:
|
|||
virtual bool needsRenderUpdate() const override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
void flagForCollisionGeometryUpdate();
|
||||
void setCollisionMeshKey(const void* key);
|
||||
|
||||
private:
|
||||
void animate(const TypedEntityPointer& entity);
|
||||
|
@ -163,6 +170,7 @@ private:
|
|||
|
||||
bool _needsJointSimulation{ false };
|
||||
bool _showCollisionGeometry{ false };
|
||||
bool _needsCollisionGeometryUpdate{ false };
|
||||
const void* _collisionMeshKey{ nullptr };
|
||||
|
||||
// used on client side
|
||||
|
|
|
@ -235,7 +235,6 @@ void Model::updateRenderItems() {
|
|||
self->updateClusterMatrices();
|
||||
|
||||
Transform modelTransform = self->getTransform();
|
||||
Transform physicsTransform = modelTransform;
|
||||
modelTransform.setScale(glm::vec3(1.0f));
|
||||
|
||||
uint32_t deleteGeometryCounter = self->_deleteGeometryCounter;
|
||||
|
@ -259,13 +258,12 @@ void Model::updateRenderItems() {
|
|||
});
|
||||
}
|
||||
|
||||
// collision mesh does not share the same unit scale as the FBX file's mesh: only apply offset
|
||||
Transform collisionMeshOffset;
|
||||
collisionMeshOffset.setIdentity();
|
||||
foreach(auto itemID, self->_collisionRenderItemsMap.keys()) {
|
||||
transaction.updateItem<MeshPartPayload>(itemID, [physicsTransform, collisionMeshOffset](MeshPartPayload& data) {
|
||||
transaction.updateItem<MeshPartPayload>(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) {
|
||||
// update the model transform for this render item.
|
||||
data.updateTransform(physicsTransform, collisionMeshOffset);
|
||||
data.updateTransform(modelTransform, collisionMeshOffset);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
|
|||
}
|
||||
break;
|
||||
case SHAPE_TYPE_COMPOUND:
|
||||
case SHAPE_TYPE_SIMPLE_HULL:
|
||||
case SHAPE_TYPE_SIMPLE_COMPOUND:
|
||||
case SHAPE_TYPE_STATIC_MESH:
|
||||
_url = QUrl(url);
|
||||
break;
|
||||
|
@ -250,16 +252,26 @@ const DoubleHashKey& ShapeInfo::getHash() const {
|
|||
}
|
||||
_doubleHashKey.setHash2(hash);
|
||||
|
||||
if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_STATIC_MESH) {
|
||||
QString url = _url.toString();
|
||||
if (!url.isEmpty()) {
|
||||
// fold the urlHash into both parts
|
||||
QByteArray baUrl = url.toLocal8Bit();
|
||||
const char *cUrl = baUrl.data();
|
||||
uint32_t urlHash = qChecksum(cUrl, baUrl.count());
|
||||
_doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash);
|
||||
_doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash);
|
||||
}
|
||||
QString url = _url.toString();
|
||||
if (!url.isEmpty()) {
|
||||
// fold the urlHash into both parts
|
||||
QByteArray baUrl = url.toLocal8Bit();
|
||||
uint32_t urlHash = qChecksum(baUrl.data(), baUrl.size());
|
||||
_doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash);
|
||||
_doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash);
|
||||
}
|
||||
|
||||
uint32_t numHulls = 0;
|
||||
if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
numHulls = (uint32_t)_pointCollection.size();
|
||||
} else if (_type == SHAPE_TYPE_SIMPLE_HULL) {
|
||||
numHulls = 1;
|
||||
}
|
||||
if (numHulls > 0) {
|
||||
hash = DoubleHashKey::hashFunction(numHulls, primeIndex++);
|
||||
_doubleHashKey.setHash(_doubleHashKey.getHash() ^ hash);
|
||||
hash = DoubleHashKey::hashFunction2(numHulls);
|
||||
_doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ hash);
|
||||
}
|
||||
}
|
||||
return _doubleHashKey;
|
||||
|
|
Loading…
Reference in a new issue