Migrating to the new mesh for rendering and having problems with multi part mesh

This commit is contained in:
samcake 2015-10-02 18:12:16 -07:00
parent a22ee03732
commit edaa8f998a
6 changed files with 87 additions and 163 deletions

View file

@ -123,6 +123,7 @@ class FBXMeshPart {
public:
QVector<int> quadIndices; // original indices from the FBX mesh
QVector<int> quadTrianglesIndices; // original indices from the FBX mesh of the quad converted has triangles
QVector<int> triangleIndices; // original indices from the FBX mesh
mutable gpu::BufferPointer mergedTrianglesIndicesBuffer; // both the quads and the triangles merged into a single set of triangles

View file

@ -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));

View file

@ -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);
}
}

View file

@ -266,126 +266,9 @@ void NetworkGeometry::modelRequestError(QNetworkReply::NetworkError error) {
}
static NetworkMesh* buildNetworkMesh(const FBXMesh& mesh, const QUrl& textureBaseUrl) {
auto textureCache = DependencyManager::get<TextureCache>();
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<gpu::Buffer>();
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<gpu::Buffer>();
// 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<gpu::BufferStream>();
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<gpu::Stream::Format>();
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<gpu::BufferStream>();
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<gpu::Stream::Format>();
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<TextureCache>();
NetworkMaterial* networkMaterial = new NetworkMaterial();
//bool checkForTexcoordLightmap = false;
networkMaterial->_material = material._material;
if (!material.diffuseTexture.filename.isEmpty()) {

View file

@ -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

View file

@ -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<model::Mesh::Part>(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);