Mercurial > games > semicongine
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: |