get gltf mesh loading half done

This commit is contained in:
Bailey Harrison 2023-12-12 09:56:37 +00:00
parent 0b911d11d6
commit 7115acab87
7 changed files with 120 additions and 17 deletions

View File

@ -5,7 +5,7 @@ option(ENGINE_BUILD_TEST "Compile the test program" ON)
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo") SET(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo")
project(engine LANGUAGES CXX project(engine LANGUAGES CXX C
VERSION "0.1.0" VERSION "0.1.0"
) )
@ -120,7 +120,7 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_EXTENSIONS OFF) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_EXTENSIONS OFF)
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99) set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 11)
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD_REQUIRED ON) set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD_REQUIRED ON)
set_property(TARGET ${PROJECT_NAME} PROPERTY C_EXTENSIONS OFF) set_property(TARGET ${PROJECT_NAME} PROPERTY C_EXTENSIONS OFF)
@ -129,7 +129,7 @@ if (MSVC)
target_compile_options(${PROJECT_NAME} PRIVATE /MP) target_compile_options(${PROJECT_NAME} PRIVATE /MP)
target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS) target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS)
else() else()
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror -pedantic) target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic)
endif() endif()
target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PUBLIC include)

View File

@ -36,7 +36,7 @@ class SceneManager {
} }
++index; ++index;
} }
if (index >= scenes_.size()) { if (static_cast<size_t>(index) >= scenes_.size()) {
throw std::runtime_error("Failed to find active scene!"); throw std::runtime_error("Failed to find active scene!");
} }
else { else {

View File

@ -40,7 +40,7 @@
#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES) #if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
#define VK_NO_PROTOTYPES #define VK_NO_PROTOTYPES
#endif #endif
#include "volk/volk.h" #include "volk.h"
// Initialization data, for ImGui_ImplVulkan_Init() // Initialization data, for ImGui_ImplVulkan_Init()
// [Please zero-clear before use!] // [Please zero-clear before use!]

View File

@ -728,7 +728,8 @@ static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext
static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn)
{ {
int iNumUniqueVerts = 0, t=0, i=0; // int iNumUniqueVerts = 0;
int t=0, i=0;
for (t=0; t<iNrTrianglesIn; t++) for (t=0; t<iNrTrianglesIn; t++)
{ {
for (i=0; i<3; i++) for (i=0; i<3; i++)
@ -762,7 +763,7 @@ static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], cons
assert(bFound); assert(bFound);
// if we found our own // if we found our own
if (index2rec == index) { ++iNumUniqueVerts; } //if (index2rec == index) { ++iNumUniqueVerts; }
piTriList_in_and_out[offs] = index2rec; piTriList_in_and_out[offs] = index2rec;
} }
@ -1202,7 +1203,8 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con
STSpace * pSubGroupTspace = NULL; STSpace * pSubGroupTspace = NULL;
SSubGroup * pUniSubGroups = NULL; SSubGroup * pUniSubGroups = NULL;
int * pTmpMembers = NULL; int * pTmpMembers = NULL;
int iMaxNrFaces=0, iUniqueTspaces=0, g=0, i=0; // int iUniqueTspaces = 0;
int iMaxNrFaces=0, g=0, i=0;
for (g=0; g<iNrActiveGroups; g++) for (g=0; g<iNrActiveGroups; g++)
if (iMaxNrFaces < pGroups[g].iNrFaces) if (iMaxNrFaces < pGroups[g].iNrFaces)
iMaxNrFaces = pGroups[g].iNrFaces; iMaxNrFaces = pGroups[g].iNrFaces;
@ -1222,7 +1224,7 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con
} }
iUniqueTspaces = 0; //iUniqueTspaces = 0;
for (g=0; g<iNrActiveGroups; g++) for (g=0; g<iNrActiveGroups; g++)
{ {
const SGroup * pGroup = &pGroups[g]; const SGroup * pGroup = &pGroups[g];
@ -1353,7 +1355,7 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con
// clean up and offset iUniqueTspaces // clean up and offset iUniqueTspaces
for (s=0; s<iUniqueSubGroups; s++) for (s=0; s<iUniqueSubGroups; s++)
free(pUniSubGroups[s].pTriMembers); free(pUniSubGroups[s].pTriMembers);
iUniqueTspaces += iUniqueSubGroups; //iUniqueTspaces += iUniqueSubGroups;
} }
// clean up // clean up

View File

@ -53,8 +53,7 @@ static glm::mat4 MatFromDoubleArray(const std::vector<double>& arr)
return mat; return mat;
} }
static void CreateNodes(engine::Scene& app_scene, const tg::Scene& gl_scene, const tg::Model& gl_model, engine::Entity parent_entity, static void CreateNodes(engine::Scene& app_scene, const tg::Scene& gl_scene, const tg::Model& gl_model, engine::Entity parent_entity, const tg::Node& node)
const tg::Node& node)
{ {
static int node_uuid = 0; static int node_uuid = 0;
@ -68,9 +67,111 @@ static void CreateNodes(engine::Scene& app_scene, const tg::Scene& gl_scene, con
if (node.mesh >= 0) { if (node.mesh >= 0) {
const tg::Mesh& mesh = gl_model.meshes.at(node.mesh); const tg::Mesh& mesh = gl_model.meshes.at(node.mesh);
const tg::Primitive& prim = mesh.primitives.front(); const tg::Primitive& prim = mesh.primitives.front(); // required
const tg::Accessor& indices_accessor = gl_model.accessors.at(prim.indices); if (prim.mode != TINYGLTF_MODE_TRIANGLES) throw std::runtime_error("glTF loader only supports triangles!");
const tg::BufferView& indices_bufferview = gl_model.bufferViews.at(indices_accessor.bufferView);
const tg::Accessor& indices_accessor = gl_model.accessors.at(prim.indices); // not required. TODO: handle no indices
size_t indices_int_size = 0;
if (indices_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) indices_int_size = 1;
if (indices_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) indices_int_size = 2;
if (indices_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) indices_int_size = 4;
if (indices_int_size == 0) throw std::runtime_error("GLTF parse error!");
const tg::BufferView& indices_bufferview = gl_model.bufferViews.at(indices_accessor.bufferView); // required for TG
const size_t indices_byteoffset = indices_accessor.byteOffset + indices_bufferview.byteOffset;
const tg::Buffer& indices_buffer = gl_model.buffers.at(indices_bufferview.buffer);
if (indices_int_size != 4) throw std::runtime_error("TODO: handle and support this");
const uint32_t* const indices_data = reinterpret_cast<const uint32_t*>(indices_buffer.data.data() + indices_byteoffset);
// in future, let Mesh constructor use spans to avoid unneccesary copy here
const std::vector<uint32_t> indices(indices_data, indices_data + indices_accessor.count);
const tg::Accessor& pos_accessor = gl_model.accessors.at(prim.attributes.at("POSITION"));
if (pos_accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) throw std::runtime_error("Position att. must be float!");
if (pos_accessor.type != 3) throw std::runtime_error("Position att. dim. must be 3!");
const tg::BufferView& pos_bufferview = gl_model.bufferViews.at(pos_accessor.bufferView);
const size_t pos_byteoffset = pos_accessor.byteOffset + pos_bufferview.byteOffset;
const size_t pos_bytestride = pos_accessor.ByteStride(pos_bufferview);
const tg::Buffer& pos_buffer = gl_model.buffers.at(pos_bufferview.buffer);
const tg::Accessor& norm_accessor = gl_model.accessors.at(prim.attributes.at("NORMAL"));
if (norm_accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) throw std::runtime_error("Normal att. must be float!");
if (norm_accessor.type != 3) throw std::runtime_error("Normal att. dim. must be 3!");
const tg::BufferView& norm_bufferview = gl_model.bufferViews.at(norm_accessor.bufferView);
const size_t norm_byteoffset = norm_accessor.byteOffset + norm_bufferview.byteOffset;
const size_t norm_bytestride = norm_accessor.ByteStride(norm_bufferview);
const tg::Buffer& norm_buffer = gl_model.buffers.at(norm_bufferview.buffer);
const tg::Accessor& uv_accessor = gl_model.accessors.at(prim.attributes.at("TEXCOORD_0"));
if (uv_accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) throw std::runtime_error("UV att. must be float!");
if (uv_accessor.type != 2) throw std::runtime_error("UV att. dim. must be 2!");
const tg::BufferView& uv_bufferview = gl_model.bufferViews.at(uv_accessor.bufferView);
const size_t uv_byteoffset = uv_accessor.byteOffset + uv_bufferview.byteOffset;
const size_t uv_bytestride = uv_accessor.ByteStride(uv_bufferview);
const tg::Buffer& uv_buffer = gl_model.buffers.at(uv_bufferview.buffer);
std::vector<engine::Vertex> vertices(pos_accessor.count);
for (size_t i = 0; i < vertices.size(); ++i) {
vertices[i].pos = *reinterpret_cast<const glm::vec3*>(&pos_buffer.data[pos_byteoffset + pos_bytestride * i]);
vertices[i].norm = *reinterpret_cast<const glm::vec3*>(&norm_buffer.data[norm_byteoffset + norm_bytestride * i]);
vertices[i].uv = *reinterpret_cast<const glm::vec2*>(&uv_buffer.data[uv_byteoffset + uv_bytestride * i]);
}
// create tangents
struct MeshData {
engine::Vertex* vertices;
const uint32_t* indices;
size_t count;
};
MeshData meshData{};
meshData.vertices = vertices.data();
meshData.indices = indices.data();
meshData.count = indices.size();
SMikkTSpaceInterface mts_interface{};
mts_interface.m_getNumFaces = [](const SMikkTSpaceContext* pContext) -> int { return static_cast<const MeshData*>(pContext->m_pUserData)->count / 3; };
mts_interface.m_getNumVerticesOfFace = [](const SMikkTSpaceContext*, const int) -> int { return 3; };
mts_interface.m_getPosition = [](const SMikkTSpaceContext* pContext, float fvPosOut[], const int iFace, const int iVert) -> void {
const MeshData* const meshData = static_cast<const MeshData*>(pContext->m_pUserData);
const glm::vec3 pos = meshData->vertices[meshData->indices[iFace * 3 + iVert]].pos;
fvPosOut[0] = pos.x;
fvPosOut[1] = pos.y;
fvPosOut[2] = pos.z;
};
mts_interface.m_getNormal = [](const SMikkTSpaceContext* pContext, float fvNormOut[], const int iFace, const int iVert) -> void {
const MeshData* const meshData = static_cast<const MeshData*>(pContext->m_pUserData);
const glm::vec3 norm = meshData->vertices[meshData->indices[iFace * 3 + iVert]].norm;
fvNormOut[0] = norm.x;
fvNormOut[1] = norm.y;
fvNormOut[2] = norm.z;
};
mts_interface.m_getTexCoord = [](const SMikkTSpaceContext* pContext, float fvTexcOut[], const int iFace, const int iVert) -> void {
const MeshData* const meshData = static_cast<const MeshData*>(pContext->m_pUserData);
const glm::vec2 uv = meshData->vertices[meshData->indices[iFace * 3 + iVert]].uv;
fvTexcOut[0] = uv.x;
fvTexcOut[1] = uv.y;
};
mts_interface.m_setTSpaceBasic = [](const SMikkTSpaceContext* pContext, const float fvTangent[], const float fSign, const int iFace,
const int iVert) -> void {
MeshData* const meshData = static_cast<MeshData*>(pContext->m_pUserData);
glm::vec4& tangent = meshData->vertices[meshData->indices[iFace * 3 + iVert]].tangent;
tangent.x = fvTangent[0];
tangent.y = fvTangent[1];
tangent.z = fvTangent[2];
tangent.w = fSign;
};
SMikkTSpaceContext mts_context{};
mts_context.m_pInterface = &mts_interface;
mts_context.m_pUserData = &meshData;
bool tan_result = genTangSpaceDefault(&mts_context);
if (tan_result == false) throw std::runtime_error("Failed to generate tangents!");
auto mesh_comp = app_scene.AddComponent<engine::MeshRenderableComponent>(entity);
mesh_comp->mesh = std::make_unique<engine::Mesh>(app_scene.app()->renderer()->GetDevice(), vertices, indices);
mesh_comp->material = std::make_unique<engine::Material>(app_scene.app()->renderer(), app_scene.app()->GetResource<Shader>("builtin.fancy"));
mesh_comp->material->SetAlbedoTexture(app_scene.app()->GetResource<Texture>("builtin.white"));
mesh_comp->material->SetNormalTexture(app_scene.app()->GetResource<Texture>("builtin.normal"));
} }
for (const int node : node.children) { for (const int node : node.children) {

View File

@ -36,7 +36,7 @@ if (MSVC)
target_compile_options(${PROJECT_NAME} PRIVATE /MP) target_compile_options(${PROJECT_NAME} PRIVATE /MP)
target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS) target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS)
else() else()
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror -pedantic) target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic)
endif() endif()
target_include_directories(${PROJECT_NAME} PRIVATE src) target_include_directories(${PROJECT_NAME} PRIVATE src)

View File

@ -74,7 +74,7 @@ void PlayGame(GameSettings settings)
} }
{ /* floor */ { /* floor */
engine::Entity floor = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/terrain.dae"), true); [[maybe_unused]] engine::Entity floor = engine::util::LoadMeshFromFile(my_scene, app.GetResourcePath("models/terrain.dae"), true);
} }
#if 0 #if 0