From 26f5d3cfaa382dcf075ba7f8f503e7b2305bbcb3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 26 Jul 2016 07:55:34 -0700 Subject: [PATCH] fix render geometry for collision shapes --- .../physics/src/CollisionRenderMeshCache.cpp | 84 ++++++++++++------- libraries/render-utils/src/Model.cpp | 23 +++-- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/libraries/physics/src/CollisionRenderMeshCache.cpp b/libraries/physics/src/CollisionRenderMeshCache.cpp index 22f0b986ab..ef2f9013ef 100644 --- a/libraries/physics/src/CollisionRenderMeshCache.cpp +++ b/libraries/physics/src/CollisionRenderMeshCache.cpp @@ -18,53 +18,69 @@ #include // for MAX_HULL_POINTS -float verts[3 * MAX_HULL_POINTS]; +const int32_t MAX_HULL_INDICES = 6 * MAX_HULL_POINTS; +float tempVertexBuffer[3 * MAX_HULL_POINTS]; +model::Index tempIndexBuffer[MAX_HULL_INDICES]; -void copyShapeToMesh(const btTransform& transform, const btConvexShape* shape, model::MeshPointer mesh) { - assert((bool)mesh); +//void copyShapeToMesh(const btTransform& transform, const btConvexShape* shape, model::MeshPointer mesh) { +void copyShapeToMesh(const btTransform& transform, const btConvexShape* shape, + gpu::BufferView& vertices, gpu::BufferView& indices, gpu::BufferView& parts) { assert(shape); btShapeHull hull(shape); const btScalar MARGIN = 0.0f; hull.buildHull(MARGIN); - const uint32_t* hullIndices = hull.getIndexPointer(); - int32_t numIndices = hull.numIndices(); - assert(numIndices <= 6 * MAX_HULL_POINTS); + int32_t numHullIndices = hull.numIndices(); + assert(numHullIndices <= MAX_HULL_INDICES); + + int32_t numHullVertices = hull.numVertices(); + assert(numHullVertices <= MAX_HULL_POINTS); { // new part model::Mesh::Part part; - part._startIndex = mesh->getIndexBuffer().getNumElements(); - part._numIndices = (model::Index)numIndices; - part._baseVertex = mesh->getVertexBuffer().getNumElements(); + part._startIndex = indices.getNumElements(); + part._numIndices = (model::Index)numHullIndices; + // FIXME: the render code cannot handle the case where part._baseVertex != 0 + //part._baseVertex = vertices.getNumElements(); // DOES NOT WORK + part._baseVertex = 0; gpu::BufferView::Size numBytes = sizeof(model::Mesh::Part); const gpu::Byte* data = reinterpret_cast(&part); - mesh->getPartBuffer()._buffer->append(numBytes, data); + parts._buffer->append(numBytes, data); + parts._size = parts._buffer->getSize(); } + model::Index indexOffset = vertices.getNumElements(); { // new vertices const btVector3* hullVertices = hull.getVertexPointer(); - int32_t numVertices = hull.numVertices(); - assert(numVertices <= MAX_HULL_POINTS); - for (int32_t i = 0; i < numVertices; ++i) { + assert(numHullVertices <= MAX_HULL_POINTS); + for (int32_t i = 0; i < numHullVertices; ++i) { btVector3 transformedPoint = transform * hullVertices[i]; - memcpy(transformedPoint.m_floats, verts + 3 * i, 3 * sizeof(float)); - //data[0] = transformedPoint.getX(); - //data[1] = transformedPoint.getY(); - //data[2] = transformedPoint.getZ(); + memcpy(tempVertexBuffer + 3 * i, transformedPoint.m_floats, 3 * sizeof(float)); } - gpu::BufferView::Size numBytes = sizeof(float) * (3 * numVertices); - const gpu::Byte* data = reinterpret_cast(verts); - mesh->getVertexBuffer()._buffer->append(numBytes, data); + gpu::BufferView::Size numBytes = sizeof(float) * (3 * numHullVertices); + const gpu::Byte* data = reinterpret_cast(tempVertexBuffer); + vertices._buffer->append(numBytes, data); + vertices._size = vertices._buffer->getSize(); } { // new indices - gpu::BufferView::Size numBytes = (gpu::BufferView::Size)(sizeof(uint32_t) * hull.numIndices()); - const gpu::Byte* data = reinterpret_cast(hullIndices); - mesh->getIndexBuffer()._buffer->append(numBytes, data); + const uint32_t* hullIndices = hull.getIndexPointer(); + // FIXME: the render code cannot handle the case where part._baseVertex != 0 + // so we must add an offset to each index + for (int32_t i = 0; i < numHullIndices; ++i) { + tempIndexBuffer[i] = hullIndices[i] + indexOffset; + } + const gpu::Byte* data = reinterpret_cast(tempIndexBuffer); + gpu::BufferView::Size numBytes = (gpu::BufferView::Size)(sizeof(model::Index) * numHullIndices); + indices._buffer->append(numBytes, data); + indices._size = indices._buffer->getSize(); } + + gpu::BufferView::Iterator partItr = parts.cbegin(); + gpu::Size numParts = parts.getNumElements(); } model::MeshPointer createMeshFromShape(const void* pointer) { @@ -73,17 +89,18 @@ model::MeshPointer createMeshFromShape(const void* pointer) { return mesh; } - // pointer must actually be a const btCollisionShape*, but it only - // needs to be valid here when its render mesh is created. + // pointer must be a const btCollisionShape* (cast to void*), but it only + // needs to be valid here when its render mesh is created, after this call + // the cache doesn't care what happens to the shape behind the pointer const btCollisionShape* shape = static_cast(pointer); int32_t shapeType = shape->getShapeType(); if (shapeType == (int32_t)COMPOUND_SHAPE_PROXYTYPE || shape->isConvex()) { // create the mesh and allocate buffers for it mesh = std::make_shared(); - mesh->setVertexBuffer(gpu::BufferView(new gpu::Buffer(), mesh->getVertexBuffer()._element)); - mesh->setIndexBuffer(gpu::BufferView(new gpu::Buffer(), mesh->getIndexBuffer()._element)); - mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(), mesh->getPartBuffer()._element)); + gpu::BufferView vertices(new gpu::Buffer(), mesh->getVertexBuffer()._element); + gpu::BufferView indices(new gpu::Buffer(), mesh->getIndexBuffer()._element); + gpu::BufferView parts(new gpu::Buffer(), mesh->getPartBuffer()._element); if (shapeType == (int32_t)COMPOUND_SHAPE_PROXYTYPE) { const btCompoundShape* compoundShape = static_cast(shape); @@ -92,14 +109,19 @@ model::MeshPointer createMeshFromShape(const void* pointer) { const btCollisionShape* childShape = compoundShape->getChildShape(i); if (childShape->isConvex()) { const btConvexShape* convexShape = static_cast(childShape); - copyShapeToMesh(compoundShape->getChildTransform(i), convexShape, mesh); + copyShapeToMesh(compoundShape->getChildTransform(i), convexShape, vertices, indices, parts); } } } else { // shape is convex const btConvexShape* convexShape = static_cast(shape); - copyShapeToMesh(btTransform(), convexShape, mesh); + btTransform transform; + transform.setIdentity(); + copyShapeToMesh(transform, convexShape, vertices, indices, parts); } + mesh->setVertexBuffer(vertices); + mesh->setIndexBuffer(indices); + mesh->setPartBuffer(parts); } return mesh; } @@ -151,7 +173,7 @@ bool CollisionRenderMeshCache::releaseMesh(CollisionRenderMeshCache::Key key) { void CollisionRenderMeshCache::collectGarbage() { uint32_t numShapes = _pendingGarbage.size(); - for (int32_t i = 0; i < numShapes; ++i) { + for (uint32_t i = 0; i < numShapes; ++i) { CollisionRenderMeshCache::Key key = _pendingGarbage[i]; CollisionMeshMap::const_iterator itr = _meshMap.find(key); if (itr != _meshMap.end()) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 075e550dd5..bbb0294e21 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -219,10 +219,6 @@ void Model::updateRenderItems() { modelMeshOffset.postTranslate(self->_offset); } - // only apply offset only, collision mesh does not share the same unit scale as the FBX file's mesh. - Transform collisionMeshOffset; - collisionMeshOffset.postTranslate(self->_offset); - uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; render::PendingChanges pendingChanges; @@ -243,6 +239,11 @@ void Model::updateRenderItems() { }); } + // collision mesh does not share the same unit scale as the FBX file's mesh: only apply offset + Transform collisionMeshOffset; + // adebug FIXME: recover correct behavior for collisionURL shapes + //collisionMeshOffset.postTranslate(self->_offset); + collisionMeshOffset.setIdentity(); foreach (auto itemID, self->_collisionRenderItems.keys()) { pendingChanges.updateItem(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) { // update the model transform for this render item. @@ -1321,12 +1322,16 @@ void Model::createCollisionRenderItemSet() { Q_ASSERT(_collisionRenderItemsSet.isEmpty()); Transform transform; - transform.setTranslation(_translation); - transform.setRotation(_rotation); + transform.setIdentity(); + // adebug FIXME: recover correct behavior for collisionURL + //transform.setTranslation(_translation); + //transform.setRotation(_rotation); Transform offset; - offset.setScale(_scale); - offset.postTranslate(_offset); + // adebug FIXME: recover correct behavior for collisionURL + offset.setIdentity(); + //offset.setScale(_scale); + //offset.postTranslate(_offset); // Run through all of the meshes, and place them into their segregated, but unsorted buckets uint32_t numMeshes = (uint32_t)meshes.size(); @@ -1339,7 +1344,7 @@ void Model::createCollisionRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - model::MaterialPointer& material = _collisionHullMaterials[partIndex % NUM_COLLISION_HULL_COLORS]; + model::MaterialPointer& material = _collisionHullMaterials[partIndex % NUM_COLLISION_HULL_COLORS]; _collisionRenderItemsSet << std::make_shared(mesh, partIndex, material, transform, offset); } }