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