Gltf parsing and rendering
This commit is contained in:
5
.ignore
Normal file
5
.ignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/data/**.png
|
||||||
|
/data/**.bin
|
||||||
|
/data/**.blend
|
||||||
|
/data/**.blend1
|
||||||
|
/.git
|
BIN
data/cubemap.bin
Normal file
BIN
data/cubemap.bin
Normal file
Binary file not shown.
142
data/cubemap.gltf
Normal file
142
data/cubemap.gltf
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v4.5.48",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"extensionsUsed":[
|
||||||
|
"KHR_materials_unlit"
|
||||||
|
],
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"cubemap"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"extensions":{
|
||||||
|
"KHR_materials_unlit":{}
|
||||||
|
},
|
||||||
|
"name":"Material_0",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0,
|
||||||
|
"roughnessFactor":0.9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Cube.001",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"NORMAL":1,
|
||||||
|
"TEXCOORD_0":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"cubemap.png",
|
||||||
|
"uri":"cubemap.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"max":[
|
||||||
|
0.4999999701976776,
|
||||||
|
0.5,
|
||||||
|
0.5
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-0.4999999701976776,
|
||||||
|
-0.5,
|
||||||
|
-0.5
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":36,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":288,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":288,
|
||||||
|
"byteOffset":288,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":192,
|
||||||
|
"byteOffset":576,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":72,
|
||||||
|
"byteOffset":768,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9729,
|
||||||
|
"minFilter":9987
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":840,
|
||||||
|
"uri":"cubemap.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
data/hand.bin
Normal file
BIN
data/hand.bin
Normal file
Binary file not shown.
144
data/hand.gltf
Normal file
144
data/hand.gltf
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v4.5.48",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"extensionsUsed":[
|
||||||
|
"KHR_materials_unlit"
|
||||||
|
],
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"hand"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"alphaMode":"BLEND",
|
||||||
|
"doubleSided":true,
|
||||||
|
"extensions":{
|
||||||
|
"KHR_materials_unlit":{}
|
||||||
|
},
|
||||||
|
"name":"Material",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0,
|
||||||
|
"roughnessFactor":0.9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Plane.001",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"NORMAL":1,
|
||||||
|
"TEXCOORD_0":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"hand.png",
|
||||||
|
"uri":"hand.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":4,
|
||||||
|
"max":[
|
||||||
|
0.5,
|
||||||
|
0.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-0.5,
|
||||||
|
-0.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":4,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":4,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":6,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":48,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":48,
|
||||||
|
"byteOffset":48,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":32,
|
||||||
|
"byteOffset":96,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":12,
|
||||||
|
"byteOffset":128,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9728,
|
||||||
|
"minFilter":9984
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":140,
|
||||||
|
"uri":"hand.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
data/yakuza/card.bin
Normal file
BIN
data/yakuza/card.bin
Normal file
Binary file not shown.
144
data/yakuza/card.gltf
Normal file
144
data/yakuza/card.gltf
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v4.5.48",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"extensionsUsed":[
|
||||||
|
"KHR_materials_unlit"
|
||||||
|
],
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"card"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"alphaMode":"BLEND",
|
||||||
|
"doubleSided":true,
|
||||||
|
"extensions":{
|
||||||
|
"KHR_materials_unlit":{}
|
||||||
|
},
|
||||||
|
"name":"Material",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0,
|
||||||
|
"roughnessFactor":0.9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Plane.002",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"NORMAL":1,
|
||||||
|
"TEXCOORD_0":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"game.png",
|
||||||
|
"uri":"game.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":120,
|
||||||
|
"max":[
|
||||||
|
0.25,
|
||||||
|
0.25,
|
||||||
|
0.00390625
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-0.25,
|
||||||
|
-0.25,
|
||||||
|
-0.00390625
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":120,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":120,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":228,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":1440,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":1440,
|
||||||
|
"byteOffset":1440,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":960,
|
||||||
|
"byteOffset":2880,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":456,
|
||||||
|
"byteOffset":3840,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9728,
|
||||||
|
"minFilter":9984
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":4296,
|
||||||
|
"uri":"card.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
BIN
data/yakuza/pad.bin
Normal file
BIN
data/yakuza/pad.bin
Normal file
Binary file not shown.
144
data/yakuza/pad.gltf
Normal file
144
data/yakuza/pad.gltf
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v4.5.48",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"extensionsUsed":[
|
||||||
|
"KHR_materials_unlit"
|
||||||
|
],
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"pad"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"alphaMode":"BLEND",
|
||||||
|
"doubleSided":true,
|
||||||
|
"extensions":{
|
||||||
|
"KHR_materials_unlit":{}
|
||||||
|
},
|
||||||
|
"name":"Material",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0,
|
||||||
|
"roughnessFactor":0.9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Plane.003",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"NORMAL":1,
|
||||||
|
"TEXCOORD_0":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"game.png",
|
||||||
|
"uri":"game.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":1272,
|
||||||
|
"max":[
|
||||||
|
0.4140625,
|
||||||
|
0.4140625,
|
||||||
|
0.00390625
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-0.4140625,
|
||||||
|
-0.4140625,
|
||||||
|
-0.00390625
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":1272,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":1272,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":2532,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":15264,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":15264,
|
||||||
|
"byteOffset":15264,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":10176,
|
||||||
|
"byteOffset":30528,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":5064,
|
||||||
|
"byteOffset":40704,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9728,
|
||||||
|
"minFilter":9984
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":45768,
|
||||||
|
"uri":"pad.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
data/yakuza/table.bin
Normal file
BIN
data/yakuza/table.bin
Normal file
Binary file not shown.
144
data/yakuza/table.gltf
Normal file
144
data/yakuza/table.gltf
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v4.5.48",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"extensionsUsed":[
|
||||||
|
"KHR_materials_unlit"
|
||||||
|
],
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"alphaMode":"BLEND",
|
||||||
|
"doubleSided":true,
|
||||||
|
"extensions":{
|
||||||
|
"KHR_materials_unlit":{}
|
||||||
|
},
|
||||||
|
"name":"Material",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0,
|
||||||
|
"roughnessFactor":0.9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Plane",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"NORMAL":1,
|
||||||
|
"TEXCOORD_0":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"game.png",
|
||||||
|
"uri":"game.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"max":[
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-4,
|
||||||
|
-4,
|
||||||
|
-0.5
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":36,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":288,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":288,
|
||||||
|
"byteOffset":288,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":192,
|
||||||
|
"byteOffset":576,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":72,
|
||||||
|
"byteOffset":768,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9728,
|
||||||
|
"minFilter":9984
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":840,
|
||||||
|
"uri":"table.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -1,11 +1,17 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const err = @import("error.zig");
|
const err = @import("error.zig");
|
||||||
const Game = @import("game.zig");
|
const Game = @import("game.zig");
|
||||||
const FileLoader = @import("assets/file.zig");
|
const FileLoader = @import("assets/file.zig");
|
||||||
const TextureLoader = @import("assets/texture.zig");
|
const TextureLoader = @import("assets/texture.zig");
|
||||||
|
const GltfLoader = @import("assets/gltf.zig");
|
||||||
const Assets = @This();
|
const Assets = @This();
|
||||||
|
|
||||||
|
// TODO: Unload assets in correct order to account for asset dependencies
|
||||||
|
|
||||||
|
pub const File = AssetContainer(FileLoader);
|
||||||
pub const Texture = AssetContainer(TextureLoader);
|
pub const Texture = AssetContainer(TextureLoader);
|
||||||
|
pub const Object = AssetContainer(GltfLoader);
|
||||||
|
|
||||||
const WORKERS_MAX = 4;
|
const WORKERS_MAX = 4;
|
||||||
var next_worker_update: usize = 0;
|
var next_worker_update: usize = 0;
|
||||||
@@ -50,16 +56,18 @@ pub const LoadError = error{
|
|||||||
ParsingError,
|
ParsingError,
|
||||||
SdlError,
|
SdlError,
|
||||||
FileTooBig,
|
FileTooBig,
|
||||||
} || std.mem.Allocator.Error || std.fs.File.OpenError || std.fs.File.ReadError;
|
} || std.mem.Allocator.Error || std.fs.File.OpenError || std.fs.File.ReadError || std.json.ParseError(std.json.Scanner);
|
||||||
|
|
||||||
pub const AssetType = enum {
|
pub const AssetType = enum {
|
||||||
file,
|
file,
|
||||||
texture,
|
texture,
|
||||||
|
gltf,
|
||||||
|
|
||||||
pub fn getType(comptime self: @This()) type {
|
pub fn getType(comptime self: @This()) type {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
.file => FileLoader,
|
.file => FileLoader,
|
||||||
.texture => TextureLoader,
|
.texture => TextureLoader,
|
||||||
|
.gltf => GltfLoader,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -82,6 +90,8 @@ pub const AssetCell = struct {
|
|||||||
|
|
||||||
fn load(self: *AssetCell, alloc: std.mem.Allocator) void {
|
fn load(self: *AssetCell, alloc: std.mem.Allocator) void {
|
||||||
self.loader(self, alloc) catch |e| {
|
self.loader(self, alloc) catch |e| {
|
||||||
|
if (builtin.mode == .Debug)
|
||||||
|
std.debug.panic("Asset loading error: {s} - {}!\n", .{ self.path, e });
|
||||||
self.state = .{ .fail = e };
|
self.state = .{ .fail = e };
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -119,6 +129,8 @@ pub fn AssetContainer(comptime T: type) type {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: Add smth like `Assets.immediateLoad`
|
||||||
|
|
||||||
/// To be used by worker threads to request other assets
|
/// To be used by worker threads to request other assets
|
||||||
pub fn getSync(self: *@This()) !*T {
|
pub fn getSync(self: *@This()) !*T {
|
||||||
sw: switch (self.last_state) {
|
sw: switch (self.last_state) {
|
||||||
@@ -168,6 +180,7 @@ pub fn deinit() void {
|
|||||||
std.debug.assert(asset.*.counter == 0);
|
std.debug.assert(asset.*.counter == 0);
|
||||||
if (asset.*.state == .loaded)
|
if (asset.*.state == .loaded)
|
||||||
asset.*.unload(Game.alloc);
|
asset.*.unload(Game.alloc);
|
||||||
|
Game.alloc.free(asset.*.path);
|
||||||
Game.alloc.destroy(asset.*);
|
Game.alloc.destroy(asset.*);
|
||||||
}
|
}
|
||||||
Assets.asset_map.clearAndFree(Game.alloc);
|
Assets.asset_map.clearAndFree(Game.alloc);
|
||||||
@@ -202,6 +215,7 @@ pub fn update() void {
|
|||||||
if (!Assets.asset_map.remove(.{ .type = request.type, .path = request.path })) continue;
|
if (!Assets.asset_map.remove(.{ .type = request.type, .path = request.path })) continue;
|
||||||
if (request.state == .loaded)
|
if (request.state == .loaded)
|
||||||
request.unload(Game.alloc);
|
request.unload(Game.alloc);
|
||||||
|
Game.alloc.free(request.path);
|
||||||
Game.alloc.destroy(request);
|
Game.alloc.destroy(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,7 +273,7 @@ fn mapAsset(comptime asset_type: AssetType, path: []const u8) *AssetCell {
|
|||||||
.mutex = .{},
|
.mutex = .{},
|
||||||
.type = asset_type,
|
.type = asset_type,
|
||||||
.data = undefined,
|
.data = undefined,
|
||||||
.path = path,
|
.path = Game.alloc.dupe(u8, path) catch err.oom(),
|
||||||
.loader = Assets.makeLoader(asset_type.getType(), asset_type.getType().load),
|
.loader = Assets.makeLoader(asset_type.getType(), asset_type.getType().load),
|
||||||
.unloader = Assets.makeUnloader(asset_type.getType(), asset_type.getType().unload),
|
.unloader = Assets.makeUnloader(asset_type.getType(), asset_type.getType().unload),
|
||||||
.state = .not_loaded,
|
.state = .not_loaded,
|
||||||
|
389
src/assets/gltf.zig
Normal file
389
src/assets/gltf.zig
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const sdl = @import("sdl");
|
||||||
|
const err = @import("../error.zig");
|
||||||
|
const Assets = @import("../assets.zig");
|
||||||
|
const Graphics = @import("../graphics.zig");
|
||||||
|
|
||||||
|
nodes: []Node,
|
||||||
|
meshes: []Mesh,
|
||||||
|
|
||||||
|
const Node = struct {
|
||||||
|
mesh: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Mesh = struct {
|
||||||
|
primitives: []Primitive,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Primitive = struct {
|
||||||
|
vertex_buffer: *sdl.GPUBuffer,
|
||||||
|
index_buffer: ?*sdl.GPUBuffer = null,
|
||||||
|
|
||||||
|
vertices: u32,
|
||||||
|
indices: u32 = 0,
|
||||||
|
texture: Assets.Texture,
|
||||||
|
};
|
||||||
|
|
||||||
|
const GltfJson = struct {
|
||||||
|
scene: u32,
|
||||||
|
scenes: []GltfSceneJson,
|
||||||
|
nodes: []GltfNodeJson,
|
||||||
|
materials: []GltfMaterialJson,
|
||||||
|
meshes: []GltfMeshJson,
|
||||||
|
textures: []GltfTextureJson,
|
||||||
|
images: []GltfImageJson,
|
||||||
|
accessors: []GltfAccessorJson,
|
||||||
|
bufferViews: []GltfBufferViewJson,
|
||||||
|
samplers: []GltfSamplerJson,
|
||||||
|
buffers: []GltfBufferJson,
|
||||||
|
|
||||||
|
const GltfSceneJson = struct {
|
||||||
|
nodes: []u32,
|
||||||
|
};
|
||||||
|
const GltfNodeJson = struct {
|
||||||
|
mesh: u32,
|
||||||
|
};
|
||||||
|
const GltfMaterialJson = struct {
|
||||||
|
pbrMetallicRoughness: GltfPbrMRJson,
|
||||||
|
|
||||||
|
const GltfPbrMRJson = struct {
|
||||||
|
baseColorTexture: GltfPbrMRBaseColorTexture,
|
||||||
|
|
||||||
|
const GltfPbrMRBaseColorTexture = struct {
|
||||||
|
index: u32,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const GltfMeshJson = struct {
|
||||||
|
primitives: []GltfPrimitiveJson,
|
||||||
|
|
||||||
|
const GltfPrimitiveJson = struct {
|
||||||
|
attributes: GltfAttributesJson,
|
||||||
|
indices: u32,
|
||||||
|
material: u32,
|
||||||
|
|
||||||
|
const GltfAttributesJson = struct {
|
||||||
|
POSITION: u32,
|
||||||
|
TEXCOORD_0: u32,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const GltfTextureJson = struct {
|
||||||
|
sampler: ?u32,
|
||||||
|
source: u32,
|
||||||
|
};
|
||||||
|
const GltfImageJson = struct {
|
||||||
|
uri: []u8,
|
||||||
|
};
|
||||||
|
const GltfAccessorJson = struct {
|
||||||
|
bufferView: u32,
|
||||||
|
componentType: GltfComponentTypeJson,
|
||||||
|
count: u32,
|
||||||
|
type: GltfAccessorTypeJson,
|
||||||
|
|
||||||
|
const GltfComponentTypeJson = enum(u32) {
|
||||||
|
i8 = 5120,
|
||||||
|
u8 = 5121,
|
||||||
|
i16 = 5122,
|
||||||
|
u16 = 5123,
|
||||||
|
i32 = 5125,
|
||||||
|
f32 = 5126,
|
||||||
|
};
|
||||||
|
const GltfAccessorTypeJson = enum {
|
||||||
|
SCALAR,
|
||||||
|
VEC2,
|
||||||
|
VEC3,
|
||||||
|
VEC4,
|
||||||
|
MAT2,
|
||||||
|
MAT3,
|
||||||
|
MAT4,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn slice(accessor: @This(), comptime T: type, views: []const GltfBufferViewJson, buffers: []Assets.File) !?[]align(1) T {
|
||||||
|
if (accessor.bufferView >= views.len) return null;
|
||||||
|
const view = &views[accessor.bufferView];
|
||||||
|
|
||||||
|
if (view.buffer >= buffers.len) return null;
|
||||||
|
const buffer = try buffers[view.buffer].getSync();
|
||||||
|
|
||||||
|
const component_length = switch (T) {
|
||||||
|
[3]f32 => 12,
|
||||||
|
[2]f32 => 8,
|
||||||
|
u16 => 2,
|
||||||
|
else => @compileError("Accessor of " ++ @tagName(accessor.type) ++ " of " ++ @tagName(accessor.componentType) ++ " is not supported."),
|
||||||
|
};
|
||||||
|
|
||||||
|
const start = view.byteOffset;
|
||||||
|
const length = component_length * accessor.count;
|
||||||
|
const end = start + length;
|
||||||
|
|
||||||
|
if (length != view.byteLength) return error.ParsingError;
|
||||||
|
|
||||||
|
return @as([]align(1) T, @ptrCast(buffer.bytes[start..end]));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const GltfBufferViewJson = struct {
|
||||||
|
buffer: u32,
|
||||||
|
byteLength: u32,
|
||||||
|
byteOffset: u32 = 0,
|
||||||
|
};
|
||||||
|
const GltfSamplerJson = struct {
|
||||||
|
magFilter: GltfFilterJson = .NEAREST,
|
||||||
|
minFilter: GltfFilterJson = .LINEAR,
|
||||||
|
wrapS: GltfWrapJson = .CLAMP_TO_EDGE,
|
||||||
|
wrapT: GltfWrapJson = .CLAMP_TO_EDGE,
|
||||||
|
|
||||||
|
const GltfFilterJson = enum(u32) {
|
||||||
|
NEAREST = 9728,
|
||||||
|
LINEAR = 9729,
|
||||||
|
NEAREST_MIPMAP_NEAREST = 9984,
|
||||||
|
LINEAR_MIPMAP_NEAREST = 9985,
|
||||||
|
NEAREST_MIPMAP_LINEAR = 9986,
|
||||||
|
LINEAR_MIPMAP_LINEAR = 9987,
|
||||||
|
};
|
||||||
|
const GltfWrapJson = enum(u32) {
|
||||||
|
CLAMP_TO_EDGE = 33071,
|
||||||
|
MIRRORED_REPEAT = 33648,
|
||||||
|
REPEAT = 10497,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const GltfBufferJson = struct {
|
||||||
|
// byteLength: u32,
|
||||||
|
uri: []u8,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn load(path: []const u8, alloc: std.mem.Allocator) Assets.LoadError!@This() {
|
||||||
|
var json = Assets.load(.file, path);
|
||||||
|
defer Assets.free(json);
|
||||||
|
|
||||||
|
const parsed_gltf = try std.json.parseFromSlice(
|
||||||
|
GltfJson,
|
||||||
|
alloc,
|
||||||
|
(try json.getSync()).bytes,
|
||||||
|
.{ .ignore_unknown_fields = true },
|
||||||
|
);
|
||||||
|
defer parsed_gltf.deinit();
|
||||||
|
const gltf = &parsed_gltf.value;
|
||||||
|
|
||||||
|
if (gltf.scene >= gltf.scenes.len) return error.ParsingError;
|
||||||
|
const scene = &gltf.scenes[gltf.scene];
|
||||||
|
|
||||||
|
var buffers_init: u32 = 0;
|
||||||
|
const buffers = try alloc.alloc(Assets.File, gltf.buffers.len);
|
||||||
|
defer alloc.free(buffers);
|
||||||
|
|
||||||
|
defer for (buffers[0..buffers_init]) |buffer| {
|
||||||
|
Assets.free(buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (0.., buffers) |i, *buffer| {
|
||||||
|
const buffer_path = try std.fs.path.join(alloc, &.{ std.fs.path.dirname(path) orelse return error.ParsingError, gltf.buffers[i].uri });
|
||||||
|
defer alloc.free(buffer_path);
|
||||||
|
buffer.* = Assets.load(.file, buffer_path);
|
||||||
|
buffers_init += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodes = try alloc.alloc(Node, scene.nodes.len);
|
||||||
|
errdefer alloc.free(nodes);
|
||||||
|
|
||||||
|
var meshes_init: u32 = 0;
|
||||||
|
const meshes = try alloc.alloc(Mesh, gltf.meshes.len);
|
||||||
|
errdefer alloc.free(nodes);
|
||||||
|
|
||||||
|
errdefer for (meshes[0..meshes_init]) |*mesh| {
|
||||||
|
for (mesh.primitives) |*primitive| {
|
||||||
|
sdl.ReleaseGPUBuffer(Graphics.device, primitive.vertex_buffer);
|
||||||
|
if (primitive.index_buffer) |buf| sdl.ReleaseGPUBuffer(Graphics.device, buf);
|
||||||
|
Assets.free(primitive.texture);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (0.., nodes) |i, *node| {
|
||||||
|
const node_index = scene.nodes[i];
|
||||||
|
if (node_index >= gltf.nodes.len) return error.ParsingError;
|
||||||
|
const gltf_node = &gltf.nodes[node_index];
|
||||||
|
if (gltf_node.mesh >= gltf.meshes.len) return error.ParsingError;
|
||||||
|
node.mesh = gltf_node.mesh;
|
||||||
|
}
|
||||||
|
for (0.., meshes) |i, *mesh| {
|
||||||
|
const gltf_mesh = &gltf.meshes[i];
|
||||||
|
|
||||||
|
var primitivs_init: u32 = 0;
|
||||||
|
const primitives = try alloc.alloc(Primitive, gltf_mesh.primitives.len);
|
||||||
|
errdefer alloc.free(primitives);
|
||||||
|
|
||||||
|
errdefer for (primitives[0..primitivs_init]) |*primitive| {
|
||||||
|
sdl.ReleaseGPUBuffer(Graphics.device, primitive.vertex_buffer);
|
||||||
|
if (primitive.index_buffer) |buf| sdl.ReleaseGPUBuffer(Graphics.device, buf);
|
||||||
|
Assets.free(primitive.texture);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (0.., primitives) |j, *primitive| {
|
||||||
|
const gltf_primitive = gltf_mesh.primitives[j];
|
||||||
|
|
||||||
|
if (gltf_primitive.attributes.POSITION >= gltf.accessors.len) return error.ParsingError;
|
||||||
|
if (gltf_primitive.attributes.TEXCOORD_0 >= gltf.accessors.len) return error.ParsingError;
|
||||||
|
if (gltf_primitive.material >= gltf.materials.len) return error.ParsingError;
|
||||||
|
const material = &gltf.materials[gltf_primitive.material];
|
||||||
|
const texture_index = material.pbrMetallicRoughness.baseColorTexture.index;
|
||||||
|
if (texture_index >= gltf.textures.len) return error.ParsingError;
|
||||||
|
const texture = &gltf.textures[texture_index];
|
||||||
|
if (texture.source >= gltf.images.len) return error.ParsingError;
|
||||||
|
const image = &gltf.images[texture.source];
|
||||||
|
|
||||||
|
const position = try gltf.accessors[gltf_primitive.attributes.POSITION].slice([3]f32, gltf.bufferViews, buffers) orelse return error.ParsingError;
|
||||||
|
const uv = try gltf.accessors[gltf_primitive.attributes.TEXCOORD_0].slice([2]f32, gltf.bufferViews, buffers) orelse return error.ParsingError;
|
||||||
|
const index = try gltf.accessors[gltf_primitive.indices].slice(u16, gltf.bufferViews, buffers) orelse return error.ParsingError;
|
||||||
|
|
||||||
|
primitive.vertex_buffer, primitive.index_buffer = try loadMesh(position, uv, index, alloc);
|
||||||
|
errdefer sdl.ReleaseGPUBuffer(Graphics.device, primitive.vertex_buffer);
|
||||||
|
errdefer sdl.ReleaseGPUBuffer(Graphics.device, primitive.index_buffer);
|
||||||
|
|
||||||
|
primitive.vertices = @intCast(position.len);
|
||||||
|
primitive.indices = @intCast(index.len);
|
||||||
|
|
||||||
|
const texture_path = try std.fs.path.join(alloc, &.{ std.fs.path.dirname(path) orelse return error.ParsingError, image.uri });
|
||||||
|
defer alloc.free(texture_path);
|
||||||
|
primitive.texture = Assets.load(.texture, texture_path);
|
||||||
|
|
||||||
|
primitivs_init += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh.primitives = primitives;
|
||||||
|
meshes_init += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.nodes = nodes,
|
||||||
|
.meshes = meshes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unload(self: @This(), alloc: std.mem.Allocator) void {
|
||||||
|
for (self.meshes) |mesh| {
|
||||||
|
for (mesh.primitives) |*primitive| {
|
||||||
|
sdl.ReleaseGPUBuffer(Graphics.device, primitive.vertex_buffer);
|
||||||
|
sdl.ReleaseGPUBuffer(Graphics.device, primitive.index_buffer);
|
||||||
|
Assets.free(primitive.texture);
|
||||||
|
}
|
||||||
|
alloc.free(mesh.primitives);
|
||||||
|
}
|
||||||
|
alloc.free(self.meshes);
|
||||||
|
alloc.free(self.nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn loadMesh(position: []align(1) const [3]f32, uv: []align(1) const [2]f32, index: []align(1) const u16, alloc: std.mem.Allocator) !struct { *sdl.GPUBuffer, *sdl.GPUBuffer } {
|
||||||
|
if (position.len != uv.len) return error.ParsingError;
|
||||||
|
const vertices: u32 = @intCast(position.len);
|
||||||
|
const indices: u32 = @intCast(index.len);
|
||||||
|
|
||||||
|
const BYTES_PER_VERTEX = 20;
|
||||||
|
const BYTES_PER_INDEX = 2;
|
||||||
|
|
||||||
|
const vertex_buffer = sdl.CreateGPUBuffer(Graphics.device, &.{
|
||||||
|
.size = vertices * BYTES_PER_VERTEX,
|
||||||
|
.usage = sdl.GPU_BUFFERUSAGE_VERTEX,
|
||||||
|
}) orelse return error.SdlError;
|
||||||
|
errdefer sdl.ReleaseGPUBuffer(Graphics.device, vertex_buffer);
|
||||||
|
|
||||||
|
const index_buffer = sdl.CreateGPUBuffer(Graphics.device, &.{
|
||||||
|
.size = indices * 2,
|
||||||
|
.usage = sdl.GPU_BUFFERUSAGE_INDEX,
|
||||||
|
}) orelse return error.SdlError;
|
||||||
|
errdefer sdl.ReleaseGPUBuffer(Graphics.device, index_buffer);
|
||||||
|
|
||||||
|
const TRANSFER_CAPACITY = Graphics.TRANSFER_BUFFER_DEFAULT_CAPACITY;
|
||||||
|
|
||||||
|
const transfer_buffer = sdl.CreateGPUTransferBuffer(Graphics.device, &.{
|
||||||
|
.size = TRANSFER_CAPACITY,
|
||||||
|
.usage = sdl.GPU_TRANSFERBUFFERUSAGE_UPLOAD,
|
||||||
|
}) orelse return error.SdlError;
|
||||||
|
defer sdl.ReleaseGPUTransferBuffer(Graphics.device, transfer_buffer);
|
||||||
|
|
||||||
|
const buffer = try alloc.alloc(u8, TRANSFER_CAPACITY);
|
||||||
|
defer alloc.free(buffer);
|
||||||
|
|
||||||
|
var vertices_uploaded: u32 = 0;
|
||||||
|
while (vertices_uploaded < vertices) {
|
||||||
|
const vertices_to_upload = @min(vertices - vertices_uploaded, TRANSFER_CAPACITY / BYTES_PER_VERTEX);
|
||||||
|
if (vertices_to_upload == 0) return error.FileTooBig;
|
||||||
|
|
||||||
|
for (0..vertices_to_upload) |i| {
|
||||||
|
const V = packed struct { x: f32, y: f32, z: f32, u: f32, v: f32 };
|
||||||
|
std.mem.copyForwards(
|
||||||
|
u8,
|
||||||
|
buffer[BYTES_PER_VERTEX * i ..],
|
||||||
|
&@as([BYTES_PER_VERTEX]u8, @bitCast(V{
|
||||||
|
.x = position[vertices_uploaded + i][0],
|
||||||
|
.y = position[vertices_uploaded + i][1],
|
||||||
|
.z = position[vertices_uploaded + i][2],
|
||||||
|
.u = uv[vertices_uploaded + i][0],
|
||||||
|
.v = uv[vertices_uploaded + i][1],
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const command_buffer = sdl.AcquireGPUCommandBuffer(Graphics.device) orelse return error.SdlError;
|
||||||
|
{
|
||||||
|
errdefer _ = sdl.CancelGPUCommandBuffer(command_buffer);
|
||||||
|
const copy_pass = sdl.BeginGPUCopyPass(command_buffer) orelse return error.SdlError;
|
||||||
|
defer sdl.EndGPUCopyPass(copy_pass);
|
||||||
|
|
||||||
|
const map: [*]u8 = @ptrCast(sdl.MapGPUTransferBuffer(Graphics.device, transfer_buffer, false) orelse err.sdl());
|
||||||
|
@memcpy(map, buffer[0 .. vertices_to_upload * BYTES_PER_VERTEX]);
|
||||||
|
sdl.UnmapGPUTransferBuffer(Graphics.device, transfer_buffer);
|
||||||
|
|
||||||
|
sdl.UploadToGPUBuffer(copy_pass, &.{
|
||||||
|
.transfer_buffer = transfer_buffer,
|
||||||
|
}, &.{
|
||||||
|
.buffer = vertex_buffer,
|
||||||
|
.offset = vertices_uploaded * BYTES_PER_VERTEX,
|
||||||
|
.size = vertices_to_upload * BYTES_PER_VERTEX,
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
vertices_uploaded += vertices_to_upload;
|
||||||
|
const fence = sdl.SubmitGPUCommandBufferAndAcquireFence(command_buffer) orelse return error.SdlError;
|
||||||
|
defer sdl.ReleaseGPUFence(Graphics.device, fence);
|
||||||
|
if (!sdl.WaitForGPUFences(Graphics.device, true, &fence, 1)) return error.SdlError;
|
||||||
|
}
|
||||||
|
|
||||||
|
var indices_uploaded: u32 = 0;
|
||||||
|
while (indices_uploaded < indices) {
|
||||||
|
const indices_to_upload = @min(indices - indices_uploaded, TRANSFER_CAPACITY / BYTES_PER_INDEX);
|
||||||
|
if (indices_to_upload == 0) return error.FileTooBig;
|
||||||
|
|
||||||
|
for (0..indices_to_upload) |i| {
|
||||||
|
std.mem.copyForwards(
|
||||||
|
u8,
|
||||||
|
buffer[BYTES_PER_INDEX * i ..],
|
||||||
|
&@as([BYTES_PER_INDEX]u8, @bitCast(index[i])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const command_buffer = sdl.AcquireGPUCommandBuffer(Graphics.device) orelse return error.SdlError;
|
||||||
|
{
|
||||||
|
errdefer _ = sdl.CancelGPUCommandBuffer(command_buffer);
|
||||||
|
const copy_pass = sdl.BeginGPUCopyPass(command_buffer) orelse return error.SdlError;
|
||||||
|
defer sdl.EndGPUCopyPass(copy_pass);
|
||||||
|
|
||||||
|
const map: [*]u8 = @ptrCast(sdl.MapGPUTransferBuffer(Graphics.device, transfer_buffer, false) orelse err.sdl());
|
||||||
|
@memcpy(map, buffer[0 .. indices_to_upload * BYTES_PER_INDEX]);
|
||||||
|
sdl.UnmapGPUTransferBuffer(Graphics.device, transfer_buffer);
|
||||||
|
|
||||||
|
sdl.UploadToGPUBuffer(copy_pass, &.{
|
||||||
|
.transfer_buffer = transfer_buffer,
|
||||||
|
}, &.{
|
||||||
|
.buffer = index_buffer,
|
||||||
|
.offset = indices_uploaded * BYTES_PER_INDEX,
|
||||||
|
.size = indices_to_upload * BYTES_PER_INDEX,
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
indices_uploaded += indices_to_upload;
|
||||||
|
const fence = sdl.SubmitGPUCommandBufferAndAcquireFence(command_buffer) orelse return error.SdlError;
|
||||||
|
defer sdl.ReleaseGPUFence(Graphics.device, fence);
|
||||||
|
if (!sdl.WaitForGPUFences(Graphics.device, true, &fence, 1)) return error.SdlError;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{ vertex_buffer, index_buffer };
|
||||||
|
}
|
140
src/graphics.zig
140
src/graphics.zig
@@ -7,11 +7,6 @@ const Assets = @import("assets.zig");
|
|||||||
pub const Transform = @import("graphics/transform.zig");
|
pub const Transform = @import("graphics/transform.zig");
|
||||||
pub const Camera = @import("graphics/camera.zig");
|
pub const Camera = @import("graphics/camera.zig");
|
||||||
|
|
||||||
pub const Mesh = struct {
|
|
||||||
vertex_start: usize,
|
|
||||||
vertex_count: usize,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub var window: *sdl.Window = undefined;
|
pub var window: *sdl.Window = undefined;
|
||||||
pub var device: *sdl.GPUDevice = undefined;
|
pub var device: *sdl.GPUDevice = undefined;
|
||||||
/// Only available while drawing
|
/// Only available while drawing
|
||||||
@@ -22,13 +17,6 @@ var render_target: ?*sdl.GPUTexture = null;
|
|||||||
var shader_vert: *sdl.GPUShader = undefined;
|
var shader_vert: *sdl.GPUShader = undefined;
|
||||||
var shader_frag: *sdl.GPUShader = undefined;
|
var shader_frag: *sdl.GPUShader = undefined;
|
||||||
|
|
||||||
var vertex_buffer: *sdl.GPUBuffer = undefined;
|
|
||||||
var vertex_buffer_capacity: usize = undefined;
|
|
||||||
var vertex_buffer_used: usize = undefined;
|
|
||||||
|
|
||||||
var transfer_buffer: *sdl.GPUTransferBuffer = undefined;
|
|
||||||
var transfer_buffer_capacity: usize = undefined;
|
|
||||||
|
|
||||||
var depth_texture: *sdl.GPUTexture = undefined;
|
var depth_texture: *sdl.GPUTexture = undefined;
|
||||||
var fsaa_target: *sdl.GPUTexture = undefined;
|
var fsaa_target: *sdl.GPUTexture = undefined;
|
||||||
var pipeline: *sdl.GPUGraphicsPipeline = undefined;
|
var pipeline: *sdl.GPUGraphicsPipeline = undefined;
|
||||||
@@ -40,11 +28,9 @@ var fsaa_level: u32 = 3;
|
|||||||
|
|
||||||
pub var camera: Camera = undefined;
|
pub var camera: Camera = undefined;
|
||||||
|
|
||||||
const VERTEX_BUFFER_DEFAULT_CAPACITY = 1024;
|
|
||||||
const VERTEX_BUFFER_GROWTH_MULTIPLIER = 2;
|
|
||||||
const BYTES_PER_VERTEX = 5 * 4;
|
const BYTES_PER_VERTEX = 5 * 4;
|
||||||
const DEPTH_FORMAT = sdl.GPU_TEXTUREFORMAT_D32_FLOAT;
|
const DEPTH_FORMAT = sdl.GPU_TEXTUREFORMAT_D32_FLOAT;
|
||||||
pub const TRANSFER_BUFFER_DEFAULT_CAPACITY = 256 * 1024;
|
pub const TRANSFER_BUFFER_DEFAULT_CAPACITY = 512 * 1024;
|
||||||
pub const MIP_LEVEL = 4;
|
pub const MIP_LEVEL = 4;
|
||||||
|
|
||||||
const Graphics = @This();
|
const Graphics = @This();
|
||||||
@@ -92,19 +78,6 @@ pub fn create() void {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Graphics.vertex_buffer = sdl.CreateGPUBuffer(Graphics.device, &.{
|
|
||||||
.usage = sdl.GPU_BUFFERUSAGE_VERTEX,
|
|
||||||
.size = VERTEX_BUFFER_DEFAULT_CAPACITY,
|
|
||||||
}) orelse err.sdl();
|
|
||||||
Graphics.vertex_buffer_capacity = VERTEX_BUFFER_DEFAULT_CAPACITY;
|
|
||||||
Graphics.vertex_buffer_used = 0;
|
|
||||||
|
|
||||||
Graphics.transfer_buffer = sdl.CreateGPUTransferBuffer(Graphics.device, &.{
|
|
||||||
.size = TRANSFER_BUFFER_DEFAULT_CAPACITY,
|
|
||||||
.usage = sdl.GPU_TRANSFERBUFFERUSAGE_UPLOAD | sdl.GPU_TRANSFERBUFFERUSAGE_DOWNLOAD,
|
|
||||||
}) orelse err.sdl();
|
|
||||||
Graphics.transfer_buffer_capacity = TRANSFER_BUFFER_DEFAULT_CAPACITY;
|
|
||||||
|
|
||||||
const target_format = sdl.GetGPUSwapchainTextureFormat(Graphics.device, Graphics.window);
|
const target_format = sdl.GetGPUSwapchainTextureFormat(Graphics.device, Graphics.window);
|
||||||
if (target_format == sdl.GPU_TEXTUREFORMAT_INVALID) err.sdl();
|
if (target_format == sdl.GPU_TEXTUREFORMAT_INVALID) err.sdl();
|
||||||
|
|
||||||
@@ -183,8 +156,6 @@ pub fn destroy() void {
|
|||||||
sdl.ReleaseGPUGraphicsPipeline(Graphics.device, Graphics.pipeline);
|
sdl.ReleaseGPUGraphicsPipeline(Graphics.device, Graphics.pipeline);
|
||||||
sdl.ReleaseGPUTexture(Graphics.device, Graphics.fsaa_target);
|
sdl.ReleaseGPUTexture(Graphics.device, Graphics.fsaa_target);
|
||||||
sdl.ReleaseGPUTexture(Graphics.device, Graphics.depth_texture);
|
sdl.ReleaseGPUTexture(Graphics.device, Graphics.depth_texture);
|
||||||
sdl.ReleaseGPUBuffer(Graphics.device, Graphics.vertex_buffer);
|
|
||||||
sdl.ReleaseGPUTransferBuffer(Graphics.device, Graphics.transfer_buffer);
|
|
||||||
|
|
||||||
sdl.ReleaseGPUShader(Graphics.device, Graphics.shader_vert);
|
sdl.ReleaseGPUShader(Graphics.device, Graphics.shader_vert);
|
||||||
sdl.ReleaseGPUShader(Graphics.device, Graphics.shader_frag);
|
sdl.ReleaseGPUShader(Graphics.device, Graphics.shader_frag);
|
||||||
@@ -196,98 +167,6 @@ pub fn destroy() void {
|
|||||||
sdl.DestroyGPUDevice(Graphics.device);
|
sdl.DestroyGPUDevice(Graphics.device);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn loadMesh(mesh_bytes: []const u8) Mesh {
|
|
||||||
std.debug.assert(mesh_bytes.len < Graphics.transfer_buffer_capacity);
|
|
||||||
|
|
||||||
var size_mult: usize = 1;
|
|
||||||
while (Graphics.vertex_buffer_used + mesh_bytes.len > Graphics.vertex_buffer_capacity * size_mult) {
|
|
||||||
size_mult *= VERTEX_BUFFER_GROWTH_MULTIPLIER;
|
|
||||||
}
|
|
||||||
if (size_mult > 1) {
|
|
||||||
Graphics.growVertexBuffer(Graphics.vertex_buffer_capacity * size_mult);
|
|
||||||
}
|
|
||||||
|
|
||||||
const map = sdl.MapGPUTransferBuffer(Graphics.device, Graphics.transfer_buffer, true) orelse err.sdl();
|
|
||||||
@memcpy(@as([*]u8, @ptrCast(map)), mesh_bytes);
|
|
||||||
sdl.UnmapGPUTransferBuffer(Graphics.device, Graphics.transfer_buffer);
|
|
||||||
|
|
||||||
const temp_command_buffer = sdl.AcquireGPUCommandBuffer(Graphics.device) orelse err.sdl();
|
|
||||||
const fence = blk: {
|
|
||||||
const copy_pass = sdl.BeginGPUCopyPass(temp_command_buffer) orelse err.sdl();
|
|
||||||
sdl.UploadToGPUBuffer(copy_pass, &.{
|
|
||||||
.transfer_buffer = Graphics.transfer_buffer,
|
|
||||||
.offset = 0,
|
|
||||||
}, &.{
|
|
||||||
.buffer = Graphics.vertex_buffer,
|
|
||||||
.offset = @intCast(Graphics.vertex_buffer_used),
|
|
||||||
.size = @intCast(mesh_bytes.len),
|
|
||||||
}, false);
|
|
||||||
sdl.EndGPUCopyPass(copy_pass);
|
|
||||||
|
|
||||||
break :blk sdl.SubmitGPUCommandBufferAndAcquireFence(temp_command_buffer) orelse err.sdl();
|
|
||||||
};
|
|
||||||
defer sdl.ReleaseGPUFence(Graphics.device, fence);
|
|
||||||
|
|
||||||
if (!sdl.WaitForGPUFences(Graphics.device, true, &fence, 1)) err.sdl();
|
|
||||||
|
|
||||||
const vertex_start = Graphics.vertex_buffer_used;
|
|
||||||
Graphics.vertex_buffer_used += mesh_bytes.len;
|
|
||||||
|
|
||||||
return Mesh{
|
|
||||||
.vertex_start = vertex_start / BYTES_PER_VERTEX,
|
|
||||||
.vertex_count = mesh_bytes.len / BYTES_PER_VERTEX,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unloadMesh(mesh: Mesh) void {
|
|
||||||
// TODO: free some memory
|
|
||||||
_ = &mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn growVertexBuffer(new_size: usize) void {
|
|
||||||
const new_buffer = sdl.CreateGPUBuffer(Graphics.device, &.{
|
|
||||||
.size = @intCast(new_size),
|
|
||||||
.usage = sdl.GPU_BUFFERUSAGE_VERTEX,
|
|
||||||
}) orelse err.sdl();
|
|
||||||
|
|
||||||
const temp_command_buffer = sdl.AcquireGPUCommandBuffer(Graphics.device) orelse err.sdl();
|
|
||||||
|
|
||||||
const fence = blk: {
|
|
||||||
const copy_pass = sdl.BeginGPUCopyPass(temp_command_buffer);
|
|
||||||
var copied: usize = 0;
|
|
||||||
while (copied < Graphics.vertex_buffer_used) {
|
|
||||||
const to_transer = @min(Graphics.vertex_buffer_used - copied, Graphics.transfer_buffer_capacity);
|
|
||||||
sdl.DownloadFromGPUBuffer(copy_pass, &.{
|
|
||||||
.buffer = Graphics.vertex_buffer,
|
|
||||||
.offset = @intCast(copied),
|
|
||||||
.size = @intCast(to_transer),
|
|
||||||
}, &.{
|
|
||||||
.transfer_buffer = Graphics.transfer_buffer,
|
|
||||||
.offset = 0,
|
|
||||||
});
|
|
||||||
sdl.UploadToGPUBuffer(copy_pass, &.{
|
|
||||||
.transfer_buffer = Graphics.transfer_buffer,
|
|
||||||
.offset = 0,
|
|
||||||
}, &.{
|
|
||||||
.buffer = new_buffer,
|
|
||||||
.offset = @intCast(copied),
|
|
||||||
.size = @intCast(to_transer),
|
|
||||||
}, false);
|
|
||||||
copied += to_transer;
|
|
||||||
}
|
|
||||||
sdl.EndGPUCopyPass(copy_pass);
|
|
||||||
|
|
||||||
break :blk sdl.SubmitGPUCommandBufferAndAcquireFence(temp_command_buffer) orelse err.sdl();
|
|
||||||
};
|
|
||||||
defer sdl.ReleaseGPUFence(Graphics.device, fence);
|
|
||||||
|
|
||||||
if (!sdl.WaitForGPUFences(Graphics.device, true, &fence, 1)) err.sdl();
|
|
||||||
|
|
||||||
sdl.ReleaseGPUBuffer(Graphics.device, Graphics.vertex_buffer);
|
|
||||||
Graphics.vertex_buffer = new_buffer;
|
|
||||||
Graphics.vertex_buffer_capacity = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If window is minimized returns `false`, `render_pass` remains null
|
/// If window is minimized returns `false`, `render_pass` remains null
|
||||||
/// Otherwise `command_buffer` and `render_pass` are both set
|
/// Otherwise `command_buffer` and `render_pass` are both set
|
||||||
pub fn beginDraw() bool {
|
pub fn beginDraw() bool {
|
||||||
@@ -323,7 +202,6 @@ pub fn beginDraw() bool {
|
|||||||
}) orelse err.sdl();
|
}) orelse err.sdl();
|
||||||
|
|
||||||
sdl.BindGPUGraphicsPipeline(Graphics.render_pass, Graphics.pipeline);
|
sdl.BindGPUGraphicsPipeline(Graphics.render_pass, Graphics.pipeline);
|
||||||
sdl.BindGPUVertexBuffers(Graphics.render_pass, 0, &.{ .offset = 0, .buffer = Graphics.vertex_buffer }, 1);
|
|
||||||
Graphics.camera.computeMatrix();
|
Graphics.camera.computeMatrix();
|
||||||
sdl.PushGPUVertexUniformData(Graphics.command_buffer, 0, &Graphics.camera.matrix, 16 * 4);
|
sdl.PushGPUVertexUniformData(Graphics.command_buffer, 0, &Graphics.camera.matrix, 16 * 4);
|
||||||
|
|
||||||
@@ -350,20 +228,28 @@ pub fn clearDepth() void {
|
|||||||
}) orelse err.sdl();
|
}) orelse err.sdl();
|
||||||
|
|
||||||
sdl.BindGPUGraphicsPipeline(Graphics.render_pass, Graphics.pipeline);
|
sdl.BindGPUGraphicsPipeline(Graphics.render_pass, Graphics.pipeline);
|
||||||
sdl.BindGPUVertexBuffers(Graphics.render_pass, 0, &.{ .offset = 0, .buffer = Graphics.vertex_buffer }, 1);
|
|
||||||
sdl.PushGPUVertexUniformData(Graphics.command_buffer, 0, &Graphics.camera.matrix, 16 * 4);
|
sdl.PushGPUVertexUniformData(Graphics.command_buffer, 0, &Graphics.camera.matrix, 16 * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawMesh(mesh: Mesh, texture: *Assets.Texture, transform: Transform) void {
|
pub fn drawObject(object: *Assets.Object, transform: Transform) void {
|
||||||
if (Graphics.render_pass == null) return;
|
if (Graphics.render_pass == null) return;
|
||||||
const asset_texture = texture.get() orelse return;
|
const asset_object = object.get() orelse return;
|
||||||
|
|
||||||
sdl.PushGPUVertexUniformData(Graphics.command_buffer, 1, &transform.matrix(), 16 * 4);
|
sdl.PushGPUVertexUniformData(Graphics.command_buffer, 1, &transform.matrix(), 16 * 4);
|
||||||
|
for (asset_object.nodes) |node| {
|
||||||
|
const mesh = &asset_object.meshes[node.mesh];
|
||||||
|
|
||||||
|
for (mesh.primitives) |*primitive| {
|
||||||
|
const asset_texture = primitive.texture.get() orelse continue;
|
||||||
sdl.BindGPUFragmentSamplers(Graphics.render_pass, 0, &sdl.GPUTextureSamplerBinding{
|
sdl.BindGPUFragmentSamplers(Graphics.render_pass, 0, &sdl.GPUTextureSamplerBinding{
|
||||||
.texture = asset_texture.texture,
|
.texture = asset_texture.texture,
|
||||||
.sampler = asset_texture.sampler,
|
.sampler = asset_texture.sampler,
|
||||||
}, 1);
|
}, 1);
|
||||||
sdl.DrawGPUPrimitives(Graphics.render_pass, @intCast(mesh.vertex_count), 1, @intCast(mesh.vertex_start), 0);
|
sdl.BindGPUVertexBuffers(Graphics.render_pass, 0, &.{ .offset = 0, .buffer = primitive.vertex_buffer }, 1);
|
||||||
|
sdl.BindGPUIndexBuffer(Graphics.render_pass, &.{ .buffer = primitive.index_buffer }, sdl.GPU_INDEXELEMENTSIZE_16BIT);
|
||||||
|
sdl.DrawGPUIndexedPrimitives(Graphics.render_pass, primitive.indices, 1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endDraw() void {
|
pub fn endDraw() void {
|
||||||
|
142
src/world.zig
142
src/world.zig
@@ -12,13 +12,9 @@ const Order = i32;
|
|||||||
pub var object_map: std.AutoHashMapUnmanaged(Id, usize) = .{};
|
pub var object_map: std.AutoHashMapUnmanaged(Id, usize) = .{};
|
||||||
pub var objects: std.ArrayListUnmanaged(Object) = .{};
|
pub var objects: std.ArrayListUnmanaged(Object) = .{};
|
||||||
|
|
||||||
pub var hand_mesh: Graphics.Mesh = undefined;
|
pub var hand: Assets.Object = undefined;
|
||||||
pub var cube_mesh: Graphics.Mesh = undefined;
|
pub var table: Assets.Object = undefined;
|
||||||
pub var table_mesh: Graphics.Mesh = undefined;
|
pub var cubemap: Assets.Object = undefined;
|
||||||
pub var cubemap_mesh: Graphics.Mesh = undefined;
|
|
||||||
pub var table_texture: Assets.Texture = undefined;
|
|
||||||
pub var hand_texture: Assets.Texture = undefined;
|
|
||||||
pub var cubemap_texture: Assets.Texture = undefined;
|
|
||||||
|
|
||||||
pub var camera_position: @Vector(2, f32) = @splat(0);
|
pub var camera_position: @Vector(2, f32) = @splat(0);
|
||||||
pub var hand_transform: Graphics.Transform = .{};
|
pub var hand_transform: Graphics.Transform = .{};
|
||||||
@@ -46,8 +42,7 @@ const Object = struct {
|
|||||||
target_transform: Graphics.Transform = .{},
|
target_transform: Graphics.Transform = .{},
|
||||||
width: f32,
|
width: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
mesh: Graphics.Mesh,
|
object: Assets.Object,
|
||||||
texture: Assets.Texture,
|
|
||||||
order: Order,
|
order: Order,
|
||||||
id: Id,
|
id: Id,
|
||||||
index: u32,
|
index: u32,
|
||||||
@@ -99,15 +94,7 @@ pub fn initDebug() void {
|
|||||||
.type = .card,
|
.type = .card,
|
||||||
.width = 0.5,
|
.width = 0.5,
|
||||||
.height = 0.5,
|
.height = 0.5,
|
||||||
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(
|
.object = Assets.load(.gltf, "data/yakuza/card.gltf"),
|
||||||
@as(f32, @floatFromInt(9 + i / 10)) / 16.0,
|
|
||||||
@as(f32, @floatFromInt(0 + i % 10)) / 16.0,
|
|
||||||
@as(f32, @floatFromInt(10 + i / 10)) / 16.0,
|
|
||||||
@as(f32, @floatFromInt(1 + i % 10)) / 16.0,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
))),
|
|
||||||
.texture = Assets.load(.texture, "data/yakuza.png"),
|
|
||||||
.order = @intCast(i),
|
.order = @intCast(i),
|
||||||
.id = @intCast(i),
|
.id = @intCast(i),
|
||||||
.index = @intCast(i),
|
.index = @intCast(i),
|
||||||
@@ -120,15 +107,7 @@ pub fn initDebug() void {
|
|||||||
.type = .deck,
|
.type = .deck,
|
||||||
.width = 1,
|
.width = 1,
|
||||||
.height = 1,
|
.height = 1,
|
||||||
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(
|
.object = Assets.load(.gltf, "data/yakuza/pad.gltf"),
|
||||||
0.0 / 8.0,
|
|
||||||
4.0 / 8.0,
|
|
||||||
1.0 / 8.0,
|
|
||||||
5.0 / 8.0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
))),
|
|
||||||
.texture = Assets.load(.texture, "data/yakuza.png"),
|
|
||||||
.order = 70,
|
.order = 70,
|
||||||
.id = 70,
|
.id = 70,
|
||||||
.index = 70,
|
.index = 70,
|
||||||
@@ -139,27 +118,16 @@ pub fn initDebug() void {
|
|||||||
.type = .deck,
|
.type = .deck,
|
||||||
.width = 1,
|
.width = 1,
|
||||||
.height = 1,
|
.height = 1,
|
||||||
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(
|
.object = Assets.load(.gltf, "data/yakuza/pad.gltf"),
|
||||||
0.0 / 8.0,
|
|
||||||
4.0 / 8.0,
|
|
||||||
1.0 / 8.0,
|
|
||||||
5.0 / 8.0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
))),
|
|
||||||
.texture = Assets.load(.texture, "data/yakuza.png"),
|
|
||||||
.order = 71,
|
.order = 71,
|
||||||
.id = 71,
|
.id = 71,
|
||||||
.index = 71,
|
.index = 71,
|
||||||
}) catch err.oom();
|
}) catch err.oom();
|
||||||
World.object_map.put(Game.alloc, 71, 71) catch err.oom();
|
World.object_map.put(Game.alloc, 71, 71) catch err.oom();
|
||||||
|
|
||||||
World.table_mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(0, 0, 0.5, 0.5, 8, 8)));
|
World.hand = Assets.load(.gltf, "data/hand.gltf");
|
||||||
World.hand_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
|
World.table = Assets.load(.gltf, "data/yakuza/table.gltf");
|
||||||
World.cubemap_mesh = Graphics.loadMesh(@ptrCast(&CUBEMAP_MESH_DATA));
|
World.cubemap = Assets.load(.gltf, "data/cubemap.gltf");
|
||||||
World.table_texture = Assets.load(.texture, "data/yakuza.png");
|
|
||||||
World.hand_texture = Assets.load(.texture, "data/hand.png");
|
|
||||||
World.cubemap_texture = Assets.load(.texture, "data/cubemap.png");
|
|
||||||
|
|
||||||
World.camera_position = @splat(0);
|
World.camera_position = @splat(0);
|
||||||
World.hand_transform = .{};
|
World.hand_transform = .{};
|
||||||
@@ -177,15 +145,11 @@ pub fn initDebug() void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
pub fn deinit() void {
|
||||||
Graphics.unloadMesh(World.table_mesh);
|
Assets.free(World.hand);
|
||||||
Graphics.unloadMesh(World.hand_mesh);
|
Assets.free(World.table);
|
||||||
Graphics.unloadMesh(World.cubemap_mesh);
|
Assets.free(World.cubemap);
|
||||||
Assets.free(World.table_texture);
|
|
||||||
Assets.free(World.hand_texture);
|
|
||||||
Assets.free(World.cubemap_texture);
|
|
||||||
for (World.objects.items) |*object| {
|
for (World.objects.items) |*object| {
|
||||||
Assets.free(object.texture);
|
Assets.free(object.object);
|
||||||
Graphics.unloadMesh(object.mesh);
|
|
||||||
}
|
}
|
||||||
World.objects.clearAndFree(Game.alloc);
|
World.objects.clearAndFree(Game.alloc);
|
||||||
World.object_map.clearAndFree(Game.alloc);
|
World.object_map.clearAndFree(Game.alloc);
|
||||||
@@ -424,8 +388,9 @@ pub fn updateObject(object: *Object, delta: f32) void {
|
|||||||
.dock => {
|
.dock => {
|
||||||
var topleft_x = -World.dock_last_width * 0.5 * DOCK_TILT_COS + World.dock_spacing * (@as(f32, @floatFromInt(object.parent_index)) - @as(f32, @floatFromInt(World.dock_objects - 1)) * 0.5);
|
var topleft_x = -World.dock_last_width * 0.5 * DOCK_TILT_COS + World.dock_spacing * (@as(f32, @floatFromInt(object.parent_index)) - @as(f32, @floatFromInt(World.dock_objects - 1)) * 0.5);
|
||||||
const total_w = @as(f32, @floatFromInt(World.dock_objects - 1)) * World.dock_spacing + World.dock_last_width * DOCK_TILT_COS;
|
const total_w = @as(f32, @floatFromInt(World.dock_objects - 1)) * World.dock_spacing + World.dock_last_width * DOCK_TILT_COS;
|
||||||
|
const mouse_x = if (World.dock_focused) Game.mouse.x_norm else 0.5;
|
||||||
if (total_w > Graphics.camera.aspect * 2) {
|
if (total_w > Graphics.camera.aspect * 2) {
|
||||||
topleft_x += math.lerp(0, Graphics.camera.aspect - total_w * 0.5, Game.mouse.x_norm);
|
topleft_x += math.lerp(0, Graphics.camera.aspect - total_w * 0.5, mouse_x);
|
||||||
}
|
}
|
||||||
const hit = World.hover == object.id;
|
const hit = World.hover == object.id;
|
||||||
const topleft_y = if (World.dock_focused) if (hit) @as(f32, 0.5) else @as(f32, 0.3) else @as(f32, 0.2);
|
const topleft_y = if (World.dock_focused) if (hit) @as(f32, 0.5) else @as(f32, 0.3) else @as(f32, 0.2);
|
||||||
@@ -465,12 +430,12 @@ pub fn updateObject(object: *Object, delta: f32) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw() void {
|
pub fn draw() void {
|
||||||
Graphics.drawMesh(World.table_mesh, &World.table_texture, .{});
|
Graphics.drawObject(&World.table, .{});
|
||||||
|
|
||||||
for (World.objects.items) |*object| {
|
for (World.objects.items) |*object| {
|
||||||
sw: switch (object.parent) {
|
sw: switch (object.parent) {
|
||||||
.none, .hand => {
|
.none, .hand => {
|
||||||
Graphics.drawMesh(object.mesh, &object.texture, object.drawingTransform());
|
Graphics.drawObject(&object.object, object.drawingTransform());
|
||||||
},
|
},
|
||||||
.dock => {},
|
.dock => {},
|
||||||
.deck => |id| {
|
.deck => |id| {
|
||||||
@@ -482,9 +447,8 @@ pub fn draw() void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics.drawMesh(
|
Graphics.drawObject(
|
||||||
World.hand_mesh,
|
&World.hand,
|
||||||
&World.hand_texture,
|
|
||||||
Graphics.Transform.combineTransforms(
|
Graphics.Transform.combineTransforms(
|
||||||
.{
|
.{
|
||||||
.position = .{ World.hand_scale * 0.5, -World.hand_scale * 0.5, 0 },
|
.position = .{ World.hand_scale * 0.5, -World.hand_scale * 0.5, 0 },
|
||||||
@@ -494,14 +458,14 @@ pub fn draw() void {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Graphics.drawMesh(World.cubemap_mesh, &World.cubemap_texture, .{
|
Graphics.drawObject(&World.cubemap, .{
|
||||||
.scale = Graphics.camera.far,
|
.scale = Graphics.camera.far,
|
||||||
.position = Graphics.camera.transform.position,
|
.position = Graphics.camera.transform.position,
|
||||||
});
|
});
|
||||||
Graphics.clearDepth();
|
Graphics.clearDepth();
|
||||||
for (World.objects.items) |*object| {
|
for (World.objects.items) |*object| {
|
||||||
if (object.parent == .dock)
|
if (object.parent == .dock)
|
||||||
Graphics.drawMesh(object.mesh, &object.texture, object.drawingTransform());
|
Graphics.drawObject(&object.object, object.drawingTransform());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,65 +544,3 @@ fn objectOrderLessThan(ctx: void, lhs: Object, rhs: Object) bool {
|
|||||||
_ = ctx;
|
_ = ctx;
|
||||||
return lhs.order < rhs.order;
|
return lhs.order < rhs.order;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T1 = 1.0 / 3.0;
|
|
||||||
const T2 = 2.0 / 3.0;
|
|
||||||
const CUBEMAP_MESH_DATA = [_]f32{
|
|
||||||
-0.5, 0.5, -0.5, T2, 0,
|
|
||||||
-0.5, -0.5, -0.5, T2, 0.5,
|
|
||||||
0.5, 0.5, -0.5, 1, 0,
|
|
||||||
0.5, -0.5, -0.5, 1, 0.5,
|
|
||||||
0.5, 0.5, -0.5, 1, 0,
|
|
||||||
-0.5, -0.5, -0.5, T2, 0.5,
|
|
||||||
|
|
||||||
0.5, 0.5, -0.5, 0, 1,
|
|
||||||
0.5, -0.5, -0.5, T1, 1,
|
|
||||||
0.5, 0.5, 0.5, 0, 0.5,
|
|
||||||
0.5, -0.5, 0.5, T1, 0.5,
|
|
||||||
0.5, 0.5, 0.5, 0, 0.5,
|
|
||||||
0.5, -0.5, -0.5, T1, 1,
|
|
||||||
|
|
||||||
0.5, 0.5, 0.5, 1.0, 0.0,
|
|
||||||
0.5, -0.5, 0.5, 1.0, 1.0,
|
|
||||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
|
||||||
-0.5, -0.5, 0.5, 0.0, 1.0,
|
|
||||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
|
||||||
0.5, -0.5, 0.5, 1.0, 1.0,
|
|
||||||
|
|
||||||
-0.5, 0.5, 0.5, T1, 0,
|
|
||||||
-0.5, -0.5, 0.5, 0, 0,
|
|
||||||
-0.5, 0.5, -0.5, T1, 0.5,
|
|
||||||
-0.5, -0.5, -0.5, 0, 0.5,
|
|
||||||
-0.5, 0.5, -0.5, T1, 0.5,
|
|
||||||
-0.5, -0.5, 0.5, 0, 0,
|
|
||||||
|
|
||||||
-0.5, 0.5, 0.5, T1, 0.5,
|
|
||||||
-0.5, 0.5, -0.5, T1, 1,
|
|
||||||
0.5, 0.5, 0.5, T2, 0.5,
|
|
||||||
0.5, 0.5, -0.5, T2, 1,
|
|
||||||
0.5, 0.5, 0.5, T2, 0.5,
|
|
||||||
-0.5, 0.5, -0.5, T1, 1,
|
|
||||||
|
|
||||||
-0.5, -0.5, -0.5, T2, 0.5,
|
|
||||||
-0.5, -0.5, 0.5, T2, 0,
|
|
||||||
0.5, -0.5, -0.5, T1, 0.5,
|
|
||||||
0.5, -0.5, 0.5, T1, 0,
|
|
||||||
0.5, -0.5, -0.5, T1, 0.5,
|
|
||||||
-0.5, -0.5, 0.5, T2, 0,
|
|
||||||
};
|
|
||||||
const PLANE_MESH_DATA = [_]f32{
|
|
||||||
-0.5, -0.5, 0, 0.0, 1.0,
|
|
||||||
0.5, 0.5, 0, 1.0, 0.0,
|
|
||||||
-0.5, 0.5, 0, 0.0, 0.0,
|
|
||||||
0.5, 0.5, 0, 1.0, 0.0,
|
|
||||||
-0.5, -0.5, 0, 0.0, 1.0,
|
|
||||||
0.5, -0.5, 0, 1.0, 1.0,
|
|
||||||
};
|
|
||||||
const PLANE_MESH_DATA_HALF = [_]f32{
|
|
||||||
-0.25, -0.25, 0, 0.0, 1.0,
|
|
||||||
0.25, 0.25, 0, 1.0, 0.0,
|
|
||||||
-0.25, 0.25, 0, 0.0, 0.0,
|
|
||||||
0.25, 0.25, 0, 1.0, 0.0,
|
|
||||||
-0.25, -0.25, 0, 0.0, 1.0,
|
|
||||||
0.25, -0.25, 0, 1.0, 1.0,
|
|
||||||
};
|
|
||||||
|
Reference in New Issue
Block a user