Can now draw mesh hierarchies from gltf files (no textures, not yet animated)

simple_math_single_header
Martin Felis 2018-03-28 22:21:21 +02:00
parent 07fbfb3c8c
commit eb189326b1
3 changed files with 89 additions and 35 deletions

View File

@ -558,6 +558,8 @@ void Renderer::RenderScene(RenderProgram &program, const Camera& camera) {
program.SetMat44("uModelMatrix", Matrix44f::Identity()); program.SetMat44("uModelMatrix", Matrix44f::Identity());
program.SetVec4("uColor", Vector4f (1.0f, 1.0f, 1.0f, 1.0f)); program.SetVec4("uColor", Vector4f (1.0f, 1.0f, 1.0f, 1.0f));
gXZPlaneMesh.Draw(GL_TRIANGLES); gXZPlaneMesh.Draw(GL_TRIANGLES);
gAssetFile.DrawModel(program);
} }
void Renderer::DrawGui() { void Renderer::DrawGui() {

View File

@ -554,7 +554,7 @@ void VertexArray::Bind() {
// Attribute 0: coords // Attribute 0: coords
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer( glVertexAttribPointer(
0, VertexAttributePosition,
4, 4,
GL_FLOAT, GL_FLOAT,
GL_FALSE, GL_FALSE,
@ -564,7 +564,7 @@ void VertexArray::Bind() {
// Attribute 1: normals // Attribute 1: normals
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glVertexAttribPointer( glVertexAttribPointer(
1, VertexAttributeNormal,
3, 3,
GL_FLOAT, GL_FLOAT,
GL_FALSE, GL_FALSE,
@ -574,17 +574,17 @@ void VertexArray::Bind() {
// Attribute 2: texture coordinates // Attribute 2: texture coordinates
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
glVertexAttribPointer( glVertexAttribPointer(
2, VertexAttributeTexCoord0,
2, 2,
GL_FLOAT, GL_FLOAT,
GL_FALSE, GL_FALSE,
(sizeof(VertexData)), (sizeof(VertexData)),
(void*)(sizeof(float) * 7) (void*)(sizeof(float) * 7)
); );
// Attribute 1: color // Attribute 3: color
glEnableVertexAttribArray(3); glEnableVertexAttribArray(3);
glVertexAttribPointer( glVertexAttribPointer(
3, VertexAttributeColor,
4, 4,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
GL_TRUE, GL_TRUE,
@ -761,13 +761,22 @@ void AssetFile::LoadBuffers() {
} }
} }
enum PrimitiveType { VertexAttributeType AssetFile::GetVertexAttributeType(const std::string &attribute_string) const {
PrimitivePosition = 1, VertexAttributeType attribute_type;
PrimitiveNormal, if (attribute_string.compare("POSITION") == 0) {
PrimitiveTexCoord0 attribute_type = VertexAttributePosition;
}; } else if (attribute_string.compare("NORMAL") == 0) {
attribute_type = VertexAttributeNormal;
} else if (attribute_string.compare("TEXCOORD_0") == 0) {
attribute_type = VertexAttributeTexCoord0;
} else {
attribute_type = VertexAttributeTypeCount;
}
void AssetFile::DrawMesh(const tinygltf::Mesh &mesh, const Matrix44f& matrix) { return attribute_type;
}
void AssetFile::DrawMesh(const tinygltf::Mesh &mesh, const Matrix44f& matrix) const {
for (int i = 0, n = mesh.primitives.size(); i < n; ++i) { for (int i = 0, n = mesh.primitives.size(); i < n; ++i) {
const tinygltf::Primitive& primitive = mesh.primitives[i]; const tinygltf::Primitive& primitive = mesh.primitives[i];
@ -792,35 +801,64 @@ void AssetFile::DrawMesh(const tinygltf::Mesh &mesh, const Matrix44f& matrix) {
default: assert(0); break; default: assert(0); break;
} }
PrimitiveType primitive_type; VertexAttributeType attribute_type = GetVertexAttributeType(it->first);
if (it->first.compare("POSITION") == 0) {
primitive_type = PrimitivePosition;
} else if (it->first.compare("NORMAL") == 0) {
primitive_type = PrimitiveNormal;
} else if (it->first.compare("TEXCOORD_0") == 0) {
primitive_type = PrimitiveTexCoord0;
} else {
gLog("Invalid primitive type: %s", it->first.c_str());
assert(false);
}
if ((it->first.compare("POSITION") == 0) if (attribute_type != VertexAttributeTypeCount) {
|| (it->first.compare("NORMAL") == 0)
|| (it->first.compare("TEXCOORD_0") == 0)) {
int byte_stride = accessor.ByteStride(mGLTFModel.bufferViews[accessor.bufferView]); int byte_stride = accessor.ByteStride(mGLTFModel.bufferViews[accessor.bufferView]);
assert(byte_stride != -1); assert(byte_stride != -1);
glVertexAttribPointer(
attribute_type,
size,
accessor.componentType,
accessor.normalized ? GL_TRUE : GL_FALSE,
byte_stride,
(char *)NULL + accessor.byteOffset);
glEnableVertexAttribArray(attribute_type);
}
}
const tinygltf::Accessor& index_accessor = mGLTFModel.accessors[primitive.indices];
glBindBuffer(
GL_ELEMENT_ARRAY_BUFFER,
mBuffers[index_accessor.bufferView]
);
int mode = -1;
switch (primitive.mode) {
case TINYGLTF_MODE_TRIANGLES : mode = GL_TRIANGLES; break;
case TINYGLTF_MODE_TRIANGLE_STRIP: mode = GL_TRIANGLE_STRIP; break;
case TINYGLTF_MODE_TRIANGLE_FAN: mode = GL_TRIANGLE_FAN; break;
case TINYGLTF_MODE_POINTS: mode = GL_POINTS; break;
case TINYGLTF_MODE_LINE: mode = GL_LINES; break;
case TINYGLTF_MODE_LINE_LOOP: mode = GL_LINE_LOOP; break;
default: gLog("Invalid primitive mode: %d", primitive.mode); assert(false);
}
glDrawElements(
mode,
index_accessor.count,
index_accessor.componentType,
(char *)NULL + index_accessor.byteOffset
);
for (; it != it_end; it++) {
VertexAttributeType attribute_type = GetVertexAttributeType(it->first);
if (attribute_type != VertexAttributeTypeCount) {
glDisableVertexAttribArray(attribute_type);
} }
} }
} }
} }
void AssetFile::DrawNode(const tinygltf::Node &node, const Matrix44f& matrix) { void AssetFile::DrawNode(RenderProgram &program, const tinygltf::Node &node, const Matrix44f& matrix) const {
Matrix44f local_matrix = matrix; Matrix44f local_matrix = matrix;
if (node.matrix.size() == 16) { if (node.matrix.size() == 16) {
// convert the matrix from double to float
Matrix44f mat; Matrix44f mat;
memcpy(mat.data(), node.matrix.data(), sizeof(float) * 4); for (int i = 0; i < 16; ++i) {
mat.data()[i] = node.matrix.data()[i];
}
local_matrix *= mat; local_matrix *= mat;
} else { } else {
if (node.scale.size() == 3) { if (node.scale.size() == 3) {
@ -836,20 +874,23 @@ void AssetFile::DrawNode(const tinygltf::Node &node, const Matrix44f& matrix) {
} }
} }
DrawMesh (mGLTFModel.meshes[node.mesh], local_matrix); if (node.mesh >= 0) {
program.SetMat44("uModelMatrix", local_matrix);
DrawMesh (mGLTFModel.meshes[node.mesh], local_matrix);
}
for (int i = 0; i < node.children.size(); ++i) { for (int i = 0; i < node.children.size(); ++i) {
DrawNode(mGLTFModel.nodes[node.children[i]], matrix); DrawNode(program, mGLTFModel.nodes[node.children[i]], local_matrix);
} }
} }
void AssetFile::DrawModel() { void AssetFile::DrawModel(RenderProgram& program) const {
// todo: support non-default scenes // todo: support non-default scenes
assert(mGLTFModel.defaultScene >= 0); assert(mGLTFModel.defaultScene >= 0);
const tinygltf::Scene &scene = mGLTFModel.scenes[mGLTFModel.defaultScene]; const tinygltf::Scene &scene = mGLTFModel.scenes[mGLTFModel.defaultScene];
for (int i = 0; i < scene.nodes.size(); ++i) { for (int i = 0; i < scene.nodes.size(); ++i) {
const tinygltf::Node &node = mGLTFModel.nodes[scene.nodes[i]]; const tinygltf::Node &node = mGLTFModel.nodes[scene.nodes[i]];
DrawNode(node, Matrix44f::Identity()); DrawNode(program, node, RotateMat44(90, 0.0, 0.0, 1.0));
} }
} }

View File

@ -289,6 +289,14 @@ struct Texture {
bool Load(const char* path, int num_components = 3); bool Load(const char* path, int num_components = 3);
}; };
enum VertexAttributeType {
VertexAttributePosition = 0,
VertexAttributeNormal = 1,
VertexAttributeTexCoord0 = 2,
VertexAttributeColor = 3,
VertexAttributeTypeCount
};
/** /**
* Storage for (multiple) VertexArrayMeshes * Storage for (multiple) VertexArrayMeshes
* Storage order is: * Storage order is:
@ -422,9 +430,12 @@ struct AssetFile {
bool Load(const char* filename); bool Load(const char* filename);
void LoadBuffers(); void LoadBuffers();
void DrawMesh(const tinygltf::Mesh &mesh, const Matrix44f &matrix); VertexAttributeType GetVertexAttributeType(const std::string &attribute_string) const;
void DrawNode(const tinygltf::Node &node, const Matrix44f &matrix); void DrawMesh(const tinygltf::Mesh &mesh, const Matrix44f &matrix) const;
void DrawModel(); void DrawNode(RenderProgram& program, const tinygltf::Node &node, const Matrix44f &matrix) const;
void DrawModel(RenderProgram& program) const;
// Debug UI
void DrawNodeGui(const tinygltf::Node& node); void DrawNodeGui(const tinygltf::Node& node);
void DrawGui(); void DrawGui();
}; };