310 if (node->has_matrix)
312 auto mat = glm::make_mat4(node->matrix);
313 glm::vec3 translation, scale, skew;
314 glm::vec4 perspective;
315 glm::quat orentation;
316 glm::decompose(mat, scale, orentation, translation, skew, perspective);
318 object->SetPosition(translation);
319 object->SetRotation(orentation);
320 object->SetScale(scale);
324 if (node->has_translation)
326 object->SetPosition(glm::vec3(node->translation[0],
327 node->translation[1],
328 node->translation[2]));
331 if (node->has_rotation)
333 object->SetRotation(glm::quat(node->rotation[3],
341 object->SetScale(glm::vec3(node->scale[0],
349 for (cgltf_size pi = 0; pi < node->mesh->primitives_count; ++pi)
351 auto& primitive = node->mesh->primitives[pi];
352 if (primitive.type != cgltf_primitive_type_triangles)
357 auto readFloats = [](
const cgltf_accessor* acc, cgltf_size i,
float* out,
int n)
359 std::fill(out, out + n, 0.0f);
360 return cgltf_accessor_read_float(acc, i, out, n) == 1;
363 auto readIndex = [](
const cgltf_accessor* acc, cgltf_size i)
366 cgltf_bool ok = cgltf_accessor_read_uint(acc, i, &out, 1);
367 return ok ?
static_cast<uint32_t
>(out) : 0;
371 cgltf_accessor* accessors[4] = {
nullptr,
nullptr,
nullptr };
373 for (cgltf_size ai = 0; ai < primitive.attributes_count; ++ai)
375 auto& attr = primitive.attributes[ai];
376 auto acc = attr.data;
383 element.
type = GL_FLOAT;
387 case cgltf_attribute_type_position:
394 case cgltf_attribute_type_color:
405 case cgltf_attribute_type_texcoord:
416 case cgltf_attribute_type_normal:
427 if (element.
size > 0)
430 vertexLayout.
stride += element.
size *
sizeof(float);
431 vertexLayout.
elements.push_back(element);
441 std::vector<float> vertices;
442 vertices.resize((vertexLayout.
stride /
sizeof(
float))* vertexCount);
444 for (cgltf_size vi = 0; vi < vertexCount; ++vi)
446 for (
auto& el : vertexLayout.
elements)
448 if (!accessors[el.index])
453 auto index = (vi * vertexLayout.
stride + el.offset) /
sizeof(
float);
454 float* outData = &vertices[index];
455 readFloats(accessors[el.index], vi, outData, el.size);
459 std::shared_ptr<Mesh>
mesh;
460 if (primitive.indices)
462 auto indexCount = primitive.indices->count;
463 std::vector<uint32_t> indices(indexCount);
464 for (cgltf_size i = 0; i < indexCount; ++i)
466 indices[i] = readIndex(primitive.indices, i);
468 mesh = std::make_shared<Mesh>(vertexLayout, vertices, indices);
472 mesh = std::make_shared<Mesh>(vertexLayout, vertices);
475 auto mat = std::make_shared<Material>();
478 if (primitive.material)
480 auto gltfMat = primitive.material;
481 if (gltfMat->has_pbr_metallic_roughness)
483 auto pbr = gltfMat->pbr_metallic_roughness;
484 auto texture = pbr.base_color_texture.texture;
485 if (texture && texture->image)
487 if (texture->image->uri)
489 auto path = folder / std::string(texture->image->uri);
491 mat->SetParam(
"baseColorTexture", tex);
495 else if (gltfMat->has_pbr_specular_glossiness)
497 auto pbr = gltfMat->pbr_specular_glossiness;
498 auto texture = pbr.diffuse_texture.texture;
499 if (texture && texture->image)
501 if (texture->image->uri)
503 auto path = folder / std::string(texture->image->uri);
505 mat->SetParam(
"baseColorTexture", tex);
515 for (cgltf_size ci = 0; ci < node->children_count; ++ci)
572 if (contents.empty())
582 cgltf_options options = {};
583 cgltf_data* data =
nullptr;
585 cgltf_result res = cgltf_parse(&options, contents.data(), contents.size(), &data);
586 if (res != cgltf_result_success)
592 auto fullFolderPath = fullPath.remove_filename();
593 auto relativeFolderPath = std::filesystem::path(path).remove_filename();
595 res = cgltf_load_buffers(&options, data, fullFolderPath.string().c_str());
596 if (res != cgltf_result_success)
603 auto scene = &data->scenes[0];
605 for (cgltf_size i = 0; i < scene->nodes_count; ++i)
607 auto node = scene->nodes[i];
611 std::vector<std::shared_ptr<AnimationClip>> clips;
612 for (cgltf_size ai = 0; ai < data->animations_count; ++ai)
614 auto& anim = data->animations[ai];
616 auto clip = std::make_shared<AnimationClip>();
617 clip->name = anim.name ? anim.name :
"noname";
618 clip->duration = 0.0f;
620 std::unordered_map<cgltf_node*, size_t> trackIndexOf;
624 auto it = trackIndexOf.find(node);
625 if (it != trackIndexOf.end())
627 return clip->tracks[it->second];
632 clip->tracks.push_back(track);
633 size_t idx = clip->tracks.size() - 1;
634 trackIndexOf[node] = idx;
635 return clip->tracks[idx];
638 for (cgltf_size ci = 0; ci < anim.channels_count; ++ci)
640 auto& channel = anim.channels[ci];
641 auto sampler = channel.sampler;
643 if (!channel.target_node || !sampler || !sampler->input || !sampler->output)
648 std::vector<float> times;
651 auto& track = GetOrCreateTrack(channel.target_node);
653 switch (channel.target_path)
655 case cgltf_animation_path_type_translation:
657 std::vector<glm::vec3> values;
659 track.positions.resize(times.size());
660 for (
size_t i = 0; i < times.size(); ++i)
662 track.positions[i].time = times[i];
663 track.positions[i].value = values[i];
667 case cgltf_animation_path_type_rotation:
669 std::vector<glm::quat> values;
671 track.rotations.resize(times.size());
672 for (
size_t i = 0; i < times.size(); ++i)
674 track.rotations[i].time = times[i];
675 track.rotations[i].value = values[i];
679 case cgltf_animation_path_type_scale:
681 std::vector<glm::vec3> values;
683 track.scales.resize(times.size());
684 for (
size_t i = 0; i < times.size(); ++i)
686 track.scales[i].time = times[i];
687 track.scales[i].value = values[i];
695 clip->duration = std::max(clip->duration, times.back());
698 clips.push_back(std::move(clip));
704 resultObject->AddComponent(animComp);
705 for (
auto& clip : clips)
707 animComp->RegisterClip(clip->name, clip);
std::shared_ptr< Texture > GetOrLoadTexture(const std::string &path)