comparison semiconginev2/gltf.nim @ 1255:2b5ca798f6d6

did: make example town loadable and renderable, yay!
author sam <sam@basx.dev>
date Sun, 28 Jul 2024 00:17:34 +0700
parents b0f4c8ccd49a
children 5442d0e9d8ff
comparison
equal deleted inserted replaced
1254:b0f4c8ccd49a 1255:2b5ca798f6d6
92 elif t is int16: return 5122 92 elif t is int16: return 5122
93 elif t is uint16: return 5123 93 elif t is uint16: return 5123
94 elif t is uint32: return 5125 94 elif t is uint32: return 5125
95 elif t is float32: return 5126 95 elif t is float32: return 5126
96 96
97 proc getAccessorData[T](root: JsonNode, accessor: JsonNode, mainBuffer: seq[ 97 proc componentTypeName(id: int): string =
98 uint8]): seq[T] = 98 if id == 5120: return int8.name
99 elif id == 5121: return uint8.name
100 elif id == 5122: return int16.name
101 elif id == 5123: return uint16.name
102 elif id == 5125: return uint32.name
103 elif id == 5126: return float32.name
104
105 proc getAccessorData[T](root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): seq[T] =
106 if accessor.hasKey("sparse"):
107 raise newException(Exception, "Sparce accessors are currently not supported")
108
99 let componentType = accessor["componentType"].getInt() 109 let componentType = accessor["componentType"].getInt()
100 let itemType = accessor["type"].getStr() 110 let itemType = accessor["type"].getStr()
101 111
102 when T is TVec or T is TMat: 112 when T is TVec or T is TMat:
103 assert componentTypeId(elementType(default(T))) == componentType, name(T) & 113 assert componentTypeId(elementType(default(T))) == componentType, "Requested type '" & name(elementType(default(T))) & $componentTypeId(elementType(default(T))) & "' but actual type is '" & componentTypeName(componentType) & "'"
104 " != " & $componentType
105 else: 114 else:
106 assert componentTypeId(T) == componentType, name(T) & " != " & $componentType 115 assert componentTypeId(T) == componentType, "Requested type '" & name(T) & "' but actual type is '" & componentTypeName(componentType) & "'"
107 116
108 when T is TVec: 117 when T is TVec:
109 when len(default(T)) == 2: assert itemType == "VEC2" 118 when len(default(T)) == 2: assert itemType == "VEC2"
110 elif len(default(T)) == 3: assert itemType == "VEC3" 119 elif len(default(T)) == 3: assert itemType == "VEC3"
111 elif len(default(T)) == 4: assert itemType == "VEC4" 120 elif len(default(T)) == 4: assert itemType == "VEC4"
118 127
119 result.setLen(accessor["count"].getInt()) 128 result.setLen(accessor["count"].getInt())
120 129
121 let bufferView = root["bufferViews"][accessor["bufferView"].getInt()] 130 let bufferView = root["bufferViews"][accessor["bufferView"].getInt()]
122 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported" 131 assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported"
123 132 let accessorOffset = if accessor.hasKey("byteOffset"): accessor["byteOffset"].getInt() else: 0
124 if accessor.hasKey("sparse"): 133 let bufferOffset = (if "byteOffset" in bufferView: bufferView["byteOffset"].getInt() else: 0) + accessorOffset
125 raise newException(Exception, "Sparce accessors are currently not supported")
126
127 let accessorOffset = if accessor.hasKey("byteOffset"): accessor[
128 "byteOffset"].getInt() else: 0
129 let length = bufferView["byteLength"].getInt()
130 let bufferOffset = bufferView["byteOffset"].getInt() + accessorOffset
131 var dstPointer = result.ToCPointer() 134 var dstPointer = result.ToCPointer()
132 135
133 if bufferView.hasKey("byteStride"): 136 if bufferView.hasKey("byteStride"):
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)." 137 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)."
135 # we don't support stride, have to convert stuff here... does this even work? 138 # we don't support stride, have to convert stuff here... does this even work?
136 for i in 0 ..< result.len: 139 for i in 0 ..< result.len:
137 copyMem(dstPointer, addr mainBuffer[bufferOffset + i * bufferView[ 140 copyMem(dstPointer, addr(mainBuffer[bufferOffset + i * bufferView["byteStride"].getInt()]), sizeof(T))
138 "byteStride"].getInt()], sizeof(T))
139 dstPointer = cast[typeof(dstPointer)](cast[uint](dstPointer) + sizeof(T).uint) 141 dstPointer = cast[typeof(dstPointer)](cast[uint](dstPointer) + sizeof(T).uint)
140 else: 142 else:
141 copyMem(dstPointer, addr mainBuffer[bufferOffset], length) 143 copyMem(dstPointer, addr(mainBuffer[bufferOffset]), result.len * sizeof(T))
142 144
143 proc loadTexture(root: JsonNode, textureNode: JsonNode, mainBuffer: seq[ 145 proc loadTexture(root: JsonNode, textureNode: JsonNode, mainBuffer: seq[
144 uint8]): Image[BGRA] = 146 uint8]): Image[BGRA] =
145 147
146 let imageIndex = textureNode["source"].getInt() 148 let imageIndex = textureNode["source"].getInt()
204 result[0] = TMesh() 206 result[0] = TMesh()
205 result[1] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST 207 result[1] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
206 if primitive.hasKey("mode"): 208 if primitive.hasKey("mode"):
207 result[1] = PRIMITIVE_MODE_MAP[primitive["mode"].getInt()] 209 result[1] = PRIMITIVE_MODE_MAP[primitive["mode"].getInt()]
208 210
211 if primitive.hasKey("indices"):
212 assert mapping.indices != "", "Mesh requires indices"
213
209 for resultFieldName, resultValue in fieldPairs(result[0]): 214 for resultFieldName, resultValue in fieldPairs(result[0]):
210 for gltfAttribute, mappedName in fieldPairs(mapping): 215 for gltfAttribute, mappedName in fieldPairs(mapping):
211 when typeof(mappedName) is string: 216 when typeof(mappedName) is seq:
212 when gltfAttribute != "" and resultFieldName == mappedName: 217 when resultFieldName in mappedName:
213 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData" 218 var i = 0
219 for mappedIndexName in mappedName:
220 if gltfAttribute != "" and resultFieldName == mappedIndexName:
221 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData"
222 let gltfAttributeIndexed = gltfAttribute & "_" & $i
223 if primitive["attributes"].hasKey(gltfAttributeIndexed):
224 let accessor = primitive["attributes"][gltfAttributeIndexed].getInt()
225 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer)
226 inc i
227 elif typeof(mappedName) is string:
228 when resultFieldName == mappedName:
229 assert resultValue is GPUData or gltfAttribute == "material", "Attribute " & resultFieldName & " must be of type GPUData"
214 when gltfAttribute == "indices": 230 when gltfAttribute == "indices":
215 if primitive.hasKey(gltfAttribute): 231 if primitive.hasKey(gltfAttribute):
216 let accessor = primitive[gltfAttribute].getInt() 232 let accessor = primitive[gltfAttribute].getInt()
217 resultValue.data = getAccessorData[elementType(resultValue.data)]( 233 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer)
218 root, root["accessors"][accessor], mainBuffer)
219 elif gltfAttribute == "material": 234 elif gltfAttribute == "material":
220 if primitive.hasKey(gltfAttribute): 235 if primitive.hasKey(gltfAttribute): # assuming here that materials IDs are a normal field on the mesh, not GPUData
221 resultValue.data = typeof(resultValue.data)(primitive[ 236 resultValue = typeof(resultValue)(primitive[gltfAttribute].getInt())
222 gltfAttribute].getInt())
223 else: 237 else:
224 if primitive["attributes"].hasKey(gltfAttribute): 238 if primitive["attributes"].hasKey(gltfAttribute):
225 let accessor = primitive["attributes"][gltfAttribute].getInt() 239 let accessor = primitive["attributes"][gltfAttribute].getInt()
226 resultValue.data = getAccessorData[elementType(resultValue.data)]( 240 resultValue.data = getAccessorData[elementType(resultValue.data)](root, root["accessors"][accessor], mainBuffer)
227 root, root["accessors"][accessor], mainBuffer)
228 else:
229 var i = 0
230 for mappedIndexName in mappedName:
231 if gltfAttribute != "" and resultFieldName == mappedIndexName:
232 assert resultValue is GPUData, "Attribute " & resultFieldName & " must be of type GPUData"
233 let gltfAttributeIndexed = gltfAttribute & "_" & $i
234 if primitive["attributes"].hasKey(gltfAttributeIndexed):
235 let accessor = primitive["attributes"][
236 gltfAttributeIndexed].getInt()
237 resultValue.data = getAccessorData[elementType(resultValue.data)](
238 root, root["accessors"][accessor], mainBuffer)
239 inc i
240 241
241 proc loadNode(node: JsonNode): GltfNode = 242 proc loadNode(node: JsonNode): GltfNode =
242 result = GltfNode() 243 result = GltfNode()
243 if "mesh" in node: 244 if "mesh" in node:
244 result.mesh = node["mesh"].getInt() 245 result.mesh = node["mesh"].getInt()
302 303
303 # check that the refered buffer is the same as the binary chunk 304 # check that the refered buffer is the same as the binary chunk
304 # external binary buffers are not supported 305 # external binary buffers are not supported
305 assert data.structuredContent["buffers"].len == 1 306 assert data.structuredContent["buffers"].len == 1
306 assert not data.structuredContent["buffers"][0].hasKey("uri") 307 assert not data.structuredContent["buffers"][0].hasKey("uri")
307 let bufferLenDiff = int(chunkLength) - data.structuredContent["buffers"][0][ 308 let bufferLenDiff = int(chunkLength) - data.structuredContent["buffers"][0]["byteLength"].getInt()
308 "byteLength"].getInt()
309 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
310 310
311 debug "Loading mesh: ", data.structuredContent.pretty 311 debug "Loading mesh: ", data.structuredContent.pretty
312 312
313 if "materials" in data.structuredContent: 313 if "materials" in data.structuredContent: