mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-06-22 00:20:18 +08:00
Fix basic example
Context: When parsing a mesh with primitives that have indices pointing to different buffer views, the VAO will use the last GL_ELEMENT_ARRAY_BUFFER that was bound to it. In this scenario, the mesh will not be rendered properly. When binding a mesh, return VAO and EBOs so that primitives can bind to the proper element array buffer.
This commit is contained in:
parent
912856823d
commit
a894904f11
@ -39,8 +39,8 @@ bool loadModel(tinygltf::Model &model, const char *filename) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
|
void bindMesh(std::map<int, GLuint>& vbos,
|
||||||
tinygltf::Model &model, tinygltf::Mesh &mesh) {
|
tinygltf::Model &model, tinygltf::Mesh &mesh) {
|
||||||
for (size_t i = 0; i < model.bufferViews.size(); ++i) {
|
for (size_t i = 0; i < model.bufferViews.size(); ++i) {
|
||||||
const tinygltf::BufferView &bufferView = model.bufferViews[i];
|
const tinygltf::BufferView &bufferView = model.bufferViews[i];
|
||||||
if (bufferView.target == 0) { // TODO impl drawarrays
|
if (bufferView.target == 0) { // TODO impl drawarrays
|
||||||
@ -144,12 +144,10 @@ std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vbos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind models
|
// bind models
|
||||||
void bindModelNodes(std::map<int, GLuint> vbos, tinygltf::Model &model,
|
void bindModelNodes(std::map<int, GLuint>& vbos, tinygltf::Model &model,
|
||||||
tinygltf::Node &node) {
|
tinygltf::Node &node) {
|
||||||
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
|
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
|
||||||
bindMesh(vbos, model, model.meshes[node.mesh]);
|
bindMesh(vbos, model, model.meshes[node.mesh]);
|
||||||
@ -160,7 +158,8 @@ void bindModelNodes(std::map<int, GLuint> vbos, tinygltf::Model &model,
|
|||||||
bindModelNodes(vbos, model, model.nodes[node.children[i]]);
|
bindModelNodes(vbos, model, model.nodes[node.children[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GLuint bindModel(tinygltf::Model &model) {
|
|
||||||
|
std::pair<GLuint, std::map<int, GLuint>> bindModel(tinygltf::Model &model) {
|
||||||
std::map<int, GLuint> vbos;
|
std::map<int, GLuint> vbos;
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
@ -173,19 +172,29 @@ GLuint bindModel(tinygltf::Model &model) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
// cleanup vbos
|
// cleanup vbos but do not delete index buffers yet
|
||||||
for (size_t i = 0; i < vbos.size(); ++i) {
|
for (auto it = vbos.cbegin(); it != vbos.cend();) {
|
||||||
glDeleteBuffers(1, &vbos[i]);
|
tinygltf::BufferView bufferView = model.bufferViews[it->first];
|
||||||
|
if (bufferView.target != GL_ELEMENT_ARRAY_BUFFER) {
|
||||||
|
glDeleteBuffers(1, &vbos[it->first]);
|
||||||
|
vbos.erase(it++);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vao;
|
return {vao, vbos};
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawMesh(tinygltf::Model &model, tinygltf::Mesh &mesh) {
|
void drawMesh(const std::map<int, GLuint>& vbos,
|
||||||
|
tinygltf::Model &model, tinygltf::Mesh &mesh) {
|
||||||
for (size_t i = 0; i < mesh.primitives.size(); ++i) {
|
for (size_t i = 0; i < mesh.primitives.size(); ++i) {
|
||||||
tinygltf::Primitive primitive = mesh.primitives[i];
|
tinygltf::Primitive primitive = mesh.primitives[i];
|
||||||
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
|
tinygltf::Accessor indexAccessor = model.accessors[primitive.indices];
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos.at(indexAccessor.bufferView));
|
||||||
|
|
||||||
glDrawElements(primitive.mode, indexAccessor.count,
|
glDrawElements(primitive.mode, indexAccessor.count,
|
||||||
indexAccessor.componentType,
|
indexAccessor.componentType,
|
||||||
BUFFER_OFFSET(indexAccessor.byteOffset));
|
BUFFER_OFFSET(indexAccessor.byteOffset));
|
||||||
@ -193,20 +202,22 @@ void drawMesh(tinygltf::Model &model, tinygltf::Mesh &mesh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// recursively draw node and children nodes of model
|
// recursively draw node and children nodes of model
|
||||||
void drawModelNodes(tinygltf::Model &model, tinygltf::Node &node) {
|
void drawModelNodes(const std::pair<GLuint, std::map<int, GLuint>>& vaoAndEbos,
|
||||||
|
tinygltf::Model &model, tinygltf::Node &node) {
|
||||||
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
|
if ((node.mesh >= 0) && (node.mesh < model.meshes.size())) {
|
||||||
drawMesh(model, model.meshes[node.mesh]);
|
drawMesh(vaoAndEbos.second, model, model.meshes[node.mesh]);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < node.children.size(); i++) {
|
for (size_t i = 0; i < node.children.size(); i++) {
|
||||||
drawModelNodes(model, model.nodes[node.children[i]]);
|
drawModelNodes(vaoAndEbos, model, model.nodes[node.children[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void drawModel(GLuint vao, tinygltf::Model &model) {
|
void drawModel(const std::pair<GLuint, std::map<int, GLuint>>& vaoAndEbos,
|
||||||
glBindVertexArray(vao);
|
tinygltf::Model &model) {
|
||||||
|
glBindVertexArray(vaoAndEbos.first);
|
||||||
|
|
||||||
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
|
const tinygltf::Scene &scene = model.scenes[model.defaultScene];
|
||||||
for (size_t i = 0; i < scene.nodes.size(); ++i) {
|
for (size_t i = 0; i < scene.nodes.size(); ++i) {
|
||||||
drawModelNodes(model, model.nodes[scene.nodes[i]]);
|
drawModelNodes(vaoAndEbos, model, model.nodes[scene.nodes[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
@ -282,7 +293,7 @@ void displayLoop(Window &window, const std::string &filename) {
|
|||||||
tinygltf::Model model;
|
tinygltf::Model model;
|
||||||
if (!loadModel(model, filename.c_str())) return;
|
if (!loadModel(model, filename.c_str())) return;
|
||||||
|
|
||||||
GLuint vao = bindModel(model);
|
std::pair<GLuint, std::map<int, GLuint>> vaoAndEbos = bindModel(model);
|
||||||
// dbgModel(model); return;
|
// dbgModel(model); return;
|
||||||
|
|
||||||
// Model matrix : an identity matrix (model will be at the origin)
|
// Model matrix : an identity matrix (model will be at the origin)
|
||||||
@ -317,10 +328,12 @@ void displayLoop(Window &window, const std::string &filename) {
|
|||||||
glUniform3fv(sun_position_u, 1, &sun_position[0]);
|
glUniform3fv(sun_position_u, 1, &sun_position[0]);
|
||||||
glUniform3fv(sun_color_u, 1, &sun_color[0]);
|
glUniform3fv(sun_color_u, 1, &sun_color[0]);
|
||||||
|
|
||||||
drawModel(vao, model);
|
drawModel(vaoAndEbos, model);
|
||||||
glfwSwapBuffers(window.window);
|
glfwSwapBuffers(window.window);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glDeleteVertexArrays(1, &vaoAndEbos.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void error_callback(int error, const char *description) {
|
static void error_callback(int error, const char *description) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user