From edaa8f998a340384ca3319d21f0d29520e41f87a Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 2 Oct 2015 18:12:16 -0700 Subject: [PATCH] Migrating to the new mesh for rendering and having problems with multi part mesh --- libraries/fbx/src/FBXReader.h | 1 + libraries/fbx/src/FBXReader_Mesh.cpp | 72 ++++++++--- libraries/gpu/src/gpu/GLBackendInput.cpp | 2 +- .../src/model-networking/ModelCache.cpp | 119 ------------------ .../src/model-networking/ModelCache.h | 4 +- libraries/render-utils/src/Model.cpp | 52 ++++---- 6 files changed, 87 insertions(+), 163 deletions(-) diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index ab0bfeacf1..3bb0545e78 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -123,6 +123,7 @@ class FBXMeshPart { public: QVector quadIndices; // original indices from the FBX mesh + QVector quadTrianglesIndices; // original indices from the FBX mesh of the quad converted has triangles QVector triangleIndices; // original indices from the FBX mesh mutable gpu::BufferPointer mergedTrianglesIndicesBuffer; // both the quads and the triangles merged into a single set of triangles diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp index 299968d663..2754fc5d67 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXReader_Mesh.cpp @@ -348,6 +348,28 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn appendIndex(data, part.quadIndices, beginIndex++); appendIndex(data, part.quadIndices, beginIndex++); appendIndex(data, part.quadIndices, beginIndex++); + + int quadStartIndex = part.quadIndices.size() - 4; + int i0 = part.quadIndices[quadStartIndex + 0]; + int i1 = part.quadIndices[quadStartIndex + 1]; + int i2 = part.quadIndices[quadStartIndex + 2]; + int i3 = part.quadIndices[quadStartIndex + 3]; + + // Sam's recommended triangle slices + // Triangle tri1 = { v0, v1, v3 }; + // Triangle tri2 = { v1, v2, v3 }; + // NOTE: Random guy on the internet's recommended triangle slices + // Triangle tri1 = { v0, v1, v2 }; + // Triangle tri2 = { v2, v3, v0 }; + + part.quadTrianglesIndices.append(i0); + part.quadTrianglesIndices.append(i1); + part.quadTrianglesIndices.append(i3); + + part.quadTrianglesIndices.append(i1); + part.quadTrianglesIndices.append(i2); + part.quadTrianglesIndices.append(i3); + } else { for (int nextIndex = beginIndex + 1;; ) { appendIndex(data, part.triangleIndices, beginIndex); @@ -369,11 +391,22 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*"); + unsigned int totalSourceIndices = 0; + foreach(const FBXMeshPart& part, extracted.mesh.parts) { + totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size()); + } + + if (!totalSourceIndices) { + qCDebug(modelformat) << "buildModelMesh failed -- no indices, url = " << url; + return; + } + if (extracted.mesh.vertices.size() == 0) { extracted.mesh._mesh; qCDebug(modelformat) << "buildModelMesh failed -- no vertices, url = " << url; return; } + FBXMesh& fbxMesh = extracted.mesh; model::MeshPointer mesh(new model::Mesh()); @@ -456,9 +489,8 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { unsigned int totalIndices = 0; - foreach(const FBXMeshPart& part, extracted.mesh.parts) { - totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); + totalIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size()); } if (! totalIndices) { @@ -473,24 +505,34 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { int offset = 0; std::vector< model::Mesh::Part > parts; - + if (extracted.mesh.parts.size() > 1) { + indexNum = 0; + } foreach(const FBXMeshPart& part, extracted.mesh.parts) { - model::Mesh::Part quadPart(indexNum, part.quadIndices.size(), 0, model::Mesh::QUADS); - if (quadPart._numIndices) { - parts.push_back(quadPart); - ib->setSubData(offset, part.quadIndices.size() * sizeof(int), - (gpu::Byte*) part.quadIndices.constData()); - offset += part.quadIndices.size() * sizeof(int); - indexNum += part.quadIndices.size(); + model::Mesh::Part modelPart(indexNum, 0, 0, model::Mesh::TRIANGLES); + if (part.quadTrianglesIndices.size()) { + + + ib->setSubData( offset, + part.quadTrianglesIndices.size() * sizeof(int), + (gpu::Byte*) part.quadTrianglesIndices.constData()); + offset += part.quadTrianglesIndices.size() * sizeof(int); + indexNum += part.quadTrianglesIndices.size(); + modelPart._numIndices += part.quadTrianglesIndices.size(); } - model::Mesh::Part triPart(indexNum, part.triangleIndices.size(), 0, model::Mesh::TRIANGLES); - if (triPart._numIndices) { - parts.push_back(triPart); - ib->setSubData(offset, part.triangleIndices.size() * sizeof(int), - (gpu::Byte*) part.triangleIndices.constData()); + // model::Mesh::Part triPart(indexNum, part.triangleIndices.size(), 0, model::Mesh::TRIANGLES); + + if (part.triangleIndices.size()) { + // parts.push_back(triPart); + ib->setSubData( offset, + part.triangleIndices.size() * sizeof(int), + (gpu::Byte*) part.triangleIndices.constData()); offset += part.triangleIndices.size() * sizeof(int); indexNum += part.triangleIndices.size(); + modelPart._numIndices += part.triangleIndices.size(); } + + parts.push_back(modelPart); } gpu::BufferView ibv(ib, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::XYZ)); diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index a70e91d7fa..5cdcf0adc6 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -315,7 +315,7 @@ void GLBackend::do_setIndirectBuffer(Batch& batch, uint32 paramOffset) { glBindBuffer(GL_DRAW_INDIRECT_BUFFER, getBufferID(*buffer)); } else { // FIXME do we really need this? Is there ever a draw call where we care that the element buffer is null? - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); } } diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index d8b53420a4..c7d3523496 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -266,126 +266,9 @@ void NetworkGeometry::modelRequestError(QNetworkReply::NetworkError error) { } static NetworkMesh* buildNetworkMesh(const FBXMesh& mesh, const QUrl& textureBaseUrl) { - auto textureCache = DependencyManager::get(); NetworkMesh* networkMesh = new NetworkMesh(); networkMesh->_mesh = mesh._mesh; - int totalIndices = 0; - //bool checkForTexcoordLightmap = false; - - - - // process network parts - foreach (const FBXMeshPart& part, mesh.parts) { - totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); - } - - // initialize index buffer - { - networkMesh->_indexBuffer = std::make_shared(); - networkMesh->_indexBuffer->resize(totalIndices * sizeof(int)); - int offset = 0; - foreach(const FBXMeshPart& part, mesh.parts) { - networkMesh->_indexBuffer->setSubData(offset, part.quadIndices.size() * sizeof(int), - (gpu::Byte*) part.quadIndices.constData()); - offset += part.quadIndices.size() * sizeof(int); - networkMesh->_indexBuffer->setSubData(offset, part.triangleIndices.size() * sizeof(int), - (gpu::Byte*) part.triangleIndices.constData()); - offset += part.triangleIndices.size() * sizeof(int); - } - } - - // initialize vertex buffer - { - networkMesh->_vertexBuffer = std::make_shared(); - // if we don't need to do any blending, the positions/normals can be static - if (mesh.blendshapes.isEmpty()) { - int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3); - int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3); - int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3); - int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); - int texCoords1Offset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); - int clusterIndicesOffset = texCoords1Offset + mesh.texCoords1.size() * sizeof(glm::vec2); - int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); - - networkMesh->_vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); - - networkMesh->_vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.vertices.constData()); - networkMesh->_vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.normals.constData()); - networkMesh->_vertexBuffer->setSubData(tangentsOffset, - mesh.tangents.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.tangents.constData()); - networkMesh->_vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.colors.constData()); - networkMesh->_vertexBuffer->setSubData(texCoordsOffset, - mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Byte*) mesh.texCoords.constData()); - networkMesh->_vertexBuffer->setSubData(texCoords1Offset, - mesh.texCoords1.size() * sizeof(glm::vec2), (gpu::Byte*) mesh.texCoords1.constData()); - networkMesh->_vertexBuffer->setSubData(clusterIndicesOffset, - mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Byte*) mesh.clusterIndices.constData()); - networkMesh->_vertexBuffer->setSubData(clusterWeightsOffset, - mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Byte*) mesh.clusterWeights.constData()); - - // otherwise, at least the cluster indices/weights can be static - networkMesh->_vertexStream = std::make_shared(); - networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, 0, sizeof(glm::vec3)); - if (mesh.normals.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, normalsOffset, sizeof(glm::vec3)); - if (mesh.tangents.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, tangentsOffset, sizeof(glm::vec3)); - if (mesh.colors.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, colorsOffset, sizeof(glm::vec3)); - if (mesh.texCoords.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); - if (mesh.texCoords1.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, texCoords1Offset, sizeof(glm::vec2)); - if (mesh.clusterIndices.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); - if (mesh.clusterWeights.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); - - int channelNum = 0; - networkMesh->_vertexFormat = std::make_shared(); - networkMesh->_vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - if (mesh.normals.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - if (mesh.tangents.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - if (mesh.colors.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); - if (mesh.texCoords.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); - if (mesh.texCoords1.size()) { - networkMesh->_vertexFormat->setAttribute(gpu::Stream::TEXCOORD1, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); - // } else if (checkForTexcoordLightmap && mesh.texCoords.size()) { - } else if (mesh.texCoords.size()) { - // need lightmap texcoord UV but doesn't have uv#1 so just reuse the same channel - networkMesh->_vertexFormat->setAttribute(gpu::Stream::TEXCOORD1, channelNum - 1, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); - } - if (mesh.clusterIndices.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW)); - if (mesh.clusterWeights.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW)); - } - else { - int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3); - int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); - int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); - int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); - - networkMesh->_vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); - networkMesh->_vertexBuffer->setSubData(0, mesh.tangents.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.tangents.constData()); - networkMesh->_vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Byte*) mesh.colors.constData()); - networkMesh->_vertexBuffer->setSubData(texCoordsOffset, - mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Byte*) mesh.texCoords.constData()); - networkMesh->_vertexBuffer->setSubData(clusterIndicesOffset, - mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Byte*) mesh.clusterIndices.constData()); - networkMesh->_vertexBuffer->setSubData(clusterWeightsOffset, - mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Byte*) mesh.clusterWeights.constData()); - - networkMesh->_vertexStream = std::make_shared(); - if (mesh.tangents.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, 0, sizeof(glm::vec3)); - if (mesh.colors.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, colorsOffset, sizeof(glm::vec3)); - if (mesh.texCoords.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); - if (mesh.clusterIndices.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); - if (mesh.clusterWeights.size()) networkMesh->_vertexStream->addBuffer(networkMesh->_vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); - - int channelNum = 0; - networkMesh->_vertexFormat = std::make_shared(); - networkMesh->_vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - if (mesh.normals.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - if (mesh.tangents.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - if (mesh.colors.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); - if (mesh.texCoords.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); - if (mesh.clusterIndices.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW)); - if (mesh.clusterWeights.size()) networkMesh->_vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW)); - } - } return networkMesh; } @@ -394,8 +277,6 @@ static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const auto textureCache = DependencyManager::get(); NetworkMaterial* networkMaterial = new NetworkMaterial(); - //bool checkForTexcoordLightmap = false; - networkMaterial->_material = material._material; if (!material.diffuseTexture.filename.isEmpty()) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 4067bed122..b53ea18874 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -193,12 +193,12 @@ class NetworkMesh { public: model::MeshPointer _mesh; - gpu::BufferPointer _indexBuffer; +/* gpu::BufferPointer _indexBuffer; gpu::BufferPointer _vertexBuffer; gpu::BufferStreamPointer _vertexStream; gpu::Stream::FormatPointer _vertexFormat; -}; +*/}; #endif // hifi_GeometryCache_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 872592a9a4..44484131d9 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -759,17 +759,27 @@ public: int partIndex; int _shapeID; - render::Item::Bound getBound() const { - if (_isBoundInvalid) { - model->getPartBounds(meshIndex, partIndex); - _isBoundInvalid = false; - } - return _bound; - } + // Render Item interface + render::Item::Bound getBound() const; + void render(RenderArgs* args) const; + + mutable render::Item::Bound _bound; mutable bool _isBoundInvalid = true; }; + +render::Item::Bound MeshPartPayload::getBound() const { + if (_isBoundInvalid) { + model->getPartBounds(meshIndex, partIndex); + _isBoundInvalid = false; + } + return _bound; +} +void MeshPartPayload::render(RenderArgs* args) const { + return model->renderPart(args, meshIndex, partIndex, _shapeID); +} + namespace render { template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { if (!payload->model->isVisible()) { @@ -794,14 +804,12 @@ namespace render { template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { if (payload) { - return payload->getBound(); // model->getPartBounds(payload->meshIndex, payload->partIndex); + return payload->getBound(); } return render::Item::Bound(); } template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { - if (args) { - return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, payload->_shapeID); - } + return payload->render(args); } /* template <> const model::MaterialKey& shapeGetMaterialKey(const MeshPartPayload::Pointer& payload) { @@ -1560,20 +1568,17 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape } batch.setModelTransform(_transforms[0]); + auto drawPart = drawMesh->getPartBuffer().get(partIndex); + if (mesh.blendshapes.isEmpty()) { - // Assign index buffer: batch.setIndexBuffer(gpu::UINT32, (drawMesh->getIndexBuffer()._buffer), 0); - // batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); - + batch.setInputFormat((drawMesh->getVertexFormat())); auto inputStream = drawMesh->makeBufferStream(); batch.setInputStream(0, inputStream); - - // batch.setInputFormat(networkMesh._vertexFormat); - // batch.setInputStream(0, *networkMesh._vertexStream); } else { - batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); + batch.setIndexBuffer(gpu::UINT32, (drawMesh->getIndexBuffer()._buffer), 0); batch.setInputFormat((drawMesh->getVertexFormat())); batch.setInputBuffer(0, _blendedVertexBuffers[meshIndex], 0, sizeof(glm::vec3)); @@ -1582,12 +1587,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape auto inputStream = drawMesh->makeBufferStream().makeRangedStream(2); batch.setInputStream(2, inputStream); - - /* batch.setInputFormat(networkMesh._vertexFormat); - - batch.setInputBuffer(0, _blendedVertexBuffers[meshIndex], 0, sizeof(glm::vec3)); - batch.setInputBuffer(1, _blendedVertexBuffers[meshIndex], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); - batch.setInputStream(2, *networkMesh._vertexStream);*/ } if (mesh.colors.isEmpty()) { @@ -1712,8 +1711,9 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape { PerformanceTimer perfTimer("batch.drawIndexed()"); - batch.setIndexBuffer(gpu::UINT32, part.getMergedTriangles(), 0); - batch.drawIndexed(gpu::TRIANGLES, part.mergedTrianglesIndicesCount, 0); + // part.getMergedTriangles(); + // part.mergedTrianglesIndicesCount; + batch.drawIndexed(gpu::TRIANGLES, drawPart._numIndices, drawPart._startIndex); } /* batch.setIndexBuffer(gpu::UINT32, part.getMergedTriangles(), 0);