comparison semiconginev2/gltf.nim @ 1249:d83726af7abb

did: first triangles getting loaded from gltf
author sam <sam@basx.dev>
date Thu, 25 Jul 2024 22:41:24 +0700
parents 317bb5a73606
children 9ceb509af5ea
comparison
equal deleted inserted replaced
1248:317bb5a73606 1249:d83726af7abb
139 139
140 if bufferView.hasKey("byteStride"): 140 if bufferView.hasKey("byteStride"):
141 raise newException(Exception, "Unsupported feature: byteStride in buffer view") 141 raise newException(Exception, "Unsupported feature: byteStride in buffer view")
142 copyMem(dstPointer, addr mainBuffer[bufferOffset], result.len) 142 copyMem(dstPointer, addr mainBuffer[bufferOffset], result.len)
143 143
144 proc componentTypeId(t: typedesc): int =
145 if t is int8: return 5120
146 elif t is uint8: return 5121
147 elif t is int16: return 5122
148 elif t is uint16: return 5123
149 elif t is uint32: return 5125
150 elif t is float32: return 5126
151
144 proc getAccessorData[T](root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): seq[T] = 152 proc getAccessorData[T](root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): seq[T] =
153 let componentType = accessor["componentType"].getInt()
154 let itemType = accessor["type"].getStr()
155
156 when T is TVec or T is TMat:
157 assert componentTypeId(elementType(default(T))) == componentType, name(T) & " != " & $componentType
158 else:
159 assert componentTypeId(T) == componentType, name(T) & " != " & $componentType
160
161 when T is TVec:
162 when len(default(T)) == 2: assert itemType == "VEC2"
163 elif len(default(T)) == 3: assert itemType == "VEC3"
164 elif len(default(T)) == 4: assert itemType == "VEC4"
165 elif T is TMat:
166 when T is Mat2: assert itemType == "MAT2"
167 elif T is Mat3: assert itemType == "MAT3"
168 elif T is Mat4: assert itemType == "MAT4"
169 else:
170 assert itemType == "SCALAR"
171
145 result.setLen(accessor["count"].getInt()) 172 result.setLen(accessor["count"].getInt())
146 173
147 let bufferView = root["bufferViews"][accessor["bufferView"].getInt()] 174 let bufferView = root["bufferViews"][accessor["bufferView"].getInt()]
148 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" 175 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported"
149 176
156 var dstPointer = result.ToCPointer() 183 var dstPointer = result.ToCPointer()
157 184
158 if bufferView.hasKey("byteStride"): 185 if bufferView.hasKey("byteStride"):
159 warn "Congratulations, you try to test a feature (loading buffer data with stride attributes) that we have no idea where it is used and how it can be tested (need a coresponding *.glb file)." 186 warn "Congratulations, you try to test a feature (loading buffer data with stride attributes) that we have no idea where it is used and how it can be tested (need a coresponding *.glb file)."
160 # we don't support stride, have to convert stuff here... does this even work? 187 # we don't support stride, have to convert stuff here... does this even work?
161 for i in 0 ..< int(result.len): 188 for i in 0 ..< result.len:
162 copyMem(dstPointer, addr mainBuffer[bufferOffset + i * bufferView["byteStride"].getInt()], result.len * sizeof(T)) 189 copyMem(dstPointer, addr mainBuffer[bufferOffset + i * bufferView["byteStride"].getInt()], sizeof(T))
163 dstPointer = cast[typeof(dstPointer)](cast[uint](dstPointer) + (result.len * sizeof(T)).uint) 190 dstPointer = cast[typeof(dstPointer)](cast[uint](dstPointer) + sizeof(T).uint)
164 else: 191 else:
165 copyMem(dstPointer, addr mainBuffer[bufferOffset], length) 192 copyMem(dstPointer, addr mainBuffer[bufferOffset], length)
166 193
167 proc loadTexture(root: JsonNode, textureNode: JsonNode, mainBuffer: seq[uint8]): Image[BGRA] = 194 proc loadTexture(root: JsonNode, textureNode: JsonNode, mainBuffer: seq[uint8]): Image[BGRA] =
168 195
191 NewVec4f(node[0].getFloat(), node[1].getFloat(), node[2].getFloat(), node[3].getFloat()) 218 NewVec4f(node[0].getFloat(), node[1].getFloat(), node[2].getFloat(), node[3].getFloat())
192 219
193 proc loadMaterial[TMaterial]( 220 proc loadMaterial[TMaterial](
194 root: JsonNode, 221 root: JsonNode,
195 materialNode: JsonNode, 222 materialNode: JsonNode,
223 mapping: static MaterialAttributeNames,
196 mainBuffer: seq[uint8], 224 mainBuffer: seq[uint8],
197 mapping: static MaterialAttributeNames
198 ): TMaterial = 225 ): TMaterial =
199 result = TMaterial() 226 result = TMaterial()
200 227
201 let pbr = materialNode["pbrMetallicRoughness"] 228 let pbr = materialNode["pbrMetallicRoughness"]
202 for name, value in fieldPairs(result): 229 for name, value in fieldPairs(result):
212 elif gltfAttribute in ["metallicFactor", "roughnessFactor"]: 239 elif gltfAttribute in ["metallicFactor", "roughnessFactor"]:
213 value = pbr[gltfAttribute].getFloat() 240 value = pbr[gltfAttribute].getFloat()
214 else: 241 else:
215 {.error: "Unsupported gltf material attribute".} 242 {.error: "Unsupported gltf material attribute".}
216 243
217 proc loadPrimitive[TMesh](root: JsonNode, primitive: JsonNode, mapping: static MeshAttributeNames, mainBuffer: seq[uint8]): (TMesh, VkPrimitiveTopology) = 244 proc loadPrimitive[TMesh](
245 root: JsonNode,
246 primitive: JsonNode,
247 mapping: static MeshAttributeNames,
248 mainBuffer: seq[uint8]
249 ): (TMesh, VkPrimitiveTopology) =
218 result[0] = TMesh() 250 result[0] = TMesh()
219 result[1] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST 251 result[1] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
220 if primitive.hasKey("mode"): 252 if primitive.hasKey("mode"):
221 result[1] = PRIMITIVE_MODE_MAP[primitive["mode"].getInt()] 253 result[1] = PRIMITIVE_MODE_MAP[primitive["mode"].getInt()]
222 254
223 for name, value in fieldPairs(result[0]): 255 for resultFieldName, resultValue in fieldPairs(result[0]):
224 for gltfAttribute, mappedName in fieldPairs(mapping): 256 for gltfAttribute, mappedName in fieldPairs(mapping):
225 when gltfAttribute != "" and name == mappedName: 257 when typeof(mappedName) is string:
226 assert value is GPUData, "Attribute " & name & " must be of type GPUData" 258 when gltfAttribute != "" and resultFieldName == mappedName:
259 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData"
260 when gltfAttribute == "indices":
261 if primitive.hasKey(gltfAttribute):
262 let accessor = primitive[gltfAttribute].getInt()
263 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer)
264 elif gltfAttribute == "material":
265 if primitive.hasKey(gltfAttribute):
266 resultValue.data = typeof(resultValue.data)(primitive[gltfAttribute].getInt())
267 else:
268 if primitive["attributes"].hasKey(gltfAttribute):
269 let accessor = primitive["attributes"][gltfAttribute].getInt()
270 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer)
271 else:
272 var i = 0
273 for mappedIndexName in mappedName:
274 if gltfAttribute != "" and resultFieldName == mappedIndexName:
275 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData"
276 let gltfAttributeIndexed = gltfAttribute & "_" & $i
277 if primitive["attributes"].hasKey(gltfAttributeIndexed):
278 let accessor = primitive["attributes"][gltfAttributeIndexed].getInt()
279 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer)
280 inc i
227 #[ 281 #[
228 when gltfAttribute == "indices": 282 when gltfAttribute == "indices":
229 if primitive.hasKey(gltfAttribute): 283 if primitive.hasKey(gltfAttribute):
230 let accessor = primitive[gltfAttribute].getInt() 284 let accessor = primitive[gltfAttribute].getInt()
231 value.data = getAccessorData[elementType(value.data)](root, root["accessors"][accessor], mainBuffer) 285 value.data = getAccessorData[elementType(value.data)](root, root["accessors"][accessor], mainBuffer)
434 488
435 debug "Loading mesh: ", data.structuredContent.pretty 489 debug "Loading mesh: ", data.structuredContent.pretty
436 490
437 if "materials" in data.structuredContent: 491 if "materials" in data.structuredContent:
438 for materialnode in items(data.structuredContent["materials"]): 492 for materialnode in items(data.structuredContent["materials"]):
439 result.materials.add loadMaterial[TMaterial](data.structuredContent, materialnode, data.binaryBufferData, materialAttributesMapping) 493 result.materials.add loadMaterial[TMaterial](data.structuredContent, materialnode, materialAttributesMapping, data.binaryBufferData)
440 494
441 if "textures" in data.structuredContent: 495 if "textures" in data.structuredContent:
442 for texturenode in items(data.structuredContent["textures"]): 496 for texturenode in items(data.structuredContent["textures"]):
443 result.textures.add loadTexture(data.structuredContent, texturenode, data.binaryBufferData) 497 result.textures.add loadTexture(data.structuredContent, texturenode, data.binaryBufferData)
444 498
459 513
460 echo "Meshes:" 514 echo "Meshes:"
461 for m in result.meshes: 515 for m in result.meshes:
462 echo " Primitives:" 516 echo " Primitives:"
463 for p in m: 517 for p in m:
464 echo " ", p[1], ": ", p[0] 518 for field, value in fieldPairs(p[0]):
519 if typeof(value) is GPUData:
520 echo " ", field, ": ", value.data.len
465 521
466 proc LoadMeshes*[TMesh, TMaterial]( 522 proc LoadMeshes*[TMesh, TMaterial](
467 path: string, 523 path: string,
468 meshAttributesMapping: static MeshAttributeNames, 524 meshAttributesMapping: static MeshAttributeNames,
469 materialAttributesMapping: static MaterialAttributeNames, 525 materialAttributesMapping: static MaterialAttributeNames,