Skip to content

Instantly share code, notes, and snippets.

@seanbaxter
Created August 23, 2020 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seanbaxter/947417862033ff7870e564c7a79eb2d1 to your computer and use it in GitHub Desktop.
Save seanbaxter/947417862033ff7870e564c7a79eb2d1 to your computer and use it in GitHub Desktop.
Load glTF primitive.
prim_t model_t::load_prim(const cgltf_primitive* prim) {
prim_t prim2 { };
glCreateVertexArrays(1, &prim2.vao);
if(prim->indices) {
// Bind the index array.
const cgltf_accessor* accessor = prim->indices;
const cgltf_buffer_view* view = accessor->buffer_view;
assert(cgltf_buffer_view_type_indices == view->type);
prim2.begin = accessor->offset + view->offset;
switch(accessor->component_type) {
case cgltf_component_type_r_8:
case cgltf_component_type_r_8u:
prim2.elements_type = GL_UNSIGNED_BYTE;
break;
case cgltf_component_type_r_16:
case cgltf_component_type_r_16u:
prim2.begin /= 2;
prim2.elements_type = GL_UNSIGNED_SHORT;
break;
case cgltf_component_type_r_32u:
prim2.begin /= 4;
prim2.elements_type = GL_UNSIGNED_INT;
break;
default:
break;
}
prim2.end = prim2.begin + accessor->count;
// Associate the buffer holding the indices.
GLuint buffer = buffers[find_buffer_index(data, view->buffer)];
glVertexArrayElementBuffer(prim2.vao, buffer);
PRINT_ERROR();
}
// One slot per potential VBO bind point.
const cgltf_buffer_view* views[16] { };
int binding_count = 0;
for(int a = 0; a < prim->attributes_count; ++a) {
const cgltf_attribute* attrib = prim->attributes + a;
const cgltf_accessor* accessor = attrib->data;
const cgltf_buffer_view* view = accessor->buffer_view;
assert(cgltf_buffer_view_type_vertices == view->type);
// Only support 0 index attributes. Eg, don't support TEXCOORD_1, _2
// etc quite yet.
if(attrib->index)
continue;
// Get the attribute location.
vattrib_t attribindex;
switch(attrib->type) {
case cgltf_attribute_type_position:
attribindex = vattrib_position;
break;
case cgltf_attribute_type_normal:
attribindex = vattrib_normal;
break;
case cgltf_attribute_type_texcoord:
attribindex = vattrib_texcoord;
break;
case cgltf_attribute_type_joints:
attribindex = vattrib_joints;
break;
case cgltf_attribute_type_weights:
attribindex = vattrib_weights;
break;
}
// Find an existing bufferView binding.
int bindingindex = -1;
for(int i = 0; i < binding_count; ++i) {
if(views[i] == view) {
bindingindex = i;
break;
}
}
if(-1 == bindingindex) {
// Use one binding per attribute.
bindingindex = binding_count++;
views[bindingindex] = view;
GLuint buffer = buffers[find_buffer_index(data, view->buffer)];
glVertexArrayVertexBuffer(prim2.vao, attribindex, buffer,
view->offset, view->stride);
PRINT_ERROR();
}
// Enable the vertex attribute location.
glEnableVertexArrayAttrib(prim2.vao, attribindex);
PRINT_ERROR();
// Get the attribute size and type.
GLenum type = GL_NONE;
int size = 0;
switch(accessor->type) {
case cgltf_type_scalar: size = 1; break;
case cgltf_type_vec2: size = 2; break;
case cgltf_type_vec3: size = 3; break;
case cgltf_type_vec4: size = 4; break;
default: break;
}
switch(accessor->component_type) {
case cgltf_component_type_r_8: type = GL_BYTE; break;
case cgltf_component_type_r_8u: type = GL_UNSIGNED_BYTE; break;
case cgltf_component_type_r_16: type = GL_SHORT; break;
case cgltf_component_type_r_16u: type = GL_UNSIGNED_SHORT; break;
case cgltf_component_type_r_32u: type = GL_UNSIGNED_INT; break;
case cgltf_component_type_r_32f: type = GL_FLOAT; break;
default: break;
}
// Associate the buffer view with the attribute location.
glVertexArrayAttribBinding(prim2.vao, attribindex, bindingindex);
PRINT_ERROR();
if(accessor->normalized || GL_FLOAT == type) {
glVertexArrayAttribFormat(prim2.vao, attribindex, size, type,
accessor->normalized, accessor->offset);
} else {
glVertexArrayAttribIFormat(prim2.vao, attribindex, size, type,
accessor->offset);
}
PRINT_ERROR();
}
return prim2;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment