Mercurial > games > semicongine
comparison semiconginev2/gltf.nim @ 1245:d594b1d07d49
add: initial changes for glTF loader
author | sam <sam@basx.dev> |
---|---|
date | Wed, 24 Jul 2024 00:26:57 +0700 |
parents | 7e55fde39ca8 |
children | c15770761865 |
comparison
equal
deleted
inserted
replaced
1244:3ef5764504ad | 1245:d594b1d07d49 |
---|---|
1 type | 1 type |
2 GLTFMesh[TMesh, TMaterial] = object | |
3 scenes: seq[int] | |
4 nodes: seq[int] | |
5 meshes: seq[TMesh] | |
6 materials: seq[TMaterial] | |
2 glTFHeader = object | 7 glTFHeader = object |
3 magic: uint32 | 8 magic: uint32 |
4 version: uint32 | 9 version: uint32 |
5 length: uint32 | 10 length: uint32 |
6 glTFData = object | 11 glTFData = object |
7 structuredContent: JsonNode | 12 structuredContent: JsonNode |
8 binaryBufferData: seq[uint8] | 13 binaryBufferData: seq[uint8] |
9 | 14 |
15 MaterialAttributeNames = object | |
16 baseColorFactor: string | |
17 emissiveFactor: string | |
18 metallicFactor: string | |
19 roughnessFactor: string | |
20 baseColorTexture: string | |
21 metallicRoughnessTexture: string | |
22 normalTexture: string | |
23 occlusionTexture: string | |
24 emissiveTexture: string | |
25 | |
10 const | 26 const |
27 HEADER_MAGIC = 0x46546C67 | |
11 JSON_CHUNK = 0x4E4F534A | 28 JSON_CHUNK = 0x4E4F534A |
12 BINARY_CHUNK = 0x004E4942 | 29 BINARY_CHUNK = 0x004E4942 |
13 ACCESSOR_TYPE_MAP = { | 30 ACCESSOR_TYPE_MAP = { |
14 5120: Int8, | 31 5120: Int8, |
15 5121: UInt8, | 32 5121: UInt8, |
148 result.sampler.wrapModeS = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] | 165 result.sampler.wrapModeS = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] |
149 if sampler.hasKey("wrapT"): | 166 if sampler.hasKey("wrapT"): |
150 result.sampler.wrapModeT = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] | 167 result.sampler.wrapModeT = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] |
151 | 168 |
152 | 169 |
153 proc loadMaterial(root: JsonNode, materialNode: JsonNode, defaultMaterial: MaterialType, mainBuffer: seq[uint8]): MaterialData = | 170 proc loadMaterial[TMaterial]( |
171 root: JsonNode, | |
172 materialNode: JsonNode, | |
173 mainBuffer: seq[uint8], | |
174 mapping: MaterialAttributeNames | |
175 ): TMaterial = | |
154 let pbr = materialNode["pbrMetallicRoughness"] | 176 let pbr = materialNode["pbrMetallicRoughness"] |
155 var attributes: Table[string, DataList] | 177 for glName, glValue in fieldPairs(mapping): |
178 if glValue != "": | |
179 for name, value in fieldPairs(result): | |
180 when name == glName: | |
181 value = | |
182 | |
183 #[ | |
156 | 184 |
157 # color | 185 # color |
158 if defaultMaterial.attributes.contains("color"): | 186 if defaultMaterial.attributes.contains("color"): |
159 attributes["color"] = InitDataList(thetype = Vec4F32) | 187 attributes["color"] = InitDataList(thetype = Vec4F32) |
160 if pbr.hasKey(GLTF_MATERIAL_MAPPING["color"]): | 188 if pbr.hasKey(GLTF_MATERIAL_MAPPING["color"]): |
205 materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][1].getFloat(), | 233 materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][1].getFloat(), |
206 materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][2].getFloat(), | 234 materialNode[GLTF_MATERIAL_MAPPING["emissiveColor"]][2].getFloat(), |
207 )] | 235 )] |
208 else: | 236 else: |
209 attributes["emissiveColor"] = @[NewVec3f(1'f32, 1'f32, 1'f32)] | 237 attributes["emissiveColor"] = @[NewVec3f(1'f32, 1'f32, 1'f32)] |
210 | 238 ]# |
211 result = InitMaterialData(theType = defaultMaterial, name = materialNode["name"].getStr(), attributes = attributes) | 239 |
212 | 240 |
213 proc loadMesh(meshname: string, root: JsonNode, primitiveNode: JsonNode, materials: seq[MaterialData], mainBuffer: seq[uint8]): Mesh = | 241 proc loadMesh(meshname: string, root: JsonNode, primitiveNode: JsonNode, materials: seq[MaterialData], mainBuffer: seq[uint8]): Mesh = |
214 if primitiveNode.hasKey("mode") and primitiveNode["mode"].getInt() != 4: | 242 if primitiveNode.hasKey("mode") and primitiveNode["mode"].getInt() != 4: |
215 raise newException(Exception, "Currently only TRIANGLE mode is supported for geometry mode") | 243 raise newException(Exception, "Currently only TRIANGLE mode is supported for geometry mode") |
216 | 244 |
311 # children | 339 # children |
312 if node.hasKey("children"): | 340 if node.hasKey("children"): |
313 for childNode in node["children"]: | 341 for childNode in node["children"]: |
314 result.children.add loadNode(root, root["nodes"][childNode.getInt()], materials, mainBuffer) | 342 result.children.add loadNode(root, root["nodes"][childNode.getInt()], materials, mainBuffer) |
315 | 343 |
316 proc loadMeshTree(root: JsonNode, scenenode: JsonNode, materials: seq[MaterialData], mainBuffer: var seq[uint8]): MeshTree = | 344 proc loadScene(root: JsonNode, scenenode: JsonNode, materials: seq[MaterialData], mainBuffer: var seq[uint8]): MeshTree = |
317 result = MeshTree() | 345 result = MeshTree() |
318 for nodeId in scenenode["nodes"]: | 346 for nodeId in scenenode["nodes"]: |
319 result.children.add loadNode(root, root["nodes"][nodeId.getInt()], materials, mainBuffer) | 347 result.children.add loadNode(root, root["nodes"][nodeId.getInt()], materials, mainBuffer) |
320 # TODO: getting from gltf to vulkan system is still messed up somehow (i.e. not consistent for different files), see other TODO | 348 # TODO: getting from gltf to vulkan system is still messed up somehow (i.e. not consistent for different files), see other TODO |
321 # result.transform = Scale(1, -1, 1) | 349 # result.transform = Scale(1, -1, 1) |
322 result.updateTransforms() | 350 result.updateTransforms() |
323 | 351 |
324 | 352 |
325 proc ReadglTF*(stream: Stream, defaultMaterial: MaterialType): seq[MeshTree] = | 353 proc ReadglTF*[TMaterial, TMesh]( |
354 stream: Stream, | |
355 attributeNames: MaterialAttributeNames, | |
356 baseColorFactor = "", | |
357 emissiveFactor = "", | |
358 metallicFactor = "", | |
359 roughnessFactor = "", | |
360 baseColorTexture = "", | |
361 metallicRoughnessTexture = "", | |
362 normalTexture = "", | |
363 occlusionTexture = "", | |
364 emissiveTexture = "", | |
365 ): GLTFMesh[TMesh, TMaterial] = | |
366 let mapping = MaterialAttributeNames( | |
367 baseColorFactor: baseColorFactor | |
368 emissiveFactor: emissiveFactor | |
369 metallicFactor: metallicFactor | |
370 roughnessFactor: roughnessFactor | |
371 baseColorTexture: baseColorTexture | |
372 metallicRoughnessTexture: metallicRoughnessTexture | |
373 normalTexture: normalTexture | |
374 occlusionTexture: occlusionTexture | |
375 emissiveTexture: emissiveTexture | |
376 ) | |
326 var | 377 var |
327 header: glTFHeader | 378 header: glTFHeader |
328 data: glTFData | 379 data: glTFData |
329 | 380 |
330 for name, value in fieldPairs(header): | 381 for name, value in fieldPairs(header): |
331 stream.read(value) | 382 stream.read(value) |
332 | 383 |
333 assert header.magic == 0x46546C67 | 384 assert header.magic == HEADER_MAGIC |
334 assert header.version == 2 | 385 assert header.version == 2 |
335 | 386 |
336 var chunkLength = stream.readUint32() | 387 var chunkLength = stream.readUint32() |
337 assert stream.readUint32() == JSON_CHUNK | 388 assert stream.readUint32() == JSON_CHUNK |
338 data.structuredContent = parseJson(stream.readStr(int(chunkLength))) | 389 data.structuredContent = parseJson(stream.readStr(int(chunkLength))) |
351 | 402 |
352 debug "Loading mesh: ", data.structuredContent.pretty | 403 debug "Loading mesh: ", data.structuredContent.pretty |
353 | 404 |
354 var materials: seq[MaterialData] | 405 var materials: seq[MaterialData] |
355 for materialnode in data.structuredContent["materials"]: | 406 for materialnode in data.structuredContent["materials"]: |
356 materials.add data.structuredContent.loadMaterial(materialnode, defaultMaterial, data.binaryBufferData) | 407 result.materials.add loadMaterial[TMaterial](data.structuredContent, materialnode, data.binaryBufferData, mapping) |
357 | 408 |
358 for scenedata in data.structuredContent["scenes"]: | 409 for scenedata in data.structuredContent["scenes"]: |
359 result.add data.structuredContent.loadMeshTree(scenedata, materials, data.binaryBufferData) | 410 result.add data.structuredContent.loadScene(scenedata, materials, data.binaryBufferData) |