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) |
