Mercurial > games > semicongine
changeset 1448:96753bec055c default tip
add: support for "name" and "extras" on gltf nodes
author | sam <sam@basx.dev> |
---|---|
date | Sun, 09 Mar 2025 22:59:34 +0700 |
parents | b17098eb052f |
children | |
files | semicongine/core/types.nim semicongine/gltf.nim tests/test_gltf.nim |
diffstat | 3 files changed, 83 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/core/types.nim Sat Mar 01 17:27:47 2025 +0700 +++ b/semicongine/core/types.nim Sun Mar 09 22:59:34 2025 +0700 @@ -479,48 +479,6 @@ # === steam === SteamUserStatsRef* = ptr object - # === glTF === - GltfNode* = object - children*: seq[int] - mesh*: int = -1 - transform*: Mat4 = Unit4 - - GltfData*[TMesh, TMaterial] = object - scenes*: seq[seq[int]] # each scene has a seq of node indices - nodes*: seq[GltfNode] # each node has a seq of mesh indices - meshes*: seq[seq[(TMesh, VkPrimitiveTopology)]] - materials*: seq[TMaterial] - textures*: seq[Image[BGRA]] - - MaterialAttributeNames* = object # pbr - baseColorTexture*: string - baseColorTextureUv*: string - baseColorFactor*: string - metallicRoughnessTexture*: string - metallicRoughnessTextureUv*: string - metallicFactor*: string - roughnessFactor*: string - - # other - normalTexture*: string - normalTextureUv*: string - occlusionTexture*: string - occlusionTextureUv*: string - emissiveTexture*: string - emissiveTextureUv*: string - emissiveFactor*: string - - MeshAttributeNames* = object - POSITION*: string - NORMAL*: string - TANGENT*: string - TEXCOORD*: seq[string] - COLOR*: seq[string] - JOINTS*: seq[string] - WEIGHTS*: seq[string] - indices*: string - material*: string - # === global engine object === EngineObj = object initialized*: bool @@ -568,6 +526,3 @@ proc `=copy`[MaxGlyphs: static int]( dest: var TextBuffer[MaxGlyphs], source: TextBuffer[MaxGlyphs] ) {.error.} - -proc `=copy`(dest: var GltfNode, source: GltfNode) {.error.} -proc `=copy`[S, T](dest: var GltfData[S, T], source: GltfData[S, T]) {.error.}
--- a/semicongine/gltf.nim Sat Mar 01 17:27:47 2025 +0700 +++ b/semicongine/gltf.nim Sun Mar 09 22:59:34 2025 +0700 @@ -10,6 +10,59 @@ import ./resources type + # === public === + GltfData*[TMesh, TMaterial] = object + scenes*: seq[seq[int]] # each scene has a seq of node indices + nodes*: seq[GltfNode] # each node has a seq of mesh indices + meshes*: seq[GltfMesh[TMesh]] + materials*: seq[TMaterial] + textures*: seq[Image[BGRA]] + + GltfNode* = object + name*: string + properties*: JsonNode + children*: seq[int] + mesh*: int = -1 + transform*: Mat4 = Unit4 + + GltfMesh*[TMesh] = object + primitives*: seq[GltfPrimitive[TMesh]] + + GltfPrimitive*[TMesh] = object + data*: TMesh + topology*: VkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST + material*: int + + MaterialAttributeNames* = object # pbr + baseColorTexture*: string + baseColorTextureUv*: string + baseColorFactor*: string + metallicRoughnessTexture*: string + metallicRoughnessTextureUv*: string + metallicFactor*: string + roughnessFactor*: string + + # other + normalTexture*: string + normalTextureUv*: string + occlusionTexture*: string + occlusionTextureUv*: string + emissiveTexture*: string + emissiveTextureUv*: string + emissiveFactor*: string + + MeshAttributeNames* = object + POSITION*: string + NORMAL*: string + TANGENT*: string + TEXCOORD*: seq[string] + COLOR*: seq[string] + JOINTS*: seq[string] + WEIGHTS*: seq[string] + indices*: string + material*: string + + # === internal === glTFHeader = object magic: uint32 version: uint32 @@ -19,6 +72,11 @@ structuredContent: JsonNode binaryBufferData: seq[uint8] +proc `=copy`[M](dest: var GltfPrimitive[M], source: GltfPrimitive[M]) {.error.} +proc `=copy`[M](dest: var GltfMesh[M], source: GltfMesh[M]) {.error.} +proc `=copy`(dest: var GltfNode, source: GltfNode) {.error.} +proc `=copy`[S, T](dest: var GltfData[S, T], source: GltfData[S, T]) {.error.} + proc `=copy`(dest: var glTFHeader, source: glTFHeader) {.error.} proc `=copy`(dest: var glTFData, source: glTFData) {.error.} @@ -212,16 +270,19 @@ primitive: JsonNode, mapping: static MeshAttributeNames, mainBuffer: seq[uint8], -): (TMesh, VkPrimitiveTopology) = - result[0] = TMesh() - result[1] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST +): GltfPrimitive[TMesh] = + result.data = TMesh() + if primitive.hasKey("mode"): - result[1] = PRIMITIVE_MODE_MAP[primitive["mode"].getInt()] + result.topology = PRIMITIVE_MODE_MAP[primitive["mode"].getInt()] + + if primitive.hasKey("material"): + result.material = primitive["material"].getInt() if primitive.hasKey("indices"): - assert mapping.indices != "", "Mesh requires indices" + doAssert mapping.indices != "", "Mesh requires indices" - for resultFieldName, resultValue in fieldPairs(result[0]): + for resultFieldName, resultValue in fieldPairs(result.data): for gltfAttribute, mappedName in fieldPairs(mapping): when typeof(mappedName) is seq: when resultFieldName in mappedName: @@ -260,6 +321,10 @@ proc loadNode(node: JsonNode): GltfNode = result = GltfNode() + if "name" in node: + result.name = node["name"].getStr() + if "properties" in node: + result.properties = node["properties"] if "mesh" in node: result.mesh = node["mesh"].getInt() if "children" in node: @@ -346,13 +411,13 @@ if "meshes" in data.structuredContent: for mesh in items(data.structuredContent["meshes"]): - var primitives: seq[(TMesh, VkPrimitiveTopology)] + var meshObj: GltfMesh[TMesh] for primitive in items(mesh["primitives"]): - primitives.add loadPrimitive[TMesh]( + meshObj.primitives.add loadPrimitive[TMesh]( data.structuredContent, primitive, meshAttributesMapping, data.binaryBufferData, ) - result.meshes.add primitives + result.meshes.add meshObj if "nodes" in data.structuredContent: for node in items(data.structuredContent["nodes"]):
--- a/tests/test_gltf.nim Sat Mar 01 17:27:47 2025 +0700 +++ b/tests/test_gltf.nim Sun Mar 09 22:59:34 2025 +0700 @@ -8,6 +8,7 @@ import ../semicongine/rendering import ../semicongine/loaders import ../semicongine/input +import ../semicongine/gltf proc test_gltf(time: float32, renderPass: RenderPass) = var renderdata = initRenderData() @@ -96,17 +97,12 @@ color: GPUArray[Vec4f, VertexBuffer] normal: GPUArray[Vec3f, VertexBuffer] indices: GPUArray[uint32, IndexBuffer] - material: int32 var gltfData = loadMeshes[Mesh, Material]( "town.glb", # "forest.glb", MeshAttributeNames( - POSITION: "position", - COLOR: @["color"], - NORMAL: "normal", - indices: "indices", - material: "material", + POSITION: "position", COLOR: @["color"], NORMAL: "normal", indices: "indices" ), MaterialAttributeNames( baseColorFactor: "color", @@ -130,11 +126,11 @@ for i in 0 ..< gltfData.materials.len: descriptors.data.materials[i] = asGPUValue(gltfData.materials[i], UniformBuffer) for mesh in mitems(gltfData.meshes): - for primitive in mitems(mesh): - primitive[0].color = asGPUArray( - newSeqWith(primitive[0].position.data.len, vec4(1, 1, 1, 1)), VertexBuffer + for primitive in mitems(mesh.primitives): + primitive.data.color = asGPUArray( + newSeqWith(primitive.data.position.data.len, vec4(1, 1, 1, 1)), VertexBuffer ) - renderdata.assignBuffers(primitive[0]) + renderdata.assignBuffers(primitive.data) renderdata.assignBuffers(descriptors) var pipeline = createPipeline(Shader(), renderPass = renderPass, cullMode = []) @@ -147,13 +143,13 @@ ) = let nodeTransform = gltfData.nodes[nodeId].transform * transform if gltfData.nodes[nodeId].mesh >= 0: - for primitive in gltfData.meshes[gltfData.nodes[nodeId].mesh].mitems: + for primitive in gltfData.meshes[gltfData.nodes[nodeId].mesh].primitives: renderWithPushConstant( commandbuffer = commandbuffer, pipeline = pipeline, - mesh = primitive[0], + mesh = primitive.data, pushConstant = - ObjectData(transform: nodeTransform, materialId: primitive[0].material), + ObjectData(transform: nodeTransform, materialId: primitive.material.int32), ) for childNode in gltfData.nodes[nodeId].children: drawNode(