comparison semiconginev2/gltf.nim @ 1254:b0f4c8ccd49a

did: stuff to test gltf importer
author sam <sam@basx.dev>
date Sat, 27 Jul 2024 20:47:54 +0700
parents c4f98eb4bb05
children 2b5ca798f6d6
comparison
equal deleted inserted replaced
1253:c4f98eb4bb05 1254:b0f4c8ccd49a
72 4: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 72 4: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
73 5: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 73 5: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
74 6: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, 74 6: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
75 ] 75 ]
76 76
77 proc getBufferViewData(bufferView: JsonNode, mainBuffer: seq[uint8], baseBufferOffset = 0): seq[uint8] = 77 proc getBufferViewData(bufferView: JsonNode, mainBuffer: seq[uint8],
78 baseBufferOffset = 0): seq[uint8] =
78 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" 79 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported"
79 80
80 result = newSeq[uint8](bufferView["byteLength"].getInt()) 81 result = newSeq[uint8](bufferView["byteLength"].getInt())
81 let bufferOffset = bufferView["byteOffset"].getInt() + baseBufferOffset 82 let bufferOffset = bufferView["byteOffset"].getInt() + baseBufferOffset
82 var dstPointer = addr result[0] 83 var dstPointer = addr result[0]
91 elif t is int16: return 5122 92 elif t is int16: return 5122
92 elif t is uint16: return 5123 93 elif t is uint16: return 5123
93 elif t is uint32: return 5125 94 elif t is uint32: return 5125
94 elif t is float32: return 5126 95 elif t is float32: return 5126
95 96
96 proc getAccessorData[T](root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): seq[T] = 97 proc getAccessorData[T](root: JsonNode, accessor: JsonNode, mainBuffer: seq[
98 uint8]): seq[T] =
97 let componentType = accessor["componentType"].getInt() 99 let componentType = accessor["componentType"].getInt()
98 let itemType = accessor["type"].getStr() 100 let itemType = accessor["type"].getStr()
99 101
100 when T is TVec or T is TMat: 102 when T is TVec or T is TMat:
101 assert componentTypeId(elementType(default(T))) == componentType, name(T) & " != " & $componentType 103 assert componentTypeId(elementType(default(T))) == componentType, name(T) &
104 " != " & $componentType
102 else: 105 else:
103 assert componentTypeId(T) == componentType, name(T) & " != " & $componentType 106 assert componentTypeId(T) == componentType, name(T) & " != " & $componentType
104 107
105 when T is TVec: 108 when T is TVec:
106 when len(default(T)) == 2: assert itemType == "VEC2" 109 when len(default(T)) == 2: assert itemType == "VEC2"
119 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" 122 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported"
120 123
121 if accessor.hasKey("sparse"): 124 if accessor.hasKey("sparse"):
122 raise newException(Exception, "Sparce accessors are currently not supported") 125 raise newException(Exception, "Sparce accessors are currently not supported")
123 126
124 let accessorOffset = if accessor.hasKey("byteOffset"): accessor["byteOffset"].getInt() else: 0 127 let accessorOffset = if accessor.hasKey("byteOffset"): accessor[
128 "byteOffset"].getInt() else: 0
125 let length = bufferView["byteLength"].getInt() 129 let length = bufferView["byteLength"].getInt()
126 let bufferOffset = bufferView["byteOffset"].getInt() + accessorOffset 130 let bufferOffset = bufferView["byteOffset"].getInt() + accessorOffset
127 var dstPointer = result.ToCPointer() 131 var dstPointer = result.ToCPointer()
128 132
129 if bufferView.hasKey("byteStride"): 133 if bufferView.hasKey("byteStride"):
130 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)." 134 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)."
131 # we don't support stride, have to convert stuff here... does this even work? 135 # we don't support stride, have to convert stuff here... does this even work?
132 for i in 0 ..< result.len: 136 for i in 0 ..< result.len:
133 copyMem(dstPointer, addr mainBuffer[bufferOffset + i * bufferView["byteStride"].getInt()], sizeof(T)) 137 copyMem(dstPointer, addr mainBuffer[bufferOffset + i * bufferView[
138 "byteStride"].getInt()], sizeof(T))
134 dstPointer = cast[typeof(dstPointer)](cast[uint](dstPointer) + sizeof(T).uint) 139 dstPointer = cast[typeof(dstPointer)](cast[uint](dstPointer) + sizeof(T).uint)
135 else: 140 else:
136 copyMem(dstPointer, addr mainBuffer[bufferOffset], length) 141 copyMem(dstPointer, addr mainBuffer[bufferOffset], length)
137 142
138 proc loadTexture(root: JsonNode, textureNode: JsonNode, mainBuffer: seq[uint8]): Image[BGRA] = 143 proc loadTexture(root: JsonNode, textureNode: JsonNode, mainBuffer: seq[
144 uint8]): Image[BGRA] =
139 145
140 let imageIndex = textureNode["source"].getInt() 146 let imageIndex = textureNode["source"].getInt()
141 147
142 if root["images"][imageIndex].hasKey("uri"): 148 if root["images"][imageIndex].hasKey("uri"):
143 raise newException(Exception, "Unsupported feature: Cannot load images from external files") 149 raise newException(Exception, "Unsupported feature: Cannot load images from external files")
144 let imageType = root["images"][imageIndex]["mimeType"].getStr() 150 let imageType = root["images"][imageIndex]["mimeType"].getStr()
145 assert imageType == "image/png", "glTF loader currently only supports PNG" 151 assert imageType == "image/png", "glTF loader currently only supports PNG"
146 152
147 let bufferView = root["bufferViews"][root["images"][imageIndex]["bufferView"].getInt()] 153 let bufferView = root["bufferViews"][root["images"][imageIndex][
154 "bufferView"].getInt()]
148 result = LoadImageData[BGRA](getBufferViewData(bufferView, mainBuffer)) 155 result = LoadImageData[BGRA](getBufferViewData(bufferView, mainBuffer))
149 156
150 if textureNode.hasKey("sampler"): 157 if textureNode.hasKey("sampler"):
151 let sampler = root["samplers"][textureNode["sampler"].getInt()] 158 let sampler = root["samplers"][textureNode["sampler"].getInt()]
152 if sampler.hasKey("magFilter"): 159 if sampler.hasKey("magFilter"):
153 result.magInterpolation = SAMPLER_FILTER_MODE_MAP[sampler["magFilter"].getInt()] 160 result.magInterpolation = SAMPLER_FILTER_MODE_MAP[sampler[
161 "magFilter"].getInt()]
154 if sampler.hasKey("minFilter"): 162 if sampler.hasKey("minFilter"):
155 result.minInterpolation = SAMPLER_FILTER_MODE_MAP[sampler["minFilter"].getInt()] 163 result.minInterpolation = SAMPLER_FILTER_MODE_MAP[sampler[
164 "minFilter"].getInt()]
156 if sampler.hasKey("wrapS"): 165 if sampler.hasKey("wrapS"):
157 result.wrapU = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()] 166 result.wrapU = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()]
158 if sampler.hasKey("wrapT"): 167 if sampler.hasKey("wrapT"):
159 result.wrapV = SAMPLER_WRAP_MODE_MAP[sampler["wrapT"].getInt()] 168 result.wrapV = SAMPLER_WRAP_MODE_MAP[sampler["wrapT"].getInt()]
160 169
161 proc getVec4f(node: JsonNode): Vec4f = 170 proc getVec4f(node: JsonNode): Vec4f =
162 NewVec4f(node[0].getFloat(), node[1].getFloat(), node[2].getFloat(), node[3].getFloat()) 171 NewVec4f(node[0].getFloat(), node[1].getFloat(), node[2].getFloat(), node[
172 3].getFloat())
163 173
164 proc loadMaterial[TMaterial]( 174 proc loadMaterial[TMaterial](
165 root: JsonNode, 175 root: JsonNode,
166 materialNode: JsonNode, 176 materialNode: JsonNode,
167 mapping: static MaterialAttributeNames, 177 mapping: static MaterialAttributeNames,
202 when gltfAttribute != "" and resultFieldName == mappedName: 212 when gltfAttribute != "" and resultFieldName == mappedName:
203 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData" 213 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData"
204 when gltfAttribute == "indices": 214 when gltfAttribute == "indices":
205 if primitive.hasKey(gltfAttribute): 215 if primitive.hasKey(gltfAttribute):
206 let accessor = primitive[gltfAttribute].getInt() 216 let accessor = primitive[gltfAttribute].getInt()
207 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer) 217 resultValue.data = getAccessorData[elementType(resultValue.data)](
218 root, root["accessors"][accessor], mainBuffer)
208 elif gltfAttribute == "material": 219 elif gltfAttribute == "material":
209 if primitive.hasKey(gltfAttribute): 220 if primitive.hasKey(gltfAttribute):
210 resultValue.data = typeof(resultValue.data)(primitive[gltfAttribute].getInt()) 221 resultValue.data = typeof(resultValue.data)(primitive[
222 gltfAttribute].getInt())
211 else: 223 else:
212 if primitive["attributes"].hasKey(gltfAttribute): 224 if primitive["attributes"].hasKey(gltfAttribute):
213 let accessor = primitive["attributes"][gltfAttribute].getInt() 225 let accessor = primitive["attributes"][gltfAttribute].getInt()
214 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer) 226 resultValue.data = getAccessorData[elementType(resultValue.data)](
227 root, root["accessors"][accessor], mainBuffer)
215 else: 228 else:
216 var i = 0 229 var i = 0
217 for mappedIndexName in mappedName: 230 for mappedIndexName in mappedName:
218 if gltfAttribute != "" and resultFieldName == mappedIndexName: 231 if gltfAttribute != "" and resultFieldName == mappedIndexName:
219 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData" 232 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData"
220 let gltfAttributeIndexed = gltfAttribute & "_" & $i 233 let gltfAttributeIndexed = gltfAttribute & "_" & $i
221 if primitive["attributes"].hasKey(gltfAttributeIndexed): 234 if primitive["attributes"].hasKey(gltfAttributeIndexed):
222 let accessor = primitive["attributes"][gltfAttributeIndexed].getInt() 235 let accessor = primitive["attributes"][
223 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer) 236 gltfAttributeIndexed].getInt()
237 resultValue.data = getAccessorData[elementType(resultValue.data)](
238 root, root["accessors"][accessor], mainBuffer)
224 inc i 239 inc i
225 240
226 proc loadNode(node: JsonNode): GltfNode = 241 proc loadNode(node: JsonNode): GltfNode =
227 result = GltfNode() 242 result = GltfNode()
228 if "mesh" in node: 243 if "mesh" in node:
280 data.structuredContent = parseJson(stream.readStr(int(chunkLength))) 295 data.structuredContent = parseJson(stream.readStr(int(chunkLength)))
281 296
282 chunkLength = stream.readUint32() 297 chunkLength = stream.readUint32()
283 assert stream.readUint32() == BINARY_CHUNK 298 assert stream.readUint32() == BINARY_CHUNK
284 data.binaryBufferData.setLen(chunkLength) 299 data.binaryBufferData.setLen(chunkLength)
285 assert stream.readData(addr data.binaryBufferData[0], int(chunkLength)) == int(chunkLength) 300 assert stream.readData(addr data.binaryBufferData[0], int(chunkLength)) ==
301 int(chunkLength)
286 302
287 # check that the refered buffer is the same as the binary chunk 303 # check that the refered buffer is the same as the binary chunk
288 # external binary buffers are not supported 304 # external binary buffers are not supported
289 assert data.structuredContent["buffers"].len == 1 305 assert data.structuredContent["buffers"].len == 1
290 assert not data.structuredContent["buffers"][0].hasKey("uri") 306 assert not data.structuredContent["buffers"][0].hasKey("uri")
291 let bufferLenDiff = int(chunkLength) - data.structuredContent["buffers"][0]["byteLength"].getInt() 307 let bufferLenDiff = int(chunkLength) - data.structuredContent["buffers"][0][
308 "byteLength"].getInt()
292 assert 0 <= bufferLenDiff and bufferLenDiff <= 3 # binary buffer may be aligned to 4 bytes 309 assert 0 <= bufferLenDiff and bufferLenDiff <= 3 # binary buffer may be aligned to 4 bytes
293 310
294 debug "Loading mesh: ", data.structuredContent.pretty 311 debug "Loading mesh: ", data.structuredContent.pretty
295 312
296 if "materials" in data.structuredContent: 313 if "materials" in data.structuredContent:
297 for materialnode in items(data.structuredContent["materials"]): 314 for materialnode in items(data.structuredContent["materials"]):
298 result.materials.add loadMaterial[TMaterial](data.structuredContent, materialnode, materialAttributesMapping, data.binaryBufferData) 315 result.materials.add loadMaterial[TMaterial](data.structuredContent,
316 materialnode, materialAttributesMapping, data.binaryBufferData)
299 317
300 if "textures" in data.structuredContent: 318 if "textures" in data.structuredContent:
301 for texturenode in items(data.structuredContent["textures"]): 319 for texturenode in items(data.structuredContent["textures"]):
302 result.textures.add loadTexture(data.structuredContent, texturenode, data.binaryBufferData) 320 result.textures.add loadTexture(data.structuredContent, texturenode,
321 data.binaryBufferData)
303 322
304 if "meshes" in data.structuredContent: 323 if "meshes" in data.structuredContent:
305 for mesh in items(data.structuredContent["meshes"]): 324 for mesh in items(data.structuredContent["meshes"]):
306 var primitives: seq[(TMesh, VkPrimitiveTopology)] 325 var primitives: seq[(TMesh, VkPrimitiveTopology)]
307 for primitive in items(mesh["primitives"]): 326 for primitive in items(mesh["primitives"]):
308 primitives.add loadPrimitive[TMesh](data.structuredContent, primitive, meshAttributesMapping, data.binaryBufferData) 327 primitives.add loadPrimitive[TMesh](data.structuredContent, primitive,
328 meshAttributesMapping, data.binaryBufferData)
309 result.meshes.add primitives 329 result.meshes.add primitives
310 330
311 if "nodes" in data.structuredContent: 331 if "nodes" in data.structuredContent:
312 for node in items(data.structuredContent["nodes"]): 332 for node in items(data.structuredContent["nodes"]):
313 result.nodes.add loadNode(node) 333 result.nodes.add loadNode(node)