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) |
