diff --git a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp index 2ca35bdab791ea18a67f33e53ab17fc485cbad02..b322f9cc2011edd491d0694396ec095ca2c37a19 100644 --- a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp +++ b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp @@ -171,7 +171,7 @@ namespace vkcv::asset { static std::array<float, 16> calculateModelMatrix(const std::array<float, 3>& translation, const std::array<float, 3>& scale, const std::array<float, 4>& rotation, - const std::array<float, 16>& matrix){ + const std::array<float, 16>& matrix) { std::array<float, 16> modelMatrix = { 1,0,0,0, 0,1,0,0, @@ -185,32 +185,55 @@ namespace vkcv::asset { // translation modelMatrix[3] = translation[0]; modelMatrix[7] = translation[1]; - modelMatrix[11] = translation[2]; + modelMatrix[11] = -translation[2]; // flip Z to convert from GLTF to Vulkan // rotation and scale - auto a = rotation[0]; - auto q1 = rotation[1]; - auto q2 = rotation[2]; - auto q3 = rotation[3]; - - modelMatrix[0] = (2 * (a * a + q1 * q1) - 1) * scale[0]; - modelMatrix[1] = (2 * (q1 * q2 - a * q3)) * scale[1]; - modelMatrix[2] = (2 * (q1 * q3 + a * q2)) * scale[2]; - - modelMatrix[4] = (2 * (q1 * q2 + a * q3)) * scale[0]; - modelMatrix[5] = (2 * (a * a + q2 * q2) - 1) * scale[1]; - modelMatrix[6] = (2 * (q2 * q3 - a * q1)) * scale[2]; - - modelMatrix[8] = (2 * (q1 * q3 - a * q2)) * scale[0]; - modelMatrix[9] = (2 * (q2 * q3 + a * q1)) * scale[1]; - modelMatrix[10] = (2 * (a * a + q3 * q3) - 1) * scale[2]; - - // flip y, because GLTF uses y up, but vulkan -y up - modelMatrix[5] *= -1; + auto a = rotation[3]; + auto q1 = rotation[0]; + auto q2 = rotation[1]; + auto q3 = rotation[2]; + + auto s = 2 / (a * a + q1 * q1 + q2 * q2 + q3 * q3); + + auto s1 = scale[0]; + auto s2 = scale[1]; + auto s3 = -scale[2]; // flip Z to convert from GLTF to Vulkan + + modelMatrix[0] = (1 - s * (q2 * q2 + q3 * q3)) * s1; + modelMatrix[1] = ( s * (q1 * q2 - q3 * a)) * s2; + modelMatrix[2] = ( s * (q1 * q3 + q2 * a)) * s3; + + modelMatrix[4] = ( s * (q1 * q2 + q3 * a)) * s1; + modelMatrix[5] = (1 - s * (q1 * q1 + q3 * q3)) * s2; + modelMatrix[6] = ( s * (q2 * q3 - q1 * a)) * s3; + + modelMatrix[8] = ( s * (q1 * q3 - q2 * a)) * s1; + modelMatrix[9] = ( s * (q2 * q3 + q1 * a)) * s2; + modelMatrix[10] = (1 - s * (q1 * q1 + q2 * q2)) * s3; return modelMatrix; } } + + static std::array<float, 16> multiplyMatrix(const std::array<float, 16>& matrix, + const std::array<float, 16>& other) { + std::array<float, 16> result; + size_t i, j, k; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + float sum = 0.0f; + + for (k = 0; k < 4; k++) { + sum += matrix[i * 4 + k] * other[k * 4 + j]; + } + + result[i * 4 + j] = sum; + } + } + + return result; + } bool Material::hasTexture(const PBRTextureTarget target) const { return textureMask & bitflag(target); @@ -496,9 +519,23 @@ namespace vkcv::asset { try { if (path.extension() == ".glb") { - sceneObjects = fx::gltf::LoadFromBinary(path.string()); + sceneObjects = fx::gltf::LoadFromBinary( + path.string(), + { + fx::gltf::detail::DefaultMaxBufferCount, + fx::gltf::detail::DefaultMaxMemoryAllocation * 16, + fx::gltf::detail::DefaultMaxMemoryAllocation * 8 + } + ); } else { - sceneObjects = fx::gltf::LoadFromText(path.string()); + sceneObjects = fx::gltf::LoadFromText( + path.string(), + { + fx::gltf::detail::DefaultMaxBufferCount, + fx::gltf::detail::DefaultMaxMemoryAllocation, + fx::gltf::detail::DefaultMaxMemoryAllocation * 8 + } + ); } } catch (const std::system_error& err) { recurseExceptionPrint(err, path.string()); @@ -536,15 +573,54 @@ namespace vkcv::asset { scene.meshes.push_back(mesh); } - // This only works if the node has a mesh and it only loads the meshes and ignores cameras and lights - for (const auto& node : sceneObjects.nodes) { + std::vector< std::array<float, 16> > matrices; + std::vector< int32_t > parents; + + matrices.reserve(sceneObjects.nodes.size()); + parents.resize(sceneObjects.nodes.size(), -1); + + for (size_t i = 0; i < sceneObjects.nodes.size(); i++) { + const auto &node = sceneObjects.nodes[i]; + + matrices.push_back(calculateModelMatrix( + node.translation, + node.scale, + node.rotation, + node.matrix + )); + + for (int32_t child : node.children) + if ((child >= 0) && (child < parents.size())) + parents[child] = static_cast<int32_t>(i); + } + + std::vector< std::array<float, 16> > final_matrices; + final_matrices.reserve(matrices.size()); + + for (size_t i = 0; i < matrices.size(); i++) { + std::vector<int> order; + order.push_back(static_cast<int32_t>(i)); + + while (parents[ order[order.size() - 1] ] >= 0) + order.push_back(parents[ order[order.size() - 1] ]); + + std::array<float, 16> matrix = matrices[ order[order.size() - 1] ]; + + for (size_t j = order.size() - 1; j > 0; j--) { + const auto id = order[j - 1]; + const std::array<float, 16> matrix_other = matrices[ id ]; + + matrix = multiplyMatrix(matrix, matrix_other); + } + + final_matrices.push_back(matrix); + } + + for (size_t i = 0; i < sceneObjects.nodes.size(); i++) { + const auto &node = sceneObjects.nodes[i]; + if ((node.mesh >= 0) && (node.mesh < scene.meshes.size())) { - scene.meshes[node.mesh].modelMatrix = calculateModelMatrix( - node.translation, - node.scale, - node.rotation, - node.matrix - ); + scene.meshes[node.mesh].modelMatrix = final_matrices[i]; } } } diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp index 4aa450da4c11b23d686a2836f815d2c03c3675f7..c334cc3649550b33d9ecffd18c10865429e51591 100644 --- a/modules/scene/src/vkcv/scene/MeshPart.cpp +++ b/modules/scene/src/vkcv/scene/MeshPart.cpp @@ -71,8 +71,23 @@ namespace vkcv::scene { if (*this) { const auto& material = getMaterial(); + IndexBitCount indexBitCount; + + switch (vertexGroup.indexBuffer.type) { + case asset::IndexType::UINT16: + indexBitCount = IndexBitCount::Bit16; + break; + case asset::IndexType::UINT32: + indexBitCount = IndexBitCount::Bit32; + break; + default: + indexBitCount = IndexBitCount::Bit16; + vkcv_log(LogLevel::WARNING, "Unsupported index type!"); + break; + } + drawcalls.push_back(DrawcallInfo( - vkcv::Mesh(m_vertexBindings, indexBuffer.getVulkanHandle(), m_indexCount), + vkcv::Mesh(m_vertexBindings, indexBuffer.getVulkanHandle(), m_indexCount, indexBitCount), { DescriptorSetUsage(0, material.getDescriptorSet()) } )); } diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt index ffe8546c961697869354993539697b118fa8d6be..997c907fb26db2344f028ff5eaec8de3f69038b7 100644 --- a/projects/CMakeLists.txt +++ b/projects/CMakeLists.txt @@ -5,6 +5,7 @@ include(${vkcv_config_ext}/ProjectFix.cmake) add_subdirectory(first_triangle) add_subdirectory(first_mesh) add_subdirectory(first_scene) +add_subdirectory(head_demo) add_subdirectory(particle_simulation) add_subdirectory(rtx_ambient_occlusion) add_subdirectory(sph) diff --git a/projects/head_demo/.gitignore b/projects/head_demo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..151f56c5bb7098a3beb7b8e049c0ade02914cd91 --- /dev/null +++ b/projects/head_demo/.gitignore @@ -0,0 +1 @@ +head_demo \ No newline at end of file diff --git a/projects/head_demo/CMakeLists.txt b/projects/head_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..09e5f693d6c6ddc243d884a74981bdb980fb9065 --- /dev/null +++ b/projects/head_demo/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.16) +project(head_demo) + +# setting c++ standard for the project +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# this should fix the execution path to load local files from the project +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +# adding source files to the project +add_executable(head_demo src/main.cpp) +fix_project(head_demo) + +# including headers of dependencies and the VkCV framework +target_include_directories(head_demo SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_scene_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include}) + +# linking with libraries from all dependencies and the VkCV framework +target_link_libraries(head_demo vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera vkcv_scene vkcv_shader_compiler vkcv_gui) diff --git a/projects/head_demo/assets/shaders/shader.frag b/projects/head_demo/assets/shaders/shader.frag new file mode 100644 index 0000000000000000000000000000000000000000..b8756a6b84af4e93f9ac932ec01d28e4f2e9638b --- /dev/null +++ b/projects/head_demo/assets/shaders/shader.frag @@ -0,0 +1,10 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 passNormal; + +layout(location = 0) out vec3 outColor; + +void main() { + outColor = (vec3(0.3f) + max(dot(passNormal, vec3(1.0f, -1.0f, 0.5f)), 0.0f) * vec3(0.7f)); +} \ No newline at end of file diff --git a/projects/head_demo/assets/shaders/shader.geom b/projects/head_demo/assets/shaders/shader.geom new file mode 100644 index 0000000000000000000000000000000000000000..4dc5121be06366d698e1b67c178a24fda28fa6c4 --- /dev/null +++ b/projects/head_demo/assets/shaders/shader.geom @@ -0,0 +1,75 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(triangles) in; +layout(triangle_strip, max_vertices = 3) out; + +layout(location = 0) in vec3 geomNormal[]; + +layout(location = 0) out vec3 passNormal; + +layout(set=1, binding=0) uniform clipBuffer { + float clipLimit; + float clipX; + float clipY; + float clipZ; +}; + +layout( push_constant ) uniform constants{ + mat4 mvp; +}; + +#define CLIP_SCALE 10000.0f + +vec4 clipPosition(vec4 pos) { + return vec4( + min(clipX, pos.x), + min(clipY, pos.y), + min(clipZ, pos.z), + 1.0f / CLIP_SCALE + ); +} + +vec4 clipByLimit(vec4 pos) { + if (pos.x / pos.w < clipLimit) { + return vec4(pos.xyz / pos.w, 1.0f); + } else { + return vec4(clipLimit, pos.y / pos.w, pos.z / pos.w, 1.0f); + } +} + +void main() { + vec4 v0 = gl_in[0].gl_Position; + vec4 v1 = gl_in[1].gl_Position; + vec4 v2 = gl_in[2].gl_Position; + + v0 = clipPosition(v0 / CLIP_SCALE); + v1 = clipPosition(v1 / CLIP_SCALE); + v2 = clipPosition(v2 / CLIP_SCALE); + + float dx = abs(v0.x - clipX) + abs(v1.x - clipX) + abs(v2.x - clipX); + float dy = abs(v0.y - clipY) + abs(v1.y - clipY) + abs(v2.y - clipY); + float dz = abs(v0.z - clipZ) + abs(v1.z - clipZ) + abs(v2.z - clipZ); + + if (dx * dy * dz > 0.0f) { + v0 = clipByLimit(mvp * (v0 * CLIP_SCALE)); + v1 = clipByLimit(mvp * (v1 * CLIP_SCALE)); + v2 = clipByLimit(mvp * (v2 * CLIP_SCALE)); + + if ((v0.x < clipLimit) || (v1.x < clipLimit) || (v2.x < clipLimit)) { + gl_Position = v0; + passNormal = geomNormal[0]; + EmitVertex(); + + gl_Position = v1; + passNormal = geomNormal[1]; + EmitVertex(); + + gl_Position = v2; + passNormal = geomNormal[2]; + EmitVertex(); + + EndPrimitive(); + } + } +} diff --git a/projects/head_demo/assets/shaders/shader.vert b/projects/head_demo/assets/shaders/shader.vert new file mode 100644 index 0000000000000000000000000000000000000000..26e43e9c89dc2ffb2355d60be8288fa9832f8baa --- /dev/null +++ b/projects/head_demo/assets/shaders/shader.vert @@ -0,0 +1,12 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; + +layout(location = 0) out vec3 geomNormal; + +void main() { + gl_Position = vec4(inPosition, 1.0); + geomNormal = inNormal; +} \ No newline at end of file diff --git a/projects/head_demo/assets/skull/license.txt b/projects/head_demo/assets/skull/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..6816d6d659087b54dfc6b8e0c2c0e158daa001f0 --- /dev/null +++ b/projects/head_demo/assets/skull/license.txt @@ -0,0 +1,11 @@ +Model Information: +* title: The Anatomy of the Human Skull +* source: https://sketchfab.com/3d-models/the-anatomy-of-the-human-skull-baf6ac7b781a46218dca2b59dee58817 +* author: HannahNewey (https://sketchfab.com/HannahNewey) + +Model License: +* license type: CC-BY-NC-SA-4.0 (http://creativecommons.org/licenses/by-nc-sa/4.0/) +* requirements: Author must be credited. No commercial use. Modified versions must have the same license. + +If you use this 3D model in your project be sure to copy paste this credit wherever you share it: +This work is based on "The Anatomy of the Human Skull" (https://sketchfab.com/3d-models/the-anatomy-of-the-human-skull-baf6ac7b781a46218dca2b59dee58817) by HannahNewey (https://sketchfab.com/HannahNewey) licensed under CC-BY-NC-SA-4.0 (http://creativecommons.org/licenses/by-nc-sa/4.0/) \ No newline at end of file diff --git a/projects/head_demo/assets/skull/scene.bin b/projects/head_demo/assets/skull/scene.bin new file mode 100644 index 0000000000000000000000000000000000000000..20df66f1c1420d7dbc1be032a0c209858fff4a2f Binary files /dev/null and b/projects/head_demo/assets/skull/scene.bin differ diff --git a/projects/head_demo/assets/skull/scene.gltf b/projects/head_demo/assets/skull/scene.gltf new file mode 100644 index 0000000000000000000000000000000000000000..d6ea46d39f4bd957e784156e12ffb35444b6498c --- /dev/null +++ b/projects/head_demo/assets/skull/scene.gltf @@ -0,0 +1,1873 @@ +{ + "accessors": [ + { + "bufferView": 1, + "componentType": 5126, + "count": 65532, + "max": [ + 2840.37841796875, + 244.7664031982422, + -766.7376098632813 + ], + "min": [ + -3235.25927734375, + -4385.1171875, + -5725.921875 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 786384, + "componentType": 5126, + "count": 65532, + "max": [ + 0.999799907207489, + 0.9999416470527649, + 0.9999858140945435 + ], + "min": [ + -0.9999641180038452, + -0.9999430775642395, + -0.9361197352409363 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.9137254953384399, + 0.8705882430076599, + 0.6509804129600525, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "componentType": 5125, + "count": 313611, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 1572768, + "componentType": 5126, + "count": 65532, + "max": [ + 3130.354736328125, + 187.51498413085938, + -694.5037841796875 + ], + "min": [ + -3290.6533203125, + -4355.27978515625, + -5911.3916015625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 2359152, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999974370002747, + 0.9999324679374695, + 0.999767005443573 + ], + "min": [ + -0.999965250492096, + -0.9999395608901978, + -0.9859874248504639 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 1048512, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.9176470637321472, + 0.8705882430076599, + 0.6470588445663452, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 1254444, + "componentType": 5125, + "count": 321948, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 3145536, + "componentType": 5126, + "count": 65532, + "max": [ + 3344.8837890625, + 244.6723175048828, + -588.5365600585938 + ], + "min": [ + -3090.33837890625, + -4362.89599609375, + -5977.587890625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 3931920, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9997606873512268, + 0.999998152256012, + 0.9999467134475708 + ], + "min": [ + -0.9999973177909851, + -0.9998958706855774, + -0.9937521815299988 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 2097024, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.9176470637321472, + 0.8745098114013672, + 0.6470588445663452, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 2542236, + "componentType": 5125, + "count": 324204, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 4718304, + "componentType": 5126, + "count": 65532, + "max": [ + 3369.185302734375, + 215.57359313964844, + -599.1707763671875 + ], + "min": [ + -3271.009521484375, + -4311.8984375, + -6019.16015625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 5504688, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999703764915466, + 0.9999807476997375, + 0.9999433755874634 + ], + "min": [ + -0.9999938011169434, + -0.9999474287033081, + -0.9999995827674866 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 3145536, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.5098039507865906, + 0.5098039507865906, + 0.5098039507865906, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 3839052, + "componentType": 5125, + "count": 321339, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 6291072, + "componentType": 5126, + "count": 65532, + "max": [ + 3390.07470703125, + 244.83804321289063, + -587.0177612304688 + ], + "min": [ + -3188.865478515625, + -4346.97265625, + -6010.4072265625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 7077456, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999974966049194, + 0.9999837279319763, + 0.9999989867210388 + ], + "min": [ + -0.9999641180038452, + -0.9995811581611633, + -0.9993560314178467 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 4194048, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.9137254953384399, + 0.8705882430076599, + 0.6470588445663452, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 5124408, + "componentType": 5125, + "count": 322497, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 7863840, + "componentType": 5126, + "count": 65532, + "max": [ + 3370.440673828125, + 242.63902282714844, + -595.2008056640625 + ], + "min": [ + -3258.293701171875, + -4342.2158203125, + -6015.8408203125 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 8650224, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999961853027344, + 0.9999135732650757, + 0.9999547004699707 + ], + "min": [ + -0.9998935461044312, + -0.9998529553413391, + -0.9999858140945435 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 5242560, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.9176470637321472, + 0.8705882430076599, + 0.6470588445663452, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 6414396, + "componentType": 5125, + "count": 319161, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 9436608, + "componentType": 5126, + "count": 65532, + "max": [ + 3380.496337890625, + 238.19361877441406, + -596.5640869140625 + ], + "min": [ + -3271.791015625, + -4371.51220703125, + -6013.41015625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 10222992, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999738931655884, + 0.9999688267707825, + 0.9999756813049316 + ], + "min": [ + -0.9998912811279297, + -0.9996834993362427, + -0.9999995827674866 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 6291072, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.9137254953384399, + 0.8666666746139526, + 0.6470588445663452, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 7691040, + "componentType": 5125, + "count": 297117, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 11009376, + "componentType": 5126, + "count": 65532, + "max": [ + 3389.1083984375, + 243.10780334472656, + -589.3672485351563 + ], + "min": [ + -3290.338623046875, + -4384.59814453125, + -6018.95556640625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 11795760, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999974966049194, + 0.9999807476997375, + 0.9999858140945435 + ], + "min": [ + -0.9999557733535767, + -0.9997233152389526, + -0.9998651742935181 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 7339584, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.5098039507865906, + 0.5098039507865906, + 0.5098039507865906, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 8879508, + "componentType": 5125, + "count": 209295, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 12582144, + "componentType": 5126, + "count": 44391, + "max": [ + 3388.56982421875, + 244.58836364746094, + -588.1055297851563 + ], + "min": [ + -3285.114990234375, + -4384.2646484375, + -6016.705078125 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 13114836, + "componentType": 5126, + "count": 44391, + "max": [ + 0.9999710321426392, + 0.9999837279319763, + 0.9999265670776367 + ], + "min": [ + -0.9999641180038452, + -0.9998239278793335, + -0.9995859265327454 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 8388096, + "componentType": 5126, + "count": 44391, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.5098039507865906, + 0.5098039507865906, + 0.5098039507865906, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 9716688, + "componentType": 5125, + "count": 79998, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 13647528, + "componentType": 5126, + "count": 65532, + "max": [ + 3146.496337890625, + 5315.1474609375, + 6185.98681640625 + ], + "min": [ + -3952.677490234375, + -5363.68896484375, + -3587.6884765625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 14433912, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999997019767761, + 0.9999786019325256, + 0.9998370409011841 + ], + "min": [ + -0.9999956488609314, + -0.9999863505363464, + -0.9999605417251587 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 9098352, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.5333333611488342, + 0.5215686559677124, + 0.4117647111415863, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 10036680, + "componentType": 5125, + "count": 306360, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 15220296, + "componentType": 5126, + "count": 65532, + "max": [ + 3950.16015625, + 5223.5029296875, + 6478.5556640625 + ], + "min": [ + -3955.41748046875, + -5363.11962890625, + -3657.999267578125 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 16006680, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999980330467224, + 0.9999274611473083, + 0.999988853931427 + ], + "min": [ + -0.9999822974205017, + -0.9999578595161438, + -0.9999580979347229 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 10146864, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.5411764979362488, + 0.5254902243614197, + 0.46666666865348816, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 11262120, + "componentType": 5125, + "count": 313335, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 16793064, + "componentType": 5126, + "count": 65532, + "max": [ + 3927.240234375, + 5322.87109375, + 6479.7353515625 + ], + "min": [ + -3759.5595703125, + -5230.9775390625, + -3691.5771484375 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 17579448, + "componentType": 5126, + "count": 65532, + "max": [ + 0.999993085861206, + 0.9999855160713196, + 0.9999846816062927 + ], + "min": [ + -0.9999897480010986, + -0.9999833703041077, + -0.999967098236084 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 11195376, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.572549045085907, + 0.5529412031173706, + 0.4901960790157318, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 12515460, + "componentType": 5125, + "count": 313683, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 18365832, + "componentType": 5126, + "count": 65532, + "max": [ + 4082.3076171875, + 5258.32373046875, + 4838.353515625 + ], + "min": [ + -3914.320068359375, + -4704.12841796875, + -3723.84375 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 19152216, + "componentType": 5126, + "count": 65532, + "max": [ + 0.999993085861206, + 0.9999508857727051, + 0.9999281167984009 + ], + "min": [ + -0.9999762177467346, + -0.9999469518661499, + -0.9999806880950928 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 12243888, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 1.0, + 1.0 + ], + "min": [ + 0.5254902243614197, + 0.5137255191802979, + 0.4588235318660736, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 13770192, + "componentType": 5125, + "count": 314970, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 19938600, + "componentType": 5126, + "count": 65532, + "max": [ + 3978.6708984375, + 5068.7177734375, + 6478.3291015625 + ], + "min": [ + -3623.656494140625, + -5151.37060546875, + -3697.931884765625 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 20724984, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999825358390808, + 0.9999790787696838, + 0.9999794960021973 + ], + "min": [ + -0.9999620318412781, + -0.9998840689659119, + -0.9999629855155945 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 13292400, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 1.0, + 1.0 + ], + "min": [ + 0.5137255191802979, + 0.501960813999176, + 0.45098039507865906, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 15030072, + "componentType": 5125, + "count": 321024, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 21511368, + "componentType": 5126, + "count": 65532, + "max": [ + 3933.90625, + 5318.9453125, + 6449.291015625 + ], + "min": [ + -3956.8564453125, + -5107.72705078125, + -3670.520751953125 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 22297752, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999693632125854, + 0.9998798966407776, + 0.9999902844429016 + ], + "min": [ + -0.9999911189079285, + -0.9999756217002869, + -0.9999973773956299 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 14340912, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.501960813999176, + 0.4941176474094391, + 0.4431372582912445, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 16314168, + "componentType": 5125, + "count": 319773, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 23084136, + "componentType": 5126, + "count": 65532, + "max": [ + 3938.263671875, + 5276.44677734375, + 6474.9052734375 + ], + "min": [ + -3905.52099609375, + -5001.58203125, + -3704.025146484375 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 23870520, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999945759773254, + 0.9998493194580078, + 0.9999690055847168 + ], + "min": [ + -0.9998875260353088, + -0.9999592900276184, + -0.9999815225601196 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 15389424, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 1.0, + 1.0 + ], + "min": [ + 0.4117647111415863, + 0.40392157435417175, + 0.3843137323856354, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 17593260, + "componentType": 5125, + "count": 316758, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 24656904, + "componentType": 5126, + "count": 65532, + "max": [ + 3888.703369140625, + 5241.58740234375, + 6403.5859375 + ], + "min": [ + -3952.21875, + -5127.146484375, + -3704.025146484375 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 25443288, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999896287918091, + 0.9999837279319763, + 0.999700129032135 + ], + "min": [ + -0.99997878074646, + -0.999870240688324, + -0.9999804496765137 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 16437936, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.5254902243614197, + 0.5098039507865906, + 0.45490196347236633, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 18860292, + "componentType": 5125, + "count": 315858, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 26229672, + "componentType": 5126, + "count": 65532, + "max": [ + 3988.08447265625, + 5318.513671875, + 6453.59521484375 + ], + "min": [ + -3913.2177734375, + -5171.2724609375, + -3702.723876953125 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 27016056, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999912977218628, + 0.9998858571052551, + 0.9999213814735413 + ], + "min": [ + -0.9999544024467468, + -0.9997307062149048, + -0.9999856352806091 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 17486448, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.4588235318660736, + 0.45098039507865906, + 0.4156862795352936, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 20123724, + "componentType": 5125, + "count": 305763, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 27802440, + "componentType": 5126, + "count": 65532, + "max": [ + 4009.908447265625, + 5284.25244140625, + 6479.7353515625 + ], + "min": [ + -3956.53125, + -5359.29052734375, + -3723.657958984375 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 28588824, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999276995658875, + 0.9999786019325256, + 0.9999854564666748 + ], + "min": [ + -0.9999956488609314, + -0.9999469518661499, + -0.9999597668647766 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 18534960, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.4901960790157318, + 0.48235294222831726, + 0.43529412150382996, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 21346776, + "componentType": 5125, + "count": 276246, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 29375208, + "componentType": 5126, + "count": 65532, + "max": [ + 4076.767578125, + 5290.2880859375, + 6470.759765625 + ], + "min": [ + -3955.88671875, + -5352.85546875, + -3723.918701171875 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 30161592, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999912977218628, + 0.9999776482582092, + 0.9998868107795715 + ], + "min": [ + -0.9999671578407288, + -0.9998840689659119, + -0.9999973773956299 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 19583472, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.4117647111415863, + 0.40392157435417175, + 0.3843137323856354, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 22451760, + "componentType": 5125, + "count": 209874, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 30947976, + "componentType": 5126, + "count": 65532, + "max": [ + 4077.26025390625, + 5320.7841796875, + 6472.42041015625 + ], + "min": [ + -3955.21240234375, + -5363.025390625, + -3714.435302734375 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 31734360, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9999883770942688, + 0.9999697804450989, + 0.9999690055847168 + ], + "min": [ + -0.9999778270721436, + -0.9999863505363464, + -0.9999513626098633 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 20631984, + "componentType": 5126, + "count": 65532, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.42352941632270813, + 0.41960784792900085, + 0.3921568691730499, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 23291256, + "componentType": 5125, + "count": 121605, + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 32520744, + "componentType": 5126, + "count": 4421, + "max": [ + 4076.912109375, + 5293.73828125, + 6470.28125 + ], + "min": [ + -3950.871337890625, + -5356.6689453125, + -3703.1767578125 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 32573796, + "componentType": 5126, + "count": 4421, + "max": [ + 0.9998874664306641, + 0.9956235885620117, + 0.9997158646583557 + ], + "min": [ + -0.9993879199028015, + -0.9999043941497803, + -0.9998995065689087 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 21680496, + "componentType": 5126, + "count": 4421, + "max": [ + 0.9960784316062927, + 0.9960784316062927, + 0.9960784316062927, + 1.0 + ], + "min": [ + 0.6117647290229797, + 0.5921568870544434, + 0.5137255191802979, + 1.0 + ], + "type": "VEC4" + }, + { + "bufferView": 0, + "byteOffset": 23777676, + "componentType": 5125, + "count": 5229, + "type": "SCALAR" + } + ], + "asset": { + "extras": { + "author": "HannahNewey (https://sketchfab.com/HannahNewey)", + "license": "CC-BY-NC-SA-4.0 (http://creativecommons.org/licenses/by-nc-sa/4.0/)", + "source": "https://sketchfab.com/3d-models/the-anatomy-of-the-human-skull-baf6ac7b781a46218dca2b59dee58817", + "title": "The Anatomy of the Human Skull" + }, + "generator": "Sketchfab-12.68.0", + "version": "2.0" + }, + "bufferViews": [ + { + "buffer": 0, + "byteLength": 23798592, + "name": "floatBufferViews", + "target": 34963 + }, + { + "buffer": 0, + "byteLength": 32626848, + "byteOffset": 23798592, + "byteStride": 12, + "name": "floatBufferViews", + "target": 34962 + }, + { + "buffer": 0, + "byteLength": 21751232, + "byteOffset": 56425440, + "byteStride": 16, + "name": "floatBufferViews", + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 78176672, + "uri": "scene.bin" + } + ], + "materials": [ + { + "doubleSided": true, + "name": "material_0", + "pbrMetallicRoughness": { + "metallicFactor": 0.0, + "roughnessFactor": 0.6 + } + }, + { + "doubleSided": true, + "name": "material_1", + "pbrMetallicRoughness": { + "metallicFactor": 0.0, + "roughnessFactor": 0.6 + } + } + ], + "meshes": [ + { + "name": "Object_0", + "primitives": [ + { + "attributes": { + "COLOR_0": 2, + "NORMAL": 1, + "POSITION": 0 + }, + "indices": 3, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_1", + "primitives": [ + { + "attributes": { + "COLOR_0": 6, + "NORMAL": 5, + "POSITION": 4 + }, + "indices": 7, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_2", + "primitives": [ + { + "attributes": { + "COLOR_0": 10, + "NORMAL": 9, + "POSITION": 8 + }, + "indices": 11, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_3", + "primitives": [ + { + "attributes": { + "COLOR_0": 14, + "NORMAL": 13, + "POSITION": 12 + }, + "indices": 15, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_4", + "primitives": [ + { + "attributes": { + "COLOR_0": 18, + "NORMAL": 17, + "POSITION": 16 + }, + "indices": 19, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_5", + "primitives": [ + { + "attributes": { + "COLOR_0": 22, + "NORMAL": 21, + "POSITION": 20 + }, + "indices": 23, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_6", + "primitives": [ + { + "attributes": { + "COLOR_0": 26, + "NORMAL": 25, + "POSITION": 24 + }, + "indices": 27, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_7", + "primitives": [ + { + "attributes": { + "COLOR_0": 30, + "NORMAL": 29, + "POSITION": 28 + }, + "indices": 31, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_8", + "primitives": [ + { + "attributes": { + "COLOR_0": 34, + "NORMAL": 33, + "POSITION": 32 + }, + "indices": 35, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_9", + "primitives": [ + { + "attributes": { + "COLOR_0": 38, + "NORMAL": 37, + "POSITION": 36 + }, + "indices": 39, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_10", + "primitives": [ + { + "attributes": { + "COLOR_0": 42, + "NORMAL": 41, + "POSITION": 40 + }, + "indices": 43, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_11", + "primitives": [ + { + "attributes": { + "COLOR_0": 46, + "NORMAL": 45, + "POSITION": 44 + }, + "indices": 47, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_12", + "primitives": [ + { + "attributes": { + "COLOR_0": 50, + "NORMAL": 49, + "POSITION": 48 + }, + "indices": 51, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_13", + "primitives": [ + { + "attributes": { + "COLOR_0": 54, + "NORMAL": 53, + "POSITION": 52 + }, + "indices": 55, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_14", + "primitives": [ + { + "attributes": { + "COLOR_0": 58, + "NORMAL": 57, + "POSITION": 56 + }, + "indices": 59, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_15", + "primitives": [ + { + "attributes": { + "COLOR_0": 62, + "NORMAL": 61, + "POSITION": 60 + }, + "indices": 63, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_16", + "primitives": [ + { + "attributes": { + "COLOR_0": 66, + "NORMAL": 65, + "POSITION": 64 + }, + "indices": 67, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_17", + "primitives": [ + { + "attributes": { + "COLOR_0": 70, + "NORMAL": 69, + "POSITION": 68 + }, + "indices": 71, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_18", + "primitives": [ + { + "attributes": { + "COLOR_0": 74, + "NORMAL": 73, + "POSITION": 72 + }, + "indices": 75, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_19", + "primitives": [ + { + "attributes": { + "COLOR_0": 78, + "NORMAL": 77, + "POSITION": 76 + }, + "indices": 79, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_20", + "primitives": [ + { + "attributes": { + "COLOR_0": 82, + "NORMAL": 81, + "POSITION": 80 + }, + "indices": 83, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_21", + "primitives": [ + { + "attributes": { + "COLOR_0": 86, + "NORMAL": 85, + "POSITION": 84 + }, + "indices": 87, + "material": 0, + "mode": 4 + } + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 2.220446049250313e-16, + -1.0, + 0.0, + 0.0, + 1.0, + 2.220446049250313e-16, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "Sketchfab_model" + }, + { + "children": [ + 2, + 12 + ], + "name": "zbrush_concat.osgb.cleaner.materialmerger.gles" + }, + { + "children": [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11 + ], + "name": "/sketchfab-data/processing/8c9c6cc4aa274b7f8a90438ac5d9d239/preprocess/SubTool-1-13812201.OBJ" + }, + { + "mesh": 0, + "name": "Object_3" + }, + { + "mesh": 1, + "name": "Object_4" + }, + { + "mesh": 2, + "name": "Object_5" + }, + { + "mesh": 3, + "name": "Object_6" + }, + { + "mesh": 4, + "name": "Object_7" + }, + { + "mesh": 5, + "name": "Object_8" + }, + { + "mesh": 6, + "name": "Object_9" + }, + { + "mesh": 7, + "name": "Object_10" + }, + { + "mesh": 8, + "name": "Object_11" + }, + { + "children": [ + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ], + "name": "/sketchfab-data/processing/8c9c6cc4aa274b7f8a90438ac5d9d239/preprocess/SubTool-0-7233285.OBJ" + }, + { + "mesh": 9, + "name": "Object_13" + }, + { + "mesh": 10, + "name": "Object_14" + }, + { + "mesh": 11, + "name": "Object_15" + }, + { + "mesh": 12, + "name": "Object_16" + }, + { + "mesh": 13, + "name": "Object_17" + }, + { + "mesh": 14, + "name": "Object_18" + }, + { + "mesh": 15, + "name": "Object_19" + }, + { + "mesh": 16, + "name": "Object_20" + }, + { + "mesh": 17, + "name": "Object_21" + }, + { + "mesh": 18, + "name": "Object_22" + }, + { + "mesh": 19, + "name": "Object_23" + }, + { + "mesh": 20, + "name": "Object_24" + }, + { + "mesh": 21, + "name": "Object_25" + } + ], + "scene": 0, + "scenes": [ + { + "name": "Sketchfab_Scene", + "nodes": [ + 0 + ] + } + ] +} diff --git a/projects/head_demo/assets/skull_scaled/scene.bin b/projects/head_demo/assets/skull_scaled/scene.bin new file mode 100644 index 0000000000000000000000000000000000000000..64c6e2eae89e3c1ab68340bb1651cd8764a69053 Binary files /dev/null and b/projects/head_demo/assets/skull_scaled/scene.bin differ diff --git a/projects/head_demo/assets/skull_scaled/scene.gltf b/projects/head_demo/assets/skull_scaled/scene.gltf new file mode 100644 index 0000000000000000000000000000000000000000..59d6d2c00f7fe097e2e9c062d465303beabf7522 --- /dev/null +++ b/projects/head_demo/assets/skull_scaled/scene.gltf @@ -0,0 +1,203 @@ +{ + "asset" : { + "generator" : "Khronos glTF Blender I/O v1.8.19", + "version" : "2.0" + }, + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 5 + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "Object_13" + }, + { + "children" : [ + 0 + ], + "name" : "/sketchfab-data/processing/8c9c6cc4aa274b7f8a90438ac5d9d239" + }, + { + "mesh" : 1, + "name" : "Object_3" + }, + { + "children" : [ + 2 + ], + "name" : "/sketchfab-data/processing/8c9c6cc4aa274b7f8a90438ac5d9d239/pre" + }, + { + "children" : [ + 1, + 3 + ], + "name" : "zbrush_concat.osgb.cleaner.materialmerger.gles" + }, + { + "children" : [ + 4 + ], + "name" : "Sketchfab_model", + "rotation" : [ + -0.5, + 0.5, + 0.5, + 0.5 + ], + "scale" : [ + 0.0009999871253967285, + 0.0009999871253967285, + 0.0009999871253967285 + ] + } + ], + "materials" : [ + { + "doubleSided" : true, + "name" : "material_0", + "pbrMetallicRoughness" : { + "metallicFactor" : 0, + "roughnessFactor" : 0.6000000238418579 + } + }, + { + "doubleSided" : true, + "name" : "material_1", + "pbrMetallicRoughness" : { + "metallicFactor" : 0, + "roughnessFactor" : 0.6000000238418579 + } + } + ], + "meshes" : [ + { + "name" : "Object_9.001", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1 + }, + "indices" : 2, + "material" : 0 + } + ] + }, + { + "name" : "Object_0", + "primitives" : [ + { + "attributes" : { + "POSITION" : 3, + "NORMAL" : 4 + }, + "indices" : 5, + "material" : 1 + } + ] + } + ], + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5126, + "count" : 794711, + "max" : [ + 4082.3076171875, + 5322.87109375, + 6479.7353515625 + ], + "min" : [ + -3956.8564453125, + -5363.68896484375, + -3723.918701171875 + ], + "type" : "VEC3" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 794711, + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5125, + "count" : 3440478, + "type" : "SCALAR" + }, + { + "bufferView" : 3, + "componentType" : 5126, + "count" : 571860, + "max" : [ + 3390.07470703125, + 244.83804321289062, + -587.0177612304688 + ], + "min" : [ + -3290.6533203125, + -4385.1171875, + -6019.16015625 + ], + "type" : "VEC3" + }, + { + "bufferView" : 4, + "componentType" : 5126, + "count" : 571860, + "type" : "VEC3" + }, + { + "bufferView" : 5, + "componentType" : 5125, + "count" : 2509170, + "type" : "SCALAR" + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 9536532, + "byteOffset" : 0 + }, + { + "buffer" : 0, + "byteLength" : 9536532, + "byteOffset" : 9536532 + }, + { + "buffer" : 0, + "byteLength" : 13761912, + "byteOffset" : 19073064 + }, + { + "buffer" : 0, + "byteLength" : 6862320, + "byteOffset" : 32834976 + }, + { + "buffer" : 0, + "byteLength" : 6862320, + "byteOffset" : 39697296 + }, + { + "buffer" : 0, + "byteLength" : 10036680, + "byteOffset" : 46559616 + } + ], + "buffers" : [ + { + "byteLength" : 56596296, + "uri" : "scene.bin" + } + ] +} diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7acad116b2fe612df2523352d643275d34627de3 --- /dev/null +++ b/projects/head_demo/src/main.cpp @@ -0,0 +1,217 @@ +#include <iostream> +#include <vkcv/Core.hpp> +#include <GLFW/glfw3.h> +#include <vkcv/camera/CameraManager.hpp> +#include <vkcv/gui/GUI.hpp> +#include <chrono> +#include <vkcv/asset/asset_loader.hpp> +#include <vkcv/shader/GLSLCompiler.hpp> +#include <vkcv/scene/Scene.hpp> + +int main(int argc, const char** argv) { + const char* applicationName = "First Scene"; + + uint32_t windowWidth = 800; + uint32_t windowHeight = 600; + + vkcv::Core core = vkcv::Core::create( + applicationName, + VK_MAKE_VERSION(0, 0, 1), + {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, + { VK_KHR_SWAPCHAIN_EXTENSION_NAME } + ); + vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, false); + vkcv::Window& window = core.getWindow(windowHandle); + vkcv::camera::CameraManager cameraManager(window); + + vkcv::gui::GUI gui (core, windowHandle); + + uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); + uint32_t camIndex1 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); + + cameraManager.getCamera(camIndex0).setPosition(glm::vec3(15.5f, 0, 0)); + cameraManager.getCamera(camIndex0).setNearFar(0.1f, 30.0f); + + cameraManager.getCamera(camIndex1).setNearFar(0.1f, 30.0f); + + vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path( + argc > 1 ? argv[1] : "assets/skull_scaled/scene.gltf" + )); + + const vkcv::AttachmentDescription present_color_attachment( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR, + core.getSwapchain(windowHandle).getFormat() + ); + + const vkcv::AttachmentDescription depth_attachment( + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR, + vk::Format::eD32Sfloat + ); + + vkcv::PassConfig scenePassDefinition({ present_color_attachment, depth_attachment }); + vkcv::PassHandle scenePass = core.createPass(scenePassDefinition); + + if (!scenePass) { + std::cout << "Error. Could not create renderpass. Exiting." << std::endl; + return EXIT_FAILURE; + } + + vkcv::ShaderProgram sceneShaderProgram; + vkcv::shader::GLSLCompiler compiler; + + compiler.compileProgram(sceneShaderProgram, { + { vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" }, + { vkcv::ShaderStage::GEOMETRY, "assets/shaders/shader.geom" }, + { vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" } + }, nullptr); + + const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments(); + std::vector<vkcv::VertexBinding> bindings; + for (size_t i = 0; i < vertexAttachments.size(); i++) { + bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] })); + } + + const auto& clipBindings = sceneShaderProgram.getReflectedDescriptors().at(1); + + auto clipDescriptorSetLayout = core.createDescriptorSetLayout(clipBindings); + auto clipDescriptorSet = core.createDescriptorSet(clipDescriptorSetLayout); + + float clipLimit = 1.0f; + float clipX = 0.0f; + float clipY = 0.0f; + float clipZ = 0.0f; + + auto clipBuffer = core.createBuffer<float>(vkcv::BufferType::UNIFORM, 4); + clipBuffer.fill({ clipLimit, clipX, clipY, clipZ }); + + vkcv::DescriptorWrites clipWrites; + clipWrites.uniformBufferWrites = { + vkcv::BufferDescriptorWrite(0, clipBuffer.getHandle()) + }; + + core.writeDescriptorSet(clipDescriptorSet, clipWrites); + + float mouseX = -0.0f; + bool dragLimit = false; + + window.e_mouseMove.add([&](double x, double y) { + double cx = (x - window.getWidth() * 0.5); + double dx = cx / window.getWidth(); + + mouseX = 2.0f * static_cast<float>(dx); + + if (dragLimit) { + clipLimit = mouseX; + } + }); + + window.e_mouseButton.add([&](int button, int action, int mods) { + if ((std::abs(mouseX - clipLimit) < 0.1f) && (action == GLFW_PRESS)) { + dragLimit = true; + } else { + dragLimit = false; + } + }); + + const vkcv::VertexLayout sceneLayout(bindings); + + const auto& material0 = scene.getMaterial(0); + + const vkcv::GraphicsPipelineConfig scenePipelineDefinition{ + sceneShaderProgram, + UINT32_MAX, + UINT32_MAX, + scenePass, + {sceneLayout}, + { material0.getDescriptorSetLayout(), clipDescriptorSetLayout }, + true + }; + vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition); + + if (!scenePipeline) { + std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; + return EXIT_FAILURE; + } + + auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); + + vkcv::ImageHandle depthBuffer = core.createImage( + vk::Format::eD32Sfloat, + swapchainExtent.width, + swapchainExtent.height + ).getHandle(); + + const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); + + auto start = std::chrono::system_clock::now(); + while (vkcv::Window::hasOpenWindow()) { + vkcv::Window::pollEvents(); + + if(window.getHeight() == 0 || window.getWidth() == 0) + continue; + + uint32_t swapchainWidth, swapchainHeight; + if (!core.beginFrame(swapchainWidth, swapchainHeight,windowHandle)) { + continue; + } + + if ((swapchainWidth != swapchainExtent.width) || ((swapchainHeight != swapchainExtent.height))) { + depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle(); + + swapchainExtent.width = swapchainWidth; + swapchainExtent.height = swapchainHeight; + } + + auto end = std::chrono::system_clock::now(); + auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start); + + start = end; + cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); + + clipBuffer.fill({ clipLimit, clipX, clipY, clipZ }); + + const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; + auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); + + auto recordMesh = [&](const glm::mat4& MVP, const glm::mat4& M, + vkcv::PushConstants &pushConstants, + vkcv::DrawcallInfo& drawcallInfo) { + pushConstants.appendDrawcall(MVP); + drawcallInfo.descriptorSets.push_back( + vkcv::DescriptorSetUsage(1, clipDescriptorSet) + ); + }; + + scene.recordDrawcalls(cmdStream, + cameraManager.getActiveCamera(), + scenePass, + scenePipeline, + sizeof(glm::mat4), + recordMesh, + renderTargets, + windowHandle); + + core.prepareSwapchainImageForPresent(cmdStream); + core.submitCommandStream(cmdStream); + + auto stop = std::chrono::system_clock::now(); + auto kektime = std::chrono::duration_cast<std::chrono::microseconds>(stop - start); + + gui.beginGUI(); + + ImGui::Begin("Settings"); + ImGui::SliderFloat("Clip X", &clipX, -1.0f, 1.0f); + ImGui::SliderFloat("Clip Y", &clipY, -1.0f, 1.0f); + ImGui::SliderFloat("Clip Z", &clipZ, -1.0f, 1.0f); + ImGui::Text("Mesh by HannahNewey (https://sketchfab.com/HannahNewey)"); + ImGui::End(); + + gui.endGUI(); + + core.endFrame(windowHandle); + } + + return 0; +}