Commit for 2022.05.29 22-44-19.7z
This commit is contained in:
parent
cf3d1eebc1
commit
22d18c953c
@ -1,16 +1,16 @@
|
||||
{
|
||||
"engine": {
|
||||
"scenes": {
|
||||
"start": "SS2",
|
||||
"meshes": { "interleave": false },
|
||||
"start": "McDonalds",
|
||||
"meshes": { "interleave": true },
|
||||
"matrix": { "reverseInfinite": true },
|
||||
"lights": {
|
||||
"max": 12,
|
||||
"max": 16,
|
||||
"enabled": true
|
||||
},
|
||||
"shadows": {
|
||||
"enabled": true,
|
||||
"update": 4,
|
||||
"update": 3,
|
||||
"max": 6,
|
||||
"samples": 2,
|
||||
"experimental mode": 1
|
||||
@ -48,18 +48,19 @@
|
||||
"validation": {
|
||||
"enabled": false,
|
||||
"filters": [
|
||||
"MessageID = 0x124ffb34", // VUID-VkImageMemoryBarrier-oldLayout-01197
|
||||
"MessageID = 0x8ab1932c", // VUID-VkImageViewCreateInfo-imageViewType-04973
|
||||
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
|
||||
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
|
||||
"MessageID = 0x23e43bb7" // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls)
|
||||
|
||||
// "MessageID = 0xe91b58a0" // VUID-vkCmdDrawIndexed-None-02686 (?)
|
||||
// "MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
|
||||
|
||||
// "MessageID = 0x124ffb34", // VUID-VkImageMemoryBarrier-oldLayout-01197 (hacky bloom-shit)
|
||||
// "MessageID = 0x8ab1932c", // VUID-VkImageViewCreateInfo-imageViewType-04973 (hacky bloom-shit)
|
||||
|
||||
// "MessageID = 0x8e1000ad", // VUID-vkCmdDrawIndexedIndirect-None-04008 (bitches without nullDescriptor)
|
||||
// "MessageID = 0x9dd97212", // VUID-vkCmdDrawIndexedIndirect-None-02721 (bitches without nullDescriptor)
|
||||
// "MessageID = 0x36481fcb", // VUID-vkCmdBindVertexBuffers-pBuffers-04001 (bitches without nullDescriptor)
|
||||
|
||||
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
|
||||
// "MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
|
||||
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
|
||||
"MessageID = 0x23e43bb7" // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls)
|
||||
// "MessageID = 0xe91b58a0" // VUID-vkCmdDrawIndexed-None-02686 (?)
|
||||
]
|
||||
},
|
||||
"framebuffer": {
|
||||
@ -237,6 +238,9 @@
|
||||
"entity": {
|
||||
"delete children on destroy": true,
|
||||
"delete components on destroy": true
|
||||
},
|
||||
"loader": {
|
||||
"assert": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -30,10 +30,11 @@
|
||||
"resolution": 8192,
|
||||
"shadows": 1024,
|
||||
"layers": 1,
|
||||
"trigger": { "mode": "rendered" },
|
||||
"trigger": { "mode": "rendered", "quit": true },
|
||||
// "trigger": { "mode": "key", "value": "B" },
|
||||
"output": "./lightmap.%i.png"
|
||||
},
|
||||
"grid": {
|
||||
"-grid": {
|
||||
"/^worldspawn/": {
|
||||
"size": [6,6,6],
|
||||
// "epsilon": 0.01,
|
||||
|
||||
16
bin/data/scenes/mcdonalds/craeture.json
Normal file
16
bin/data/scenes/mcdonalds/craeture.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Craeture",
|
||||
"behaviors": [ "CraetureBehavior" ],
|
||||
"assets": [
|
||||
"./textures/craeture.jpg"
|
||||
],
|
||||
"transform": {
|
||||
"position": [9.62326, 1.1872, -40.8126],
|
||||
"scale": [8, 8, 8]
|
||||
},
|
||||
"metadata": {
|
||||
"model": {
|
||||
"cull mode": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
bin/data/scenes/mcdonalds/door.json
Normal file
9
bin/data/scenes/mcdonalds/door.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"assets": ["./scripts/door.lua"],
|
||||
"system": {
|
||||
"physics": {
|
||||
"type": "bounding box",
|
||||
"recenter": true
|
||||
}
|
||||
}
|
||||
}
|
||||
32
bin/data/scenes/mcdonalds/loading.json
Normal file
32
bin/data/scenes/mcdonalds/loading.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "Gui: Loading",
|
||||
"type": "Object",
|
||||
"behaviors": [
|
||||
// "GuiBehavior"
|
||||
],
|
||||
"assets": [
|
||||
{ "filename": "./mcdonalds.json", "delay": 0 }
|
||||
],
|
||||
"ignore": false,
|
||||
"transform": {
|
||||
"position": [ -0.830591, -0.699509, 0 ],
|
||||
"rotation": {
|
||||
"axis": [ 1, 0, 0 ],
|
||||
"angle": 0
|
||||
},
|
||||
"scale": [ 0.258737, 0.115371, 1 ]
|
||||
},
|
||||
"metadata": {
|
||||
"uv": [ 0, 0, 1, 1 ],
|
||||
"color": [ 1, 1, 1, 0.1 ],
|
||||
"location": "",
|
||||
"scaling": "relative",
|
||||
"text settings": {
|
||||
"stroke": [ 1, 0.749, 0.368, 1 ],
|
||||
"color": [ 1, 0.749, 0.368, 1 ],
|
||||
|
||||
"string": "Loading...",
|
||||
"string1": "コマンド"
|
||||
}
|
||||
}
|
||||
}
|
||||
24
bin/data/scenes/mcdonalds/marker.json
Normal file
24
bin/data/scenes/mcdonalds/marker.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "Marker",
|
||||
"type": "Gui",
|
||||
"ignore": false,
|
||||
"transform": {
|
||||
"position": [ 0, 0, 0 ],
|
||||
"rotation": {
|
||||
"axis": [ 1, 0, 0 ],
|
||||
"angle": 0
|
||||
},
|
||||
"scale": [ 1, 1, 1 ]
|
||||
},
|
||||
"metadata": {
|
||||
"uv": [ 0, 0, 1, 1 ],
|
||||
"color": [ 1, 1, 1, 0.8 ],
|
||||
"location": "",
|
||||
"scaling": [ 1, 1 ],
|
||||
"world": true,
|
||||
"gui layer": false
|
||||
},
|
||||
"assets": [
|
||||
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_in2.png"
|
||||
]
|
||||
}
|
||||
47
bin/data/scenes/mcdonalds/mcdonalds.json
Normal file
47
bin/data/scenes/mcdonalds/mcdonalds.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"import": "/model.json",
|
||||
"assets": [
|
||||
// { "filename": "./static.json", "delay": 8 },
|
||||
|
||||
// { "filename": "./models/mcdonalds.glb", "delay": 0, "single threaded": false }
|
||||
// { "filename": "./models/mcdonalds/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/mcdonalds/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
|
||||
// { "filename": "./models/mini_mcd.glb", "delay": 0, "single threaded": false }
|
||||
// { "filename": "./models/mini_mcd/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
],
|
||||
"metadata": {
|
||||
"model": {
|
||||
"lightmap": true,
|
||||
"baking": {
|
||||
"enabled": true,
|
||||
"resolution": 2048
|
||||
},
|
||||
"cull mode": "none",
|
||||
"tags": {
|
||||
"/^worldspawn/": {
|
||||
"physics": { "type": "mesh", "static": true },
|
||||
"grid": { "size": [3,2,3], "epsilon": 1.0, "cleanup": true, "print": true }
|
||||
},
|
||||
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },
|
||||
|
||||
"func_door_rotating_5409": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5487": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
|
||||
"func_door_rotating_5495": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
|
||||
"func_door_rotating_5568": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5568": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5576": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5584": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5656": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
|
||||
"func_door_rotating_5664": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5689": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5698": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5712": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
|
||||
"func_physbox_5212": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_physbox_5548": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_physbox_5931": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
bin/data/scenes/mcdonalds/player.json
Normal file
19
bin/data/scenes/mcdonalds/player.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"import": "/player.json",
|
||||
"assets": [
|
||||
// { "filename": "/gui/hud/hud.json", "delay": 0 }
|
||||
],
|
||||
"metadata": {
|
||||
"overlay": {
|
||||
"floating": true
|
||||
},
|
||||
"collider": true,
|
||||
"light": {
|
||||
"should": false,
|
||||
"color": [1, 1, 1],
|
||||
"position": [ 0, 2.5, 0 ],
|
||||
"power": 1,
|
||||
"radius": [0.001, 32]
|
||||
}
|
||||
}
|
||||
}
|
||||
60
bin/data/scenes/mcdonalds/scene.json
Normal file
60
bin/data/scenes/mcdonalds/scene.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"import": "/scene.json",
|
||||
"assets": [
|
||||
"./audio/soundscape/ambience.ogg",
|
||||
"./loading.json",
|
||||
"./static.json"
|
||||
],
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"renderer": {
|
||||
"shader": {
|
||||
"mode": 1,
|
||||
"scalar": 16,
|
||||
"parameters": [ 0, 0, 0, "time" ]
|
||||
},
|
||||
"clear values": [
|
||||
[ 1, 1, 1, 0 ]
|
||||
]
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"menus": {
|
||||
"pause": "/gui/pause/menu.json"
|
||||
},
|
||||
"bloom": {
|
||||
"scale": 6.0,
|
||||
"strength": 0.125,
|
||||
"sigma": 0.125,
|
||||
"samples": 8
|
||||
},
|
||||
"light": {
|
||||
"exposure": 1.0,
|
||||
"gamma": 1.0,
|
||||
"brightnessThreshold": 1.2,
|
||||
// "ambient": [ 0.1, 0.1, 0.1 ],
|
||||
"ambient": [ 0, 0, 0 ],
|
||||
|
||||
"fog-": {
|
||||
"color": [ 0.5, 0.5, 0.5 ],
|
||||
"range": [ 16, 32 ],
|
||||
"step scale": 2,
|
||||
"absorbtion": 0.07,
|
||||
"density": {
|
||||
"threshold": 0.35,
|
||||
"multiplier": 5.0,
|
||||
"scale": 25.0,
|
||||
"offset": [0, -1, 1],
|
||||
"timescale": 8
|
||||
}
|
||||
},
|
||||
"should": true,
|
||||
"shadows": true
|
||||
},
|
||||
"noise": {
|
||||
"size": [ 64, 64, 64 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
110
bin/data/scenes/mcdonalds/scripts/door.lua
Normal file
110
bin/data/scenes/mcdonalds/scripts/door.lua
Normal file
@ -0,0 +1,110 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
|
||||
local polarity = 1
|
||||
local state = 0
|
||||
local targetAlpha = 1
|
||||
local alpha = 0
|
||||
local target = Vector3f(0,0,0)
|
||||
local transform = ent:getComponent("Transform")
|
||||
local metadata = ent:getComponent("Metadata")
|
||||
local speed = metadata["speed"] or 1.0
|
||||
local normal = Vector3f(0,0,-1)
|
||||
if metadata["normal"] ~= nil then
|
||||
local sign = -1
|
||||
if metadata["angle"] < 0 then sign = 1 end
|
||||
normal = Vector3f( metadata["normal"][1] * sign, metadata["normal"][2] * sign, metadata["normal"][3] * sign ):normalize()
|
||||
end
|
||||
local starting = Quaternion(transform.orientation)
|
||||
local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), metadata["angle"] ))
|
||||
local soundEmitter = ent:loadChild("./sound.json",true)
|
||||
local playSound = function( key, loop )
|
||||
if not loop then loop = false end
|
||||
local url = "/door/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = true,
|
||||
streamed = true,
|
||||
volume = "sfx",
|
||||
loop = loop
|
||||
}, 0)
|
||||
end
|
||||
local stopSound = function( key )
|
||||
local url = "/door/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Stop.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"])
|
||||
}, 0)
|
||||
end
|
||||
local playSoundscape = function( key )
|
||||
local url = "/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = false,
|
||||
volume = "sfx",
|
||||
loop = true,
|
||||
streamed = true
|
||||
}, 0)
|
||||
end
|
||||
local stopSoundscape = function( key )
|
||||
local url = "/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Stop.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"])
|
||||
}, 0)
|
||||
end
|
||||
soundEmitter:getComponent("Transform"):setReference( transform )
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
-- transform.orientation = starting:slerp( ending, math.cos(time.current() * speed) * 0.5 + 0.5 )
|
||||
if state == 1 then
|
||||
alpha = alpha + time.delta() * speed
|
||||
|
||||
if alpha > targetAlpha then
|
||||
state = 2
|
||||
alpha = targetAlpha
|
||||
playSound("default_stop")
|
||||
end
|
||||
|
||||
end
|
||||
if state == 3 then
|
||||
alpha = alpha - time.delta() * speed
|
||||
|
||||
if alpha < 0 then
|
||||
state = 0
|
||||
alpha = 0
|
||||
playSound("default_stop")
|
||||
end
|
||||
end
|
||||
|
||||
if state > 0 then
|
||||
transform.orientation = starting:slerp( ending, alpha * polarity )
|
||||
end
|
||||
end )
|
||||
-- on use
|
||||
ent:addHook( "entity:Use.%UID%", function( payload )
|
||||
if state == 0 then
|
||||
state = 1
|
||||
playSound("default_move")
|
||||
if payload.uid ~= nil then
|
||||
local player = entities.get( payload.uid )
|
||||
local pTransform = player:getComponent("Transform")
|
||||
local delta = transform.position - pTransform.position
|
||||
local side = normal:dot(delta)
|
||||
if side > 0 then
|
||||
polarity = 1
|
||||
elseif side < 0 then
|
||||
polarity = -1
|
||||
end
|
||||
end
|
||||
io.print(ent:name())
|
||||
end
|
||||
if state == 2 then
|
||||
state = 3
|
||||
playSound("default_move")
|
||||
end
|
||||
io.print( state, json.encode( payload ) )
|
||||
end )
|
||||
22
bin/data/scenes/mcdonalds/scripts/realign.lua
Normal file
22
bin/data/scenes/mcdonalds/scripts/realign.lua
Normal file
@ -0,0 +1,22 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
|
||||
local transform = ent:getComponent("Transform")
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
local offset = Vector3f(0,0,0)
|
||||
if window.keyPressed("J") then offset.x = offset.x - time.delta() end
|
||||
if window.keyPressed("L") then offset.x = offset.x + time.delta() end
|
||||
if window.keyPressed("N") then offset.y = offset.y - time.delta() end
|
||||
if window.keyPressed("M") then offset.y = offset.y + time.delta() end
|
||||
if window.keyPressed("I") then offset.z = offset.z - time.delta() end
|
||||
if window.keyPressed("K") then offset.z = offset.z + time.delta() end
|
||||
if offset:magnitude() > 0.0001 then
|
||||
transform.position = transform.position + offset
|
||||
end
|
||||
end )
|
||||
90
bin/data/scenes/mcdonalds/scripts/static.lua
Normal file
90
bin/data/scenes/mcdonalds/scripts/static.lua
Normal file
@ -0,0 +1,90 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
-- release control
|
||||
--[[
|
||||
hooks.call("window:Mouse.CursorVisibility", { state = true })
|
||||
hooks.call("window:Mouse.Lock", {});
|
||||
]]
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
-- update static effect
|
||||
local metadatas = {
|
||||
ent = ent:getComponent("Metadata"),
|
||||
scene = scene:getComponent("Metadata")
|
||||
}
|
||||
local transforms = {
|
||||
ent = ent:getComponent("Transform"),
|
||||
controller = controller:getComponent("Transform")
|
||||
}
|
||||
local distanceSquared = transforms.controller.position:distance( transforms.ent.position )
|
||||
distanceSquared = distanceSquared * distanceSquared
|
||||
if type(metadatas.ent["static"]["scale"]) == "number" then
|
||||
distanceSquared = distanceSquared * metadatas.ent["static"]["scale"]
|
||||
end
|
||||
local lo = type(metadatas.ent["static"]["range"][1]) == "number" and metadatas.ent["static"]["range"][1] or 0.1
|
||||
local hi = type(metadatas.ent["static"]["range"][2]) == "number" and metadatas.ent["static"]["range"][2] or 0.5
|
||||
local staticBlend = distanceSquared > 1 and 1.0 / distanceSquared or 1.0
|
||||
staticBlend = math.clamp( staticBlend, lo, hi )
|
||||
|
||||
local flicker = type(metadatas.ent["static"]["flicker"]) == "number" and metadatas.ent["static"]["flicker"] or 0.001
|
||||
local pieces = type(metadatas.ent["static"]["pieces"]) == "number" and metadatas.ent["static"]["pieces"] or 1000
|
||||
|
||||
local payload = {
|
||||
mode = 2,
|
||||
parameters = {
|
||||
[1] = flicker,
|
||||
[2] = pieces,
|
||||
[3] = staticBlend,
|
||||
[4] = "time"
|
||||
}
|
||||
}
|
||||
scene:callHook("shader:Update.%UID%", payload)
|
||||
end )
|
||||
|
||||
--[[
|
||||
local hud = ent:loadChild("/hud.json", true)
|
||||
hud:bind( "tick", function(self)
|
||||
-- update distance HUD element
|
||||
if timer:elapsed() <= 0.0125 then return end
|
||||
timer:reset()
|
||||
|
||||
local metadata = self:getComponent("Metadata")
|
||||
local transforms = {
|
||||
controller = controller:getComponent("Transform"),
|
||||
source = ent:getComponent("Transform")
|
||||
}
|
||||
local distance = transforms.controller.position:distance( transforms.source.position )
|
||||
--distance = string.si( distance, "m" )
|
||||
local maximum = 40
|
||||
local value = math.floor(distance/maximum * 100)
|
||||
if value >= 100 then value = 100 end
|
||||
distance = "Sanity: " .. value .. "%"
|
||||
--distance = math.floor((15-distance)/15 * 100) .. "%"
|
||||
if metadata["text settings"]["string"] ~= distance then
|
||||
self:callHook( "gui:UpdateString.%UID%", {
|
||||
string = distance
|
||||
} )
|
||||
end
|
||||
end )
|
||||
]]
|
||||
--[[
|
||||
local marker = ent:loadChild("./marker.json", true)
|
||||
marker:bind( "tick", function(self)
|
||||
local transform = marker:getComponent("Transform")
|
||||
local parentTransform = ent:getComponent("Transform")
|
||||
local controllerTransform = controller:getComponent("Transform")
|
||||
|
||||
local controllerCamera = controller:getComponent("Camera")
|
||||
local controllerCameraTransform = controllerCamera:getTransform()
|
||||
|
||||
transform.position = parentTransform.position + Vector3f(0,3,0)
|
||||
transform.orientation = Quaternion.lookAt( transform.position - controllerTransform.position, Vector3f(0,1,0) )
|
||||
-- transform.orientation = transform.orientation:normalize()
|
||||
-- transform.model = controllerCamera:getProjection() * controllerCamera:getView() * Matrix4f.translate( transform.position ) * transform.orientation:matrix()
|
||||
end )
|
||||
]]
|
||||
34
bin/data/scenes/mcdonalds/sound.json
Normal file
34
bin/data/scenes/mcdonalds/sound.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"type": "Object",
|
||||
"name": "Sound Emitter",
|
||||
"ignore": false,
|
||||
"assets": [
|
||||
],
|
||||
"behaviors": [
|
||||
"SoundEmitterBehavior"
|
||||
],
|
||||
"transform": {
|
||||
"reference": true
|
||||
},
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"defaults": {
|
||||
"render": true,
|
||||
"asset load": true
|
||||
},
|
||||
"load": {
|
||||
"ignore": true
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"audio": {
|
||||
"spatial": true,
|
||||
"loop": false,
|
||||
"volume": 1,
|
||||
"rolloffFactor": 0.5,
|
||||
"epsilon": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
48
bin/data/scenes/mcdonalds/static.json
Normal file
48
bin/data/scenes/mcdonalds/static.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"type": "Object",
|
||||
"name": "Static Emitter",
|
||||
"ignore": false,
|
||||
"assets": [
|
||||
"/overworld/static.ogg",
|
||||
"./scripts/static.lua"
|
||||
],
|
||||
"behaviors": [
|
||||
"SoundEmitterBehavior"
|
||||
],
|
||||
"transform": {
|
||||
"position": [ -13.4342, 2.43658, 298.797 ],
|
||||
"rotation": {
|
||||
"axis": [ 0, 1, 0 ],
|
||||
"angle": 0
|
||||
},
|
||||
"scale": [ 1, 1, 1 ]
|
||||
},
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"defaults": {
|
||||
"render": true,
|
||||
"asset load": true
|
||||
},
|
||||
"load": {
|
||||
"ignore": true
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"audio": {
|
||||
"spatial": true,
|
||||
"loop": true,
|
||||
"streamed": false,
|
||||
"volume": 1.6,
|
||||
"rolloffFactor": 2
|
||||
},
|
||||
"static": {
|
||||
"range": [ 0.0025, 1 ],
|
||||
"flicker": 0.5,
|
||||
"pieces": 16,
|
||||
"scale": 0.4
|
||||
},
|
||||
"distance": false
|
||||
}
|
||||
}
|
||||
16
bin/data/scenes/sh2_mcdonalds/craeture.json
Normal file
16
bin/data/scenes/sh2_mcdonalds/craeture.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Craeture",
|
||||
"behaviors": [ "CraetureBehavior" ],
|
||||
"assets": [
|
||||
"./textures/craeture.jpg"
|
||||
],
|
||||
"transform": {
|
||||
"position": [19.9875, 1.54269, -2.97276],
|
||||
"scale": [1.5, 2, 1.5]
|
||||
},
|
||||
"metadata": {
|
||||
"model": {
|
||||
"cull mode": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
11
bin/data/scenes/sh2_mcdonalds/door.json
Normal file
11
bin/data/scenes/sh2_mcdonalds/door.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"assets": ["./scripts/door.lua"],
|
||||
"system": {
|
||||
"physics": {
|
||||
"mass": 0,
|
||||
"inertia": [0, 0, 0],
|
||||
"type": "bounding box",
|
||||
"recenter": true
|
||||
}
|
||||
}
|
||||
}
|
||||
32
bin/data/scenes/sh2_mcdonalds/loading.json
Normal file
32
bin/data/scenes/sh2_mcdonalds/loading.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "Gui: Loading",
|
||||
"type": "Object",
|
||||
"behaviors": [
|
||||
// "GuiBehavior"
|
||||
],
|
||||
"assets": [
|
||||
{ "filename": "./sh2_mcdonalds.json", "delay": 0 }
|
||||
],
|
||||
"ignore": false,
|
||||
"transform": {
|
||||
"position": [ -0.830591, -0.699509, 0 ],
|
||||
"rotation": {
|
||||
"axis": [ 1, 0, 0 ],
|
||||
"angle": 0
|
||||
},
|
||||
"scale": [ 0.258737, 0.115371, 1 ]
|
||||
},
|
||||
"metadata": {
|
||||
"uv": [ 0, 0, 1, 1 ],
|
||||
"color": [ 1, 1, 1, 0.1 ],
|
||||
"location": "",
|
||||
"scaling": "relative",
|
||||
"text settings": {
|
||||
"stroke": [ 1, 0.749, 0.368, 1 ],
|
||||
"color": [ 1, 0.749, 0.368, 1 ],
|
||||
|
||||
"string": "Loading...",
|
||||
"string1": "コマンド"
|
||||
}
|
||||
}
|
||||
}
|
||||
24
bin/data/scenes/sh2_mcdonalds/marker.json
Normal file
24
bin/data/scenes/sh2_mcdonalds/marker.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "Marker",
|
||||
"type": "Gui",
|
||||
"ignore": false,
|
||||
"transform": {
|
||||
"position": [ 0, 0, 0 ],
|
||||
"rotation": {
|
||||
"axis": [ 1, 0, 0 ],
|
||||
"angle": 0
|
||||
},
|
||||
"scale": [ 1, 1, 1 ]
|
||||
},
|
||||
"metadata": {
|
||||
"uv": [ 0, 0, 1, 1 ],
|
||||
"color": [ 1, 1, 1, 0.8 ],
|
||||
"location": "",
|
||||
"scaling": [ 1, 1 ],
|
||||
"world": true,
|
||||
"gui layer": false
|
||||
},
|
||||
"assets": [
|
||||
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_in2.png"
|
||||
]
|
||||
}
|
||||
20
bin/data/scenes/sh2_mcdonalds/player.json
Normal file
20
bin/data/scenes/sh2_mcdonalds/player.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"import": "/player.json",
|
||||
"assets": [
|
||||
// { "filename": "/gui/hud/hud.json", "delay": 0 }
|
||||
"./playerLight.json"
|
||||
],
|
||||
"metadata": {
|
||||
"overlay": {
|
||||
"floating": true
|
||||
},
|
||||
"collider": true,
|
||||
"light": {
|
||||
"should": false,
|
||||
"color": [1, 1, 1],
|
||||
"position": [ 0, 2.5, 0 ],
|
||||
"power": 1,
|
||||
"radius": [0.001, 32]
|
||||
}
|
||||
}
|
||||
}
|
||||
32
bin/data/scenes/sh2_mcdonalds/playerLight.json
Normal file
32
bin/data/scenes/sh2_mcdonalds/playerLight.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"import": "/light.json",
|
||||
"ignore": true,
|
||||
"assets": [
|
||||
],
|
||||
"transform": {
|
||||
"track": "parent",
|
||||
"position": [ 0, 1.7, 0 ]
|
||||
},
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"light": {
|
||||
"type": "point",
|
||||
"color": [1, 1, 1],
|
||||
"power": 15,
|
||||
"fov": 90,
|
||||
"bias": {
|
||||
"constant": 1.25,
|
||||
"slope": 1.75,
|
||||
"shader": 0.000005 //0.000000005
|
||||
},
|
||||
"radius": [0.001, 0],
|
||||
"resolution": 1024,
|
||||
"shadows": false,
|
||||
"static": false
|
||||
}
|
||||
}
|
||||
}
|
||||
11
bin/data/scenes/sh2_mcdonalds/prop.json
Normal file
11
bin/data/scenes/sh2_mcdonalds/prop.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"assets": [],
|
||||
"system": {
|
||||
"physics": {
|
||||
"mass": 0,
|
||||
"inertia": [0, 0, 0],
|
||||
"type": "bounding box",
|
||||
"recenter": true
|
||||
}
|
||||
}
|
||||
}
|
||||
60
bin/data/scenes/sh2_mcdonalds/scene.json
Normal file
60
bin/data/scenes/sh2_mcdonalds/scene.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"import": "/scene.json",
|
||||
"assets": [
|
||||
"./audio/soundscape/ambience.ogg",
|
||||
"./loading.json"
|
||||
// "./static.json"
|
||||
],
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"renderer": {
|
||||
"shader": {
|
||||
"mode": 1,
|
||||
"scalar": 16,
|
||||
"parameters": [ 0, 0, 0, "time" ]
|
||||
},
|
||||
"clear values": [
|
||||
[ 1, 1, 1, 0 ]
|
||||
]
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"menus": {
|
||||
"pause": "/gui/pause/menu.json"
|
||||
},
|
||||
"bloom": {
|
||||
"scale": 1.0,
|
||||
"strength": 1.0,
|
||||
"sigma": 2.0,
|
||||
"samples": 2
|
||||
},
|
||||
"light": {
|
||||
"exposure": 1.0,
|
||||
"gamma": 1.0,
|
||||
"brightnessThreshold": 1.2,
|
||||
|
||||
"ambient": [ 0.15, 0.15, 0.15 ],
|
||||
|
||||
"fog": {
|
||||
"color": [ 0.5, 0.5, 0.5 ],
|
||||
"range": [ 8, 256 ],
|
||||
"step scale": 2,
|
||||
"absorbtion": 0.07,
|
||||
"density": {
|
||||
"threshold": 0.35,
|
||||
"multiplier": 5.0,
|
||||
"scale": 25.0,
|
||||
"offset": [0.2, 0, 1],
|
||||
"timescale": 8
|
||||
}
|
||||
},
|
||||
"should": true,
|
||||
"shadows": true
|
||||
},
|
||||
"noise": {
|
||||
"size": [ 16, 16, 16 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
107
bin/data/scenes/sh2_mcdonalds/scripts/door.lua
Normal file
107
bin/data/scenes/sh2_mcdonalds/scripts/door.lua
Normal file
@ -0,0 +1,107 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
|
||||
local polarity = 1
|
||||
local state = 0
|
||||
local targetAlpha = 1
|
||||
local alpha = 0
|
||||
local target = Vector3f(0,0,0)
|
||||
local transform = ent:getComponent("Transform")
|
||||
local metadata = ent:getComponent("Metadata")
|
||||
local speed = metadata["speed"] or 1.0
|
||||
local normal = Vector3f(0,0,-1)
|
||||
if metadata["normal"] ~= nil then
|
||||
local sign = -1
|
||||
if metadata["angle"] < 0 then sign = 1 end
|
||||
normal = Vector3f( metadata["normal"][1] * sign, metadata["normal"][2] * sign, metadata["normal"][3] * sign ):normalize()
|
||||
end
|
||||
local starting = Quaternion(transform.orientation)
|
||||
local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), metadata["angle"] ))
|
||||
local soundEmitter = ent:loadChild("./sound.json",true)
|
||||
local playSound = function( key, loop )
|
||||
if not loop then loop = false end
|
||||
local url = "/door/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = true,
|
||||
streamed = true,
|
||||
volume = "sfx",
|
||||
loop = loop
|
||||
}, 0)
|
||||
end
|
||||
local stopSound = function( key )
|
||||
local url = "/door/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Stop.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"])
|
||||
}, 0)
|
||||
end
|
||||
local playSoundscape = function( key )
|
||||
local url = "/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Emit.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"]),
|
||||
spatial = false,
|
||||
volume = "sfx",
|
||||
loop = true,
|
||||
streamed = true
|
||||
}, 0)
|
||||
end
|
||||
local stopSoundscape = function( key )
|
||||
local url = "/soundscape/" .. key .. ".ogg"
|
||||
soundEmitter:queueHook("sound:Stop.%UID%", {
|
||||
filename = string.resolveURI(url, metadata["system"]["root"])
|
||||
}, 0)
|
||||
end
|
||||
soundEmitter:getComponent("Transform"):setReference( transform )
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
-- transform.orientation = starting:slerp( ending, math.cos(time.current() * speed) * 0.5 + 0.5 )
|
||||
if state == 1 then
|
||||
alpha = alpha + time.delta() * speed
|
||||
|
||||
if alpha > targetAlpha then
|
||||
state = 2
|
||||
alpha = targetAlpha
|
||||
playSound("default_stop")
|
||||
end
|
||||
|
||||
end
|
||||
if state == 3 then
|
||||
alpha = alpha - time.delta() * speed
|
||||
|
||||
if alpha < 0 then
|
||||
state = 0
|
||||
alpha = 0
|
||||
playSound("default_stop")
|
||||
end
|
||||
end
|
||||
|
||||
if state > 0 then
|
||||
transform.orientation = starting:slerp( ending, alpha * polarity )
|
||||
end
|
||||
end )
|
||||
-- on use
|
||||
ent:addHook( "entity:Use.%UID%", function( payload )
|
||||
if state == 0 or state == 3 then
|
||||
state = 1
|
||||
playSound("default_move")
|
||||
if payload.uid ~= nil then
|
||||
local player = entities.get( payload.uid )
|
||||
local pTransform = player:getComponent("Transform")
|
||||
local delta = transform.position - pTransform.position
|
||||
local side = normal:dot(delta)
|
||||
if side > 0 then
|
||||
polarity = 1
|
||||
elseif side < 0 then
|
||||
polarity = -1
|
||||
end
|
||||
end
|
||||
elseif state == 2 or state == 1 then
|
||||
state = 3
|
||||
playSound("default_move")
|
||||
end
|
||||
end )
|
||||
22
bin/data/scenes/sh2_mcdonalds/scripts/realign.lua
Normal file
22
bin/data/scenes/sh2_mcdonalds/scripts/realign.lua
Normal file
@ -0,0 +1,22 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
|
||||
local transform = ent:getComponent("Transform")
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
local offset = Vector3f(0,0,0)
|
||||
if window.keyPressed("J") then offset.x = offset.x - time.delta() end
|
||||
if window.keyPressed("L") then offset.x = offset.x + time.delta() end
|
||||
if window.keyPressed("N") then offset.y = offset.y - time.delta() end
|
||||
if window.keyPressed("M") then offset.y = offset.y + time.delta() end
|
||||
if window.keyPressed("I") then offset.z = offset.z - time.delta() end
|
||||
if window.keyPressed("K") then offset.z = offset.z + time.delta() end
|
||||
if offset:magnitude() > 0.0001 then
|
||||
transform.position = transform.position + offset
|
||||
end
|
||||
end )
|
||||
90
bin/data/scenes/sh2_mcdonalds/scripts/static.lua
Normal file
90
bin/data/scenes/sh2_mcdonalds/scripts/static.lua
Normal file
@ -0,0 +1,90 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local timer = Timer.new()
|
||||
if not timer:running() then
|
||||
timer:start();
|
||||
end
|
||||
-- release control
|
||||
--[[
|
||||
hooks.call("window:Mouse.CursorVisibility", { state = true })
|
||||
hooks.call("window:Mouse.Lock", {});
|
||||
]]
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
-- update static effect
|
||||
local metadatas = {
|
||||
ent = ent:getComponent("Metadata"),
|
||||
scene = scene:getComponent("Metadata")
|
||||
}
|
||||
local transforms = {
|
||||
ent = ent:getComponent("Transform"),
|
||||
controller = controller:getComponent("Transform")
|
||||
}
|
||||
local distanceSquared = transforms.controller.position:distance( transforms.ent.position )
|
||||
distanceSquared = distanceSquared * distanceSquared
|
||||
if type(metadatas.ent["static"]["scale"]) == "number" then
|
||||
distanceSquared = distanceSquared * metadatas.ent["static"]["scale"]
|
||||
end
|
||||
local lo = type(metadatas.ent["static"]["range"][1]) == "number" and metadatas.ent["static"]["range"][1] or 0.1
|
||||
local hi = type(metadatas.ent["static"]["range"][2]) == "number" and metadatas.ent["static"]["range"][2] or 0.5
|
||||
local staticBlend = distanceSquared > 1 and 1.0 / distanceSquared or 1.0
|
||||
staticBlend = math.clamp( staticBlend, lo, hi )
|
||||
|
||||
local flicker = type(metadatas.ent["static"]["flicker"]) == "number" and metadatas.ent["static"]["flicker"] or 0.001
|
||||
local pieces = type(metadatas.ent["static"]["pieces"]) == "number" and metadatas.ent["static"]["pieces"] or 1000
|
||||
|
||||
local payload = {
|
||||
mode = 2,
|
||||
parameters = {
|
||||
[1] = flicker,
|
||||
[2] = pieces,
|
||||
[3] = staticBlend,
|
||||
[4] = "time"
|
||||
}
|
||||
}
|
||||
scene:callHook("shader:Update.%UID%", payload)
|
||||
end )
|
||||
|
||||
--[[
|
||||
local hud = ent:loadChild("/hud.json", true)
|
||||
hud:bind( "tick", function(self)
|
||||
-- update distance HUD element
|
||||
if timer:elapsed() <= 0.0125 then return end
|
||||
timer:reset()
|
||||
|
||||
local metadata = self:getComponent("Metadata")
|
||||
local transforms = {
|
||||
controller = controller:getComponent("Transform"),
|
||||
source = ent:getComponent("Transform")
|
||||
}
|
||||
local distance = transforms.controller.position:distance( transforms.source.position )
|
||||
--distance = string.si( distance, "m" )
|
||||
local maximum = 40
|
||||
local value = math.floor(distance/maximum * 100)
|
||||
if value >= 100 then value = 100 end
|
||||
distance = "Sanity: " .. value .. "%"
|
||||
--distance = math.floor((15-distance)/15 * 100) .. "%"
|
||||
if metadata["text settings"]["string"] ~= distance then
|
||||
self:callHook( "gui:UpdateString.%UID%", {
|
||||
string = distance
|
||||
} )
|
||||
end
|
||||
end )
|
||||
]]
|
||||
--[[
|
||||
local marker = ent:loadChild("./marker.json", true)
|
||||
marker:bind( "tick", function(self)
|
||||
local transform = marker:getComponent("Transform")
|
||||
local parentTransform = ent:getComponent("Transform")
|
||||
local controllerTransform = controller:getComponent("Transform")
|
||||
|
||||
local controllerCamera = controller:getComponent("Camera")
|
||||
local controllerCameraTransform = controllerCamera:getTransform()
|
||||
|
||||
transform.position = parentTransform.position + Vector3f(0,3,0)
|
||||
transform.orientation = Quaternion.lookAt( transform.position - controllerTransform.position, Vector3f(0,1,0) )
|
||||
-- transform.orientation = transform.orientation:normalize()
|
||||
-- transform.model = controllerCamera:getProjection() * controllerCamera:getView() * Matrix4f.translate( transform.position ) * transform.orientation:matrix()
|
||||
end )
|
||||
]]
|
||||
11
bin/data/scenes/sh2_mcdonalds/scripts/trackPlayer.lua
Normal file
11
bin/data/scenes/sh2_mcdonalds/scripts/trackPlayer.lua
Normal file
@ -0,0 +1,11 @@
|
||||
local scene = entities.currentScene()
|
||||
local controller = entities.controller()
|
||||
|
||||
local transform = ent:getComponent("Transform")
|
||||
local controllerTransform = controller:getComponent("Transform")
|
||||
local offset = Vector3f(0,1,0) -- transform.position
|
||||
io.print("TRACKING PLAYER")
|
||||
-- on tick
|
||||
ent:bind( "tick", function(self)
|
||||
transform.position = offset + controllerTransform.position
|
||||
end )
|
||||
110
bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json
Normal file
110
bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json
Normal file
@ -0,0 +1,110 @@
|
||||
{
|
||||
"import": "/model.json",
|
||||
"assets": [
|
||||
// { "filename": "./static.json", "delay": 8 },
|
||||
|
||||
{ "filename": "./models/sh_mcd.glb", "delay": 0, "single threaded": false }
|
||||
// { "filename": "./models/sh_mcd/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/sh_mcd/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
],
|
||||
"metadata": {
|
||||
"model": {
|
||||
"cull mode": "none",
|
||||
"alpha mode": "BLEND",
|
||||
"grid": {
|
||||
"/^worldspawn/": {
|
||||
"size": [4,4,4],
|
||||
// "epsilon": 0.01,
|
||||
"cleanup": true,
|
||||
"print": true
|
||||
},
|
||||
"/^worldspawn_sh2/": {
|
||||
"size": [32,32,32],
|
||||
// "epsilon": 0.01,
|
||||
"cleanup": true,
|
||||
"print": true
|
||||
}
|
||||
},
|
||||
"tags": {
|
||||
"worldspawn": { "physics": { "type": "mesh", "static": true } },
|
||||
// "worldspawn_sh2": { "physics": { "type": "mesh", "static": true } },
|
||||
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },
|
||||
|
||||
"func_door_rotating_5409": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5487": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
|
||||
"func_door_rotating_5495": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
|
||||
"func_door_rotating_5656": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
|
||||
"func_door_rotating_5664": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5689": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5698": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5712": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
|
||||
"func_physbox_5212": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_physbox_5548": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_physbox_5931": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
|
||||
"func_door_rotating_5568": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5576": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
"func_door_rotating_5584": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
|
||||
|
||||
"func_physbox_5212": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_5548": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_5931": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5839": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5848": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5857": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5864": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5872": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5879": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5886": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5893": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5905": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"func_physbox_multiplayer_5913": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5563": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5564": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5687": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5719": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5721": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5722": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5815": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5816": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5817": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5818": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5819": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5820": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_multiplayer_5821": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5227": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5373": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5374": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5375": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5545": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5546": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5565": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5566": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5591": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5675": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5680": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5681": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5682": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5683": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5684": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5685": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5696": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5707": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5723": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5749": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5750": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5760": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5764": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5787": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5807": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5808": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5809": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5810": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5814": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5822": { "action": "load", "payload": { "import": "./prop.json" } },
|
||||
"prop_physics_override_5824": { "action": "load", "payload": { "import": "./prop.json" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
bin/data/scenes/sh2_mcdonalds/sound.json
Normal file
34
bin/data/scenes/sh2_mcdonalds/sound.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"type": "Object",
|
||||
"name": "Sound Emitter",
|
||||
"ignore": false,
|
||||
"assets": [
|
||||
],
|
||||
"behaviors": [
|
||||
"SoundEmitterBehavior"
|
||||
],
|
||||
"transform": {
|
||||
"reference": true
|
||||
},
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"defaults": {
|
||||
"render": true,
|
||||
"asset load": true
|
||||
},
|
||||
"load": {
|
||||
"ignore": true
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"audio": {
|
||||
"spatial": true,
|
||||
"loop": false,
|
||||
"volume": 1,
|
||||
"rolloffFactor": 0.5,
|
||||
"epsilon": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
48
bin/data/scenes/sh2_mcdonalds/static.json
Normal file
48
bin/data/scenes/sh2_mcdonalds/static.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"type": "Object",
|
||||
"name": "Static Emitter",
|
||||
"ignore": false,
|
||||
"assets": [
|
||||
"/overworld/static.ogg",
|
||||
"./scripts/static.lua"
|
||||
],
|
||||
"behaviors": [
|
||||
"SoundEmitterBehavior"
|
||||
],
|
||||
"transform": {
|
||||
"position": [ -13.4342, 2.43658, 298.797 ],
|
||||
"rotation": {
|
||||
"axis": [ 0, 1, 0 ],
|
||||
"angle": 0
|
||||
},
|
||||
"scale": [ 1, 1, 1 ]
|
||||
},
|
||||
"system": {
|
||||
"hot reload": {
|
||||
"enabled": true
|
||||
},
|
||||
"defaults": {
|
||||
"render": true,
|
||||
"asset load": true
|
||||
},
|
||||
"load": {
|
||||
"ignore": true
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"audio": {
|
||||
"spatial": true,
|
||||
"loop": true,
|
||||
"streamed": false,
|
||||
"volume": 1.6,
|
||||
"rolloffFactor": 2
|
||||
},
|
||||
"static": {
|
||||
"range": [ 0.0025, 1 ],
|
||||
"flicker": 0.5,
|
||||
"pieces": 16,
|
||||
"scale": 0.4
|
||||
},
|
||||
"distance": false
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,16 @@
|
||||
{
|
||||
"import": "/model.json",
|
||||
"assets": [
|
||||
// { "filename": "./craeture.json", "delay": 1 },
|
||||
|
||||
// { "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/tiny_msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
|
||||
// { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
|
||||
// { "filename": "./craeture.json", "delay": 1 }
|
||||
|
||||
// { "filename": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
@ -21,31 +22,17 @@
|
||||
],
|
||||
"metadata": {
|
||||
"model": {
|
||||
"exporter": {
|
||||
"enabled": true
|
||||
},
|
||||
"baking": {
|
||||
"enabled": false,
|
||||
"resolution": 2048, // 8192
|
||||
"shadows": 1024,
|
||||
"layers": 22,
|
||||
"trigger": { "mode": "rendered" },
|
||||
// "trigger": { "mode": "key", "value": "B" },
|
||||
"output": "./lightmap.%i.png"
|
||||
},
|
||||
"grid": {
|
||||
"/^worldspawn/": {
|
||||
"size": [3,3,3]
|
||||
}
|
||||
},
|
||||
// "lightmap": "./lightmap.%i.min.png",
|
||||
// "lightmap": false,
|
||||
"lightmap": true,
|
||||
"baking": {
|
||||
"enabled": true,
|
||||
"resolution": 1024
|
||||
},
|
||||
"filter": "LINEAR",
|
||||
"tags": {
|
||||
"worldspawn": { "physics": { "type": "mesh", "static": true } },
|
||||
"worldspawn_20": { "physics": { "type": "mesh", "static": true } },
|
||||
// "worldspawn": { "physics": { "type": "bounding boxes", "static": true } },
|
||||
"/^worldspawn/": {
|
||||
"physics": { "type": "mesh", "static": true },
|
||||
"grid": { "size": [5,2,5], "epsilon": 1.0, "cleanup": true, "print": true }
|
||||
},
|
||||
"info_player_spawn": {
|
||||
"action": "attach",
|
||||
"filename": "./player.json",
|
||||
|
||||
@ -32,6 +32,19 @@ vec2 encodeNormals( vec3 n ) {
|
||||
// return n.xy/p + 0.5;
|
||||
return (vec2(atan(n.y,n.x)/PI, n.z)+1.0)*0.5;
|
||||
}
|
||||
vec3 encodeSrgb(vec3 rgb) {
|
||||
const vec3 a = 12.92 * rgb;
|
||||
const vec3 b = 1.055 * pow(rgb, vec3(1.0 / 2.4)) - 0.055;
|
||||
const vec3 c = step(vec3(0.0031308), rgb);
|
||||
return mix(a, b, c);
|
||||
}
|
||||
|
||||
vec3 decodeSrgb(vec3 rgb) {
|
||||
const vec3 a = rgb / 12.92;
|
||||
const vec3 b = pow((rgb + 0.055) / 1.055, vec3(2.4));
|
||||
const vec3 c = step(vec3(0.04045), rgb);
|
||||
return mix(a, b, c);
|
||||
}
|
||||
bool validTextureIndex( int textureIndex ) {
|
||||
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ void lambert() {
|
||||
const vec3 diffuse = surface.material.albedo.rgb;
|
||||
const vec3 specular = vec3(0);
|
||||
|
||||
surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.fragment.a += light.power * La * Ls;
|
||||
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.light.a += light.power * La * Ls;
|
||||
}
|
||||
}
|
||||
9
bin/data/shaders/common/light.h
Normal file
9
bin/data/shaders/common/light.h
Normal file
@ -0,0 +1,9 @@
|
||||
#if PBR
|
||||
#include "../common/pbr.h"
|
||||
#endif
|
||||
#if LAMBERT
|
||||
#include "../common/lambert.h"
|
||||
#endif
|
||||
#if PHONG
|
||||
#include "../common/phong.h"
|
||||
#endif
|
||||
@ -13,7 +13,7 @@ float gaSchlickGGX(float cosLi, float cosLo, float roughness) {
|
||||
return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k);
|
||||
}
|
||||
vec3 fresnelSchlick(vec3 F0, float cosTheta) { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); }
|
||||
#if !BAKING
|
||||
#if !BAKING && !COMPUTE
|
||||
void pbr() {
|
||||
if ( validTextureIndex( surface.instance.lightmapID ) ) return;
|
||||
|
||||
@ -42,13 +42,15 @@ void pbr() {
|
||||
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
|
||||
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
|
||||
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
|
||||
/*
|
||||
// lightmapped, compute only specular
|
||||
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) surface.fragment.rgb += (specular) * Lr * cosLi;
|
||||
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) surface.light.rgb += (specular) * Lr * cosLi;
|
||||
// point light, compute only diffuse
|
||||
// else if ( abs(light.type) == 1 ) surface.fragment.rgb += (diffuse) * Lr * cosLi;
|
||||
else surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.fragment.a += light.power * La * Ls;
|
||||
// else if ( abs(light.type) == 1 ) surface.light.rgb += (diffuse) * Lr * cosLi;
|
||||
else surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
*/
|
||||
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.light.a += light.power * La * Ls;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -158,6 +158,7 @@ struct Surface {
|
||||
SurfaceMaterial material;
|
||||
Instance instance;
|
||||
|
||||
vec4 light;
|
||||
vec4 fragment;
|
||||
} surface;
|
||||
|
||||
|
||||
@ -162,7 +162,7 @@ void indirectLighting() {
|
||||
indirectSpecular = voxelConeTrace( ray, SPECULAR_CONE_APERTURE );
|
||||
// outFragColor.rgb = indirectSpecular.rgb; return;
|
||||
if ( length(indirectSpecular) < 0.0125 ) {
|
||||
// indirectSpecular += (1.0 - indirectSpecular.a) * texture( samplerSkybox, R );
|
||||
// indirectSpecular += (1.0 - indirectSpecular.a) * texture( samplerCubemaps[ubo.indexSkybox], R ) * SPECULAR_CONE_APERTURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -101,7 +101,7 @@ layout (location = 1) out vec4 outFragBright;
|
||||
|
||||
#include "../common/functions.h"
|
||||
#include "../common/fog.h"
|
||||
#include "../common/pbr.h"
|
||||
#include "../common/light.h"
|
||||
#include "../common/shadows.h"
|
||||
#if VXGI
|
||||
#include "../common/vxgi.h"
|
||||
@ -236,11 +236,11 @@ void populateSurface() {
|
||||
}
|
||||
// Lightmap
|
||||
if ( validTextureIndex( surface.instance.lightmapID ) ) {
|
||||
surface.material.albedo.rgb *= sampleTexture( surface.instance.lightmapID, surface.st ).rgb;
|
||||
surface.light += surface.material.albedo * sampleTexture( surface.instance.lightmapID, surface.st );
|
||||
}
|
||||
// Emissive textures
|
||||
if ( validTextureIndex( material.indexEmissive ) ) {
|
||||
surface.material.albedo += sampleTexture( material.indexEmissive );
|
||||
surface.light += sampleTexture( material.indexEmissive );
|
||||
}
|
||||
// Occlusion map
|
||||
if ( validTextureIndex( material.indexOcclusion ) ) {
|
||||
@ -262,15 +262,8 @@ void populateSurface() {
|
||||
}
|
||||
|
||||
void directLighting() {
|
||||
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion + surface.material.indirect.rgb;
|
||||
// surface.fragment.rgb += surface.material.albedo.rgb * ambient;
|
||||
|
||||
if ( validTextureIndex( surface.instance.lightmapID ) ) {
|
||||
surface.fragment.rgb += surface.material.albedo.rgb + ambient;
|
||||
} else {
|
||||
surface.fragment.rgb += surface.material.albedo.rgb * ambient;
|
||||
}
|
||||
// if ( ubo.lights == 0 ) { surface.fragment.rgb = surface.material.albedo.rgb; return; }
|
||||
surface.light.rgb += surface.material.albedo.rgb * ubo.ambient.rgb * surface.material.occlusion; // add ambient lighting
|
||||
surface.light.rgb += surface.material.indirect.rgb; // add indirect lighting
|
||||
#if PBR
|
||||
pbr();
|
||||
#elif LAMBERT
|
||||
@ -278,6 +271,7 @@ void directLighting() {
|
||||
#elif PHONG
|
||||
phong();
|
||||
#endif
|
||||
surface.fragment.rgb += surface.light.rgb;
|
||||
}
|
||||
|
||||
#if MULTISAMPLING
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
|
||||
|
||||
|
||||
#define LAMBERT 1
|
||||
#define PBR 0
|
||||
#define LAMBERT 0
|
||||
#define PBR 1
|
||||
#define VXGI 1
|
||||
#define COMPUTE 1
|
||||
|
||||
@ -72,6 +72,7 @@ layout (binding = 13, rg16f) uniform volatile coherent image3D voxelNormal[CASCA
|
||||
#endif
|
||||
|
||||
#include "../common/functions.h"
|
||||
#include "../common/light.h"
|
||||
#undef VXGI
|
||||
#include "../common/shadows.h"
|
||||
|
||||
@ -96,6 +97,7 @@ void main() {
|
||||
const Material material = materials[surface.instance.materialID];
|
||||
surface.material.albedo = material.colorBase;
|
||||
surface.fragment = material.colorEmissive;
|
||||
/*
|
||||
#if DEFERRED_SAMPLING
|
||||
{
|
||||
vec4 uv = imageLoad(voxelUv[CASCADE], ivec3(tUvw) );
|
||||
@ -127,20 +129,19 @@ void main() {
|
||||
#else
|
||||
surface.material.albedo = imageLoad(voxelRadiance[CASCADE], ivec3(tUvw) );
|
||||
#endif
|
||||
*/
|
||||
surface.material.albedo = imageLoad(voxelRadiance[CASCADE], ivec3(tUvw) );
|
||||
surface.material.metallic = material.factorMetallic;
|
||||
surface.material.roughness = material.factorRoughness;
|
||||
surface.material.occlusion = material.factorOcclusion;
|
||||
|
||||
float litFactor = 1.0;
|
||||
const vec3 ambient = ubo.ambient.rgb * surface.material.occlusion;
|
||||
if ( validTextureIndex( surface.instance.lightmapID ) ) {
|
||||
surface.fragment.rgb += surface.material.albedo.rgb + ubo.ambient.rgb * surface.material.occlusion;
|
||||
surface.fragment.rgb += surface.material.albedo.rgb;
|
||||
} else {
|
||||
surface.fragment.rgb += surface.material.albedo.rgb * ubo.ambient.rgb * surface.material.occlusion;
|
||||
}
|
||||
// corrections
|
||||
surface.material.roughness *= 4.0;
|
||||
if ( !validTextureIndex( surface.instance.lightmapID ) )
|
||||
{
|
||||
surface.fragment.rgb += surface.material.albedo.rgb * ambient;
|
||||
// corrections
|
||||
surface.material.roughness *= 4.0;
|
||||
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
|
||||
const vec3 Lo = normalize( surface.position.world );
|
||||
const float cosLo = max(0.0, dot(surface.normal.world, Lo));
|
||||
@ -171,14 +172,19 @@ void main() {
|
||||
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
|
||||
#endif
|
||||
// lightmapped, compute only specular
|
||||
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) surface.fragment.rgb += (specular) * Lr * cosLi;
|
||||
/*
|
||||
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) surface.light.rgb += (specular) * Lr * cosLi;
|
||||
// point light, compute only diffuse
|
||||
// else if ( abs(light.type) == 1 ) surface.fragment.rgb += (diffuse) * Lr * cosLi;
|
||||
else surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.fragment.a += light.power * La * Ls;
|
||||
// else if ( abs(light.type) == 1 ) surface.light.rgb += (diffuse) * Lr * cosLi;
|
||||
else surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
*/
|
||||
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.light.a += light.power * La * Ls;
|
||||
}
|
||||
}
|
||||
|
||||
surface.fragment.rgb += surface.light.rgb;
|
||||
|
||||
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
|
||||
}
|
||||
}
|
||||
@ -67,8 +67,9 @@ void main() {
|
||||
surface.material.roughness = material.factorRoughness;
|
||||
surface.material.occlusion = 1.0f - material.factorOcclusion;
|
||||
|
||||
surface.fragment = material.colorEmissive;
|
||||
surface.light = material.colorEmissive;
|
||||
surface.material.albedo = vec4(1);
|
||||
#if 1
|
||||
{
|
||||
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
|
||||
for ( uint i = 0; i < lights.length(); ++i ) {
|
||||
@ -107,22 +108,61 @@ void main() {
|
||||
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
|
||||
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
|
||||
#endif
|
||||
surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.fragment.a += light.power * La * Ls;
|
||||
|
||||
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.light.a += light.power * La * Ls;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
// corrections
|
||||
surface.material.roughness *= 4.0;
|
||||
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
|
||||
const vec3 Lo = normalize( surface.position.world );
|
||||
const float cosLo = max(0.0, dot(surface.normal.world, Lo));
|
||||
for ( uint i = 0; i < lights.length(); ++i ) {
|
||||
const Light light = lights[i];
|
||||
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
|
||||
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) continue;
|
||||
const vec3 Lp = light.position;
|
||||
const vec3 Liu = light.position - surface.position.world;
|
||||
const vec3 Li = normalize(Liu);
|
||||
const float Ls = shadowFactor( light, 0.0 );
|
||||
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
|
||||
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
|
||||
|
||||
#define EXPOSURE 1
|
||||
#define GAMMA 1
|
||||
const float cosLi = max(0.0, dot(surface.normal.world, Li));
|
||||
const vec3 Lr = light.color.rgb * light.power * La * Ls;
|
||||
#if LAMBERT
|
||||
const vec3 diffuse = surface.material.albedo.rgb;
|
||||
const vec3 specular = vec3(0);
|
||||
#elif PBR
|
||||
const vec3 Lh = normalize(Li + Lo);
|
||||
const float cosLh = max(0.0, dot(surface.normal.world, Lh));
|
||||
|
||||
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
|
||||
const float D = ndfGGX( cosLh, surface.material.roughness );
|
||||
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
|
||||
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
|
||||
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
|
||||
#endif
|
||||
|
||||
// surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * EXPOSURE);
|
||||
// surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / GAMMA));
|
||||
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.light.a += light.power * La * Ls;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#define EXPOSURE 0
|
||||
#define GAMMA 0
|
||||
|
||||
outAlbedo = vec4(surface.fragment.rgb, 1);
|
||||
// surface.light.rgb = vec3(1.0) - exp(-surface.light.rgb * EXPOSURE);
|
||||
// surface.light.rgb = pow(surface.light.rgb, vec3(1.0 / GAMMA));
|
||||
|
||||
outAlbedo = vec4(surface.light.rgb, 1);
|
||||
|
||||
{
|
||||
const vec2 st = inSt.xy * imageSize(outAlbedos).xy;
|
||||
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(inLayer));
|
||||
imageStore(outAlbedos, uvw, vec4(surface.fragment.rgb, 1) );
|
||||
imageStore(outAlbedos, uvw, vec4(surface.light.rgb, 1) );
|
||||
}
|
||||
}
|
||||
@ -35,6 +35,8 @@ namespace uf {
|
||||
static uf::Asset::Payload resolveToPayload( const uf::stl::string&, const uf::stl::string& = "" );
|
||||
static bool isExpected( const uf::Asset::Payload&, uf::Asset::Type expected );
|
||||
|
||||
static bool assertionLoad;
|
||||
|
||||
// URL or file path
|
||||
void processQueue();
|
||||
|
||||
|
||||
@ -9,9 +9,7 @@
|
||||
#include <uf/utils/memory/pool.h>
|
||||
|
||||
namespace uf {
|
||||
class UF_API Object;
|
||||
class UF_API Entity : public uf::Behaviors {
|
||||
//friend class EntityBehavior;
|
||||
public:
|
||||
typedef uf::stl::vector<uf::Entity*> container_t;
|
||||
static uf::Entity null;
|
||||
@ -36,8 +34,8 @@ namespace uf {
|
||||
std::size_t getUid() const;
|
||||
void setName( const uf::stl::string& );
|
||||
// cast to other Entity classes, avoid nasty shit like *((uf::Object*) &entity)
|
||||
template<typename T=uf::Object> T& as();
|
||||
template<typename T=uf::Object> const T& as() const;
|
||||
template<typename T> T& as();
|
||||
template<typename T> const T& as() const;
|
||||
// parent-child relationship
|
||||
bool hasParent() const;
|
||||
template<typename T=uf::Entity> T& getParent();
|
||||
|
||||
@ -44,6 +44,7 @@ namespace uf {
|
||||
} load;
|
||||
|
||||
bool ignoreGraph = false;
|
||||
bool invalid = false;
|
||||
} system;
|
||||
struct {
|
||||
pod::Transform<> initial;
|
||||
|
||||
@ -13,6 +13,8 @@ namespace uf {
|
||||
class UF_API Object : public uf::Entity {
|
||||
public:
|
||||
static uf::Timer<long long> timer;
|
||||
static bool assertionLoad;
|
||||
|
||||
Object();
|
||||
|
||||
bool reload( bool = false );
|
||||
|
||||
@ -56,6 +56,7 @@ namespace uf {
|
||||
pod::Thread& UF_API fetchWorker( const uf::stl::string& name = "Aux" );
|
||||
void UF_API batchWorker( const pod::Thread::function_t&, const uf::stl::string& name = "Aux" );
|
||||
void UF_API batchWorkers( const uf::stl::vector<pod::Thread::function_t>&, bool = true, const uf::stl::string& name = "Aux" );
|
||||
void UF_API batchWorkers_Async( const uf::stl::vector<pod::Thread::function_t>&, bool = true, const uf::stl::string& name = "Aux" );
|
||||
void UF_API add( pod::Thread&, const pod::Thread::function_t&, bool = false );
|
||||
void UF_API process( pod::Thread& );
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ namespace {
|
||||
}
|
||||
|
||||
uf::Asset uf::Asset::masterAssetLoader;
|
||||
bool uf::Asset::assertionLoad = true;
|
||||
|
||||
void uf::Asset::processQueue() {
|
||||
uf::thread::batchWorker( [&](){
|
||||
@ -223,18 +224,30 @@ uf::stl::string uf::Asset::cache( const uf::Asset::Payload& payload ) {
|
||||
uf::stl::string hash = uf::string::sha256( filename );
|
||||
uf::stl::string cached = uf::io::root + "/cache/http/" + hash + "." + extension;
|
||||
if ( !uf::io::exists( cached ) && !retrieve( filename, cached, hash ) ) {
|
||||
UF_MSG_ERROR("Failed to preload `" + filename + "` (`" + cached + "`): HTTP error");
|
||||
if ( !uf::Asset::assertionLoad ) {
|
||||
UF_MSG_ERROR("Failed to preload `" + filename + "` (`" + cached + "`): HTTP error");
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to preload `" + filename + "` (`" + cached + "`): HTTP error");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
filename = cached;
|
||||
}
|
||||
if ( !uf::io::exists( filename ) ) {
|
||||
UF_MSG_ERROR("Failed to preload `" + filename + "`: Does not exist");
|
||||
if ( !uf::Asset::assertionLoad ) {
|
||||
UF_MSG_ERROR("Failed to preload `" + filename + "`: Does not exist");
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to preload `" + filename + "`: Does not exist");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
uf::stl::string actual = payload.hash;
|
||||
if ( payload.hash != "" && (actual = uf::io::hash( filename )) != payload.hash ) {
|
||||
UF_MSG_ERROR("Failed to preload `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
if ( !uf::Asset::assertionLoad ) {
|
||||
UF_MSG_ERROR("Failed to preload `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to preload `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return filename;
|
||||
@ -247,18 +260,30 @@ uf::stl::string uf::Asset::load(const uf::Asset::Payload& payload ) {
|
||||
uf::stl::string hash = uf::string::sha256( payload.filename );
|
||||
uf::stl::string cached = uf::io::root + "/cache/http/" + hash + "." + extension;
|
||||
if ( !uf::io::exists( cached ) && !retrieve( payload.filename, cached, hash ) ) {
|
||||
UF_MSG_ERROR("Failed to load `" + payload.filename + "` (`" + cached + "`): HTTP error");
|
||||
if ( !uf::Asset::assertionLoad ) {
|
||||
UF_MSG_ERROR("Failed to load `" + payload.filename + "` (`" + cached + "`): HTTP error");
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to load `" + payload.filename + "` (`" + cached + "`): HTTP error");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
filename = cached;
|
||||
}
|
||||
if ( !uf::io::exists( filename ) ) {
|
||||
UF_MSG_ERROR("Failed to load `" + filename + "`: Does not exist");
|
||||
if ( !uf::Asset::assertionLoad ) {
|
||||
UF_MSG_ERROR("Failed to load `" + filename + "`: Does not exist");
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to load `" + filename + "`: Does not exist");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
uf::stl::string actual = payload.hash;
|
||||
if ( payload.hash != "" && (actual = uf::io::hash( filename )) != payload.hash ) {
|
||||
UF_MSG_ERROR("Failed to load `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
if ( !uf::Asset::assertionLoad ) {
|
||||
UF_MSG_ERROR("Failed to load `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to load `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#if UF_ENV_DREAMCAST
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 0
|
||||
#else
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 0
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 1 // causes Vulkan OOM
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
@ -428,7 +428,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
|
||||
graph.root = decodeNode( serializer["root"], graph );
|
||||
});
|
||||
#if UF_GRAPH_LOAD_MULTITHREAD
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
|
||||
#else
|
||||
for ( auto& job : jobs ) job();
|
||||
#endif
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#if UF_ENV_DREAMCAST
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 0
|
||||
#else
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 0
|
||||
#define UF_GRAPH_LOAD_MULTITHREAD 1 // causes Vulkan OOM
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
@ -427,7 +427,7 @@ void uf::graph::save( const pod::Graph& graph, const uf::stl::string& filename )
|
||||
serializer["root"] = encode(graph.root, settings);
|
||||
});
|
||||
#if UF_GRAPH_LOAD_MULTITHREAD
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
|
||||
#else
|
||||
for ( auto& job : jobs ) job();
|
||||
#endif
|
||||
|
||||
@ -367,31 +367,37 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
//
|
||||
if ( !graph.root.entity ) graph.root.entity = new uf::Object;
|
||||
|
||||
//
|
||||
uf::stl::unordered_map<uf::stl::string, bool> isSrgb;
|
||||
|
||||
// process lightmap
|
||||
#if UF_USE_OPENGL
|
||||
#define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.%i.min.dtex"
|
||||
#else
|
||||
#define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.%i.png"
|
||||
#endif
|
||||
if ( graph.metadata["lightmap"].as<bool>() ) {
|
||||
{
|
||||
uf::stl::unordered_map<size_t, uf::stl::string> filenames;
|
||||
uf::stl::unordered_map<size_t, size_t> lightmapIDs;
|
||||
|
||||
UF_MSG_DEBUG( graph.instances.size() );
|
||||
uint32_t lightmapCount = 0;
|
||||
|
||||
for ( auto& name : graph.instances ) {
|
||||
auto& instance = uf::graph::storage.instances[name];
|
||||
// if ( !instance.auxID ) break;
|
||||
filenames[instance.auxID] = uf::string::replace(UF_GRAPH_DEFAULT_LIGHTMAP, "%i", std::to_string(instance.auxID));
|
||||
|
||||
lightmapCount = std::max( lightmapCount, instance.auxID );
|
||||
}
|
||||
for ( auto& name : graph.primitives ) {
|
||||
auto& primitives = uf::graph::storage.primitives[name];
|
||||
for ( auto& primitive : primitives ) {
|
||||
// if ( !primitive.instance.auxID ) break;
|
||||
filenames[primitive.instance.auxID] = uf::string::replace(UF_GRAPH_DEFAULT_LIGHTMAP, "%i", std::to_string(primitive.instance.auxID));
|
||||
|
||||
lightmapCount = std::max( lightmapCount, primitive.instance.auxID );
|
||||
}
|
||||
}
|
||||
for ( auto& pair : filenames ) {
|
||||
graph.metadata["baking"]["layers"] = lightmapCount;
|
||||
|
||||
if ( graph.metadata["lightmap"].as<bool>() ) for ( auto& pair : filenames ) {
|
||||
auto i = pair.first;
|
||||
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
|
||||
|
||||
@ -399,6 +405,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
UF_MSG_ERROR( "lightmap does not exist: " << f )
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
auto textureID = graph.textures.size();
|
||||
auto imageID = graph.images.size();
|
||||
@ -413,6 +420,8 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
|
||||
graph.metadata["lightmaps"][i] = f;
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
|
||||
isSrgb[f] = false;
|
||||
}
|
||||
|
||||
for ( auto& name : graph.instances ) {
|
||||
@ -427,38 +436,6 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
primitive.instance.lightmapID = lightmapIDs[primitive.instance.auxID];
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
const uf::stl::string lightmapFilename = graph.metadata["lightmap"].as<uf::stl::string>(UF_GRAPH_DEFAULT_LIGHTMAP);
|
||||
// load lightmap, if requested
|
||||
if ( lightmapFilename != "" ) {
|
||||
// check if valid filename, if not it's a texture name
|
||||
uf::stl::string f = uf::io::sanitize( lightmapFilename, uf::io::directory( graph.name ) );
|
||||
if ( uf::io::exists( f ) ) {
|
||||
auto textureID = graph.textures.size();
|
||||
auto imageID = graph.images.size();
|
||||
|
||||
auto& texture = /*graph.storage*/uf::graph::storage.textures[graph.textures.emplace_back(f)];
|
||||
auto& image = /*graph.storage*/uf::graph::storage.images[graph.images.emplace_back(f)];
|
||||
image.open( f, false );
|
||||
|
||||
texture.index = imageID;
|
||||
|
||||
for ( auto& name : graph.instances ) {
|
||||
auto& instance = uf::graph::storage.instances[name];
|
||||
instance.lightmapID = textureID;
|
||||
}
|
||||
for ( auto& name : graph.primitives ) {
|
||||
auto& primitives = uf::graph::storage.primitives[name];
|
||||
for ( auto& primitive : primitives ) {
|
||||
primitive.instance.lightmapID = textureID;
|
||||
}
|
||||
}
|
||||
|
||||
graph.metadata["lightmapped"] = f;
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// add atlas
|
||||
|
||||
@ -480,19 +457,21 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
if ( !(0 <= ID && ID < graph.textures.size()) ) continue;
|
||||
|
||||
auto texName = graph.textures[ID];
|
||||
auto& texture = uf::graph::storage.texture2Ds[texName];
|
||||
texture.srgb = true;
|
||||
isSrgb[texName] = true;
|
||||
}
|
||||
|
||||
for ( auto& key : graph.images ) {
|
||||
auto& image = uf::graph::storage.images[key];
|
||||
auto& texture = uf::graph::storage.texture2Ds[key];
|
||||
if ( !texture.generated() ) {
|
||||
bool isLightmap = graph.metadata["lightmapped"].as<uf::stl::string>() == key;
|
||||
auto filter = graph.metadata["filter"].as<uf::stl::string>() == "NEAREST" && !isLightmap ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR;
|
||||
// bool isLightmap = graph.metadata["lightmapped"].as<uf::stl::string>() == key;
|
||||
// auto filter = graph.metadata["filter"].as<uf::stl::string>() == "NEAREST" && !isLightmap ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR;
|
||||
// auto filter = uf::renderer::enums::Filter::LINEAR;
|
||||
|
||||
auto filter = graph.metadata["filter"].as<uf::stl::string>() == "NEAREST" ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR;
|
||||
texture.sampler.descriptor.filter.min = filter;
|
||||
texture.sampler.descriptor.filter.mag = filter;
|
||||
texture.srgb = isSrgb.count(key) == 0 ? false : isSrgb[key];
|
||||
|
||||
texture.loadFromImage( image );
|
||||
#if UF_ENV_DREAMCAST
|
||||
@ -706,40 +685,40 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
// on systems where frametime is very, very important, we can set all static nodes to not tick
|
||||
|
||||
// tie to tag
|
||||
{
|
||||
ext::json::Value info = ext::json::null();
|
||||
if ( ext::json::isObject( graph.metadata["tags"][node.name] ) ) {
|
||||
info = graph.metadata["tags"][node.name];
|
||||
} else {
|
||||
ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
if ( !uf::string::isRegex( key ) ) return;
|
||||
if ( uf::string::matches( node.name, key ).empty() ) return;
|
||||
info = value;
|
||||
});
|
||||
}
|
||||
if ( ext::json::isObject( info ) ) {
|
||||
if ( info["ignore"].as<bool>() ) return;
|
||||
ext::json::Value tag = ext::json::null();
|
||||
/*
|
||||
if ( ext::json::isObject( graph.metadata["tags"][node.name] ) ) {
|
||||
tag = graph.metadata["tags"][node.name];
|
||||
}
|
||||
*/
|
||||
ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
if ( uf::string::isRegex( key ) ) {
|
||||
if ( uf::string::matches( node.name, key ).empty() ) return;
|
||||
} else if ( node.name != key ) return;
|
||||
tag = value;
|
||||
});
|
||||
if ( ext::json::isObject( tag ) ) {
|
||||
if ( tag["ignore"].as<bool>() ) return;
|
||||
|
||||
if ( info["action"].as<uf::stl::string>() == "load" ) {
|
||||
if ( info["filename"].is<uf::stl::string>() ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
entity.load(filename);
|
||||
} else if ( ext::json::isObject( info["payload"] ) ) {
|
||||
uf::Serializer json = info["payload"];
|
||||
json["root"] = graph.metadata["root"];
|
||||
entity.load(json);
|
||||
}
|
||||
} else if ( info["action"].as<uf::stl::string>() == "attach" ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
auto& child = entity.loadChild( filename, false );
|
||||
auto& childTransform = child.getComponent<pod::Transform<>>();
|
||||
auto flatten = uf::transform::flatten( node.transform );
|
||||
if ( !info["preserve position"].as<bool>() ) childTransform.position = flatten.position;
|
||||
if ( !info["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
|
||||
}
|
||||
if ( info["static"].is<bool>() ) {
|
||||
metadata.system.ignoreGraph = info["static"].as<bool>();
|
||||
if ( tag["action"].as<uf::stl::string>() == "load" ) {
|
||||
if ( tag["filename"].is<uf::stl::string>() ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( tag["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
entity.load(filename);
|
||||
} else if ( ext::json::isObject( tag["payload"] ) ) {
|
||||
uf::Serializer json = tag["payload"];
|
||||
json["root"] = graph.metadata["root"];
|
||||
entity.load(json);
|
||||
}
|
||||
} else if ( tag["action"].as<uf::stl::string>() == "attach" ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( tag["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
auto& child = entity.loadChild( filename, false );
|
||||
auto& childTransform = child.getComponent<pod::Transform<>>();
|
||||
auto flatten = uf::transform::flatten( node.transform );
|
||||
if ( !tag["preserve position"].as<bool>() ) childTransform.position = flatten.position;
|
||||
if ( !tag["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
|
||||
}
|
||||
if ( tag["static"].is<bool>() ) {
|
||||
metadata.system.ignoreGraph = tag["static"].as<bool>();
|
||||
}
|
||||
}
|
||||
// create as light
|
||||
@ -790,27 +769,24 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
transform = node.transform;
|
||||
transform.reference = &parent.getComponent<pod::Transform<>>();
|
||||
// override transform
|
||||
if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) {
|
||||
auto& info = graph.metadata["tags"][node.name];
|
||||
if ( info["transform"]["offset"].as<bool>() ) {
|
||||
auto parsed = uf::transform::decode( info["transform"], pod::Transform<>{} );
|
||||
transform.position += parsed.position;
|
||||
transform.orientation = uf::quaternion::multiply( transform.orientation, parsed.orientation );
|
||||
} else {
|
||||
transform = uf::transform::decode( info["transform"], transform );
|
||||
if ( info["transform"]["parent"].is<uf::stl::string>() ) {
|
||||
auto* parentPointer = uf::graph::find( graph, info["transform"]["parent"].as<uf::stl::string>() );
|
||||
if ( parentPointer ) {
|
||||
auto& parentNode = *parentPointer;
|
||||
// entity already exists, bind to its transform
|
||||
if ( parentNode.entity && parentNode.entity->hasComponent<pod::Transform<>>() ) {
|
||||
auto& parentTransform = parentNode.entity->getComponent<pod::Transform<>>();
|
||||
transform = uf::transform::reference( transform, parentTransform, info["transform"]["reorient"].as<bool>() );
|
||||
transform.position = -transform.position;
|
||||
// doesnt exist, bind to the node transform
|
||||
} else {
|
||||
transform = uf::transform::reference( transform, parentNode.transform, info["transform"]["reorient"].as<bool>() );
|
||||
}
|
||||
if ( tag["transform"]["offset"].as<bool>() ) {
|
||||
auto parsed = uf::transform::decode( tag["transform"], pod::Transform<>{} );
|
||||
transform.position += parsed.position;
|
||||
transform.orientation = uf::quaternion::multiply( transform.orientation, parsed.orientation );
|
||||
} else {
|
||||
transform = uf::transform::decode( tag["transform"], transform );
|
||||
if ( tag["transform"]["parent"].is<uf::stl::string>() ) {
|
||||
auto* parentPointer = uf::graph::find( graph, tag["transform"]["parent"].as<uf::stl::string>() );
|
||||
if ( parentPointer ) {
|
||||
auto& parentNode = *parentPointer;
|
||||
// entity already exists, bind to its transform
|
||||
if ( parentNode.entity && parentNode.entity->hasComponent<pod::Transform<>>() ) {
|
||||
auto& parentTransform = parentNode.entity->getComponent<pod::Transform<>>();
|
||||
transform = uf::transform::reference( transform, parentTransform, tag["transform"]["reorient"].as<bool>() );
|
||||
transform.position = -transform.position;
|
||||
// doesnt exist, bind to the node transform
|
||||
} else {
|
||||
transform = uf::transform::reference( transform, parentNode.transform, tag["transform"]["reorient"].as<bool>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -860,23 +836,23 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
uf::graph::initializeGraphics( graph, entity );
|
||||
}
|
||||
|
||||
if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) {
|
||||
auto info = graph.metadata["tags"][node.name]["physics"];
|
||||
if ( !ext::json::isObject( info ) ) info = metadataJson["system"]["physics"];
|
||||
else metadataJson["system"]["physics"] = info;
|
||||
{
|
||||
auto phyziks = tag["physics"];
|
||||
if ( !ext::json::isObject( phyziks ) ) phyziks = metadataJson["system"]["physics"];
|
||||
else metadataJson["system"]["physics"] = phyziks;
|
||||
|
||||
if ( ext::json::isObject( info ) ) {
|
||||
uf::stl::string type = info["type"].as<uf::stl::string>();
|
||||
if ( ext::json::isObject( phyziks ) ) {
|
||||
uf::stl::string type = phyziks["type"].as<uf::stl::string>();
|
||||
|
||||
if ( type == "mesh" ) {
|
||||
auto& collider = entity.getComponent<pod::PhysicsState>();
|
||||
collider.stats.mass = info["mass"].as(collider.stats.mass);
|
||||
collider.stats.friction = info["friction"].as(collider.stats.friction);
|
||||
collider.stats.restitution = info["restitution"].as(collider.stats.restitution);
|
||||
collider.stats.inertia = uf::vector::decode( info["inertia"], collider.stats.inertia );
|
||||
collider.stats.gravity = uf::vector::decode( info["gravity"], collider.stats.gravity );
|
||||
collider.stats.mass = phyziks["mass"].as(collider.stats.mass);
|
||||
collider.stats.friction = phyziks["friction"].as(collider.stats.friction);
|
||||
collider.stats.restitution = phyziks["restitution"].as(collider.stats.restitution);
|
||||
collider.stats.inertia = uf::vector::decode( phyziks["inertia"], collider.stats.inertia );
|
||||
collider.stats.gravity = uf::vector::decode( phyziks["gravity"], collider.stats.gravity );
|
||||
|
||||
uf::physics::impl::create( entity.as<uf::Object>(), mesh, !info["static"].as<bool>(true) );
|
||||
uf::physics::impl::create( entity.as<uf::Object>(), mesh, !phyziks["static"].as<bool>(true) );
|
||||
} else {
|
||||
auto min = uf::matrix::multiply<float>( model, bounds.min, 1.0f );
|
||||
auto max = uf::matrix::multiply<float>( model, bounds.max, 1.0f );
|
||||
|
||||
@ -10,10 +10,14 @@
|
||||
#include <uf/utils/mesh/mesh.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
|
||||
uf::Timer<long long> uf::Object::timer(false);
|
||||
/*
|
||||
namespace {
|
||||
uf::Object null;
|
||||
}
|
||||
*/
|
||||
|
||||
uf::Timer<long long> uf::Object::timer(false);
|
||||
bool uf::Object::assertionLoad = true;
|
||||
|
||||
UF_OBJECT_REGISTER_BEGIN(uf::Object)
|
||||
UF_OBJECT_REGISTER_BEHAVIOR(uf::EntityBehavior)
|
||||
@ -432,7 +436,14 @@ uf::Object& uf::Object::loadChild( const uf::stl::string& f, bool initialize ) {
|
||||
uf::Serializer json;
|
||||
uf::stl::string filename = uf::io::resolveURI( f, metadata.system.root );
|
||||
if ( !json.readFromFile(filename) ) {
|
||||
return ::null;
|
||||
if ( !uf::Object::assertionLoad ) {
|
||||
UF_MSG_ERROR("assertionLoad is unset, loading empty entity");
|
||||
auto& entity = uf::instantiator::instantiate("Object");
|
||||
entity.getComponent<uf::ObjectBehavior::Metadata>().system.invalid = true;
|
||||
this->addChild(entity);
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to load file: " << filename);
|
||||
}
|
||||
}
|
||||
|
||||
json["source"] = filename;
|
||||
@ -445,33 +456,39 @@ uf::Object& uf::Object::loadChild( const uf::Serializer& _json, bool initialize
|
||||
uf::Serializer json = _json;
|
||||
uf::stl::string type = json["type"].as<uf::stl::string>();
|
||||
if ( type == "" ) type = "Object";
|
||||
if ( json["ignore"].as<bool>() ) return ::null;
|
||||
|
||||
uf::Entity& entity = uf::instantiator::instantiate(type);
|
||||
uf::Object& object = entity.as<uf::Object>();
|
||||
this->addChild(entity);
|
||||
if ( json["ignore"].as<bool>() ) return object;
|
||||
if ( !object.load(json) ) {
|
||||
this->removeChild(entity);
|
||||
return ::null;
|
||||
if ( !uf::Object::assertionLoad ) {
|
||||
UF_MSG_ERROR("assertionLoad is unset, loading empty entity");
|
||||
entity.getComponent<uf::ObjectBehavior::Metadata>().system.invalid = true;
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to load JSON: " << json);
|
||||
}
|
||||
}
|
||||
if ( initialize ) entity.initialize();
|
||||
return object;
|
||||
}
|
||||
uf::Object* uf::Object::loadChildPointer( const uf::stl::string& f, bool initialize ) {
|
||||
uf::Object* pointer = &this->loadChild(f, initialize);
|
||||
return pointer != &::null ? pointer : NULL;
|
||||
return pointer;
|
||||
// return pointer != &::null ? pointer : NULL;
|
||||
}
|
||||
uf::Object* uf::Object::loadChildPointer( const uf::Serializer& json, bool initialize ) {
|
||||
uf::Object* pointer = &this->loadChild(json, initialize);
|
||||
return pointer != &::null ? pointer : NULL;
|
||||
return pointer;
|
||||
// return pointer != &::null ? pointer : NULL;
|
||||
}
|
||||
std::size_t uf::Object::loadChildUid( const uf::stl::string& f, bool initialize ) {
|
||||
size_t uf::Object::loadChildUid( const uf::stl::string& f, bool initialize ) {
|
||||
uf::Object* pointer = this->loadChildPointer(f, initialize);
|
||||
return pointer ? pointer->getUid() : -1;
|
||||
return pointer ? pointer->getUid() : 0;
|
||||
}
|
||||
std::size_t uf::Object::loadChildUid( const uf::Serializer& json, bool initialize ) {
|
||||
size_t uf::Object::loadChildUid( const uf::Serializer& json, bool initialize ) {
|
||||
uf::Object* pointer = this->loadChildPointer(json, initialize);
|
||||
return pointer ? pointer->getUid() : -1;
|
||||
return pointer ? pointer->getUid() : 0;
|
||||
}
|
||||
|
||||
uf::stl::string uf::Object::grabURI( const uf::stl::string& filename, const uf::stl::string& root ) {
|
||||
|
||||
@ -243,17 +243,15 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
bool print = false;
|
||||
bool cleanup = true;
|
||||
} meshgrid;
|
||||
|
||||
if ( ext::json::isObject( graph.metadata["grid"][m.name] ) ) {
|
||||
meshgrid.metadata = graph.metadata["grid"][m.name];
|
||||
} else {
|
||||
ext::json::forEach( graph.metadata["grid"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
if ( !ext::json::isNull( meshgrid.metadata["size"] ) ) return;
|
||||
if ( !uf::string::isRegex( key ) ) return;
|
||||
|
||||
ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
if ( !ext::json::isObject( value["grid"] ) ) return; // no tag["grid"] defined
|
||||
if ( ext::json::isNull( value["grid"]["size"] ) ) return; // no tag["grid"]["size"] defined
|
||||
if ( uf::string::isRegex( key ) ) {
|
||||
if ( uf::string::matches( m.name, key ).empty() ) return;
|
||||
meshgrid.metadata = value;
|
||||
});
|
||||
}
|
||||
} else if ( m.name != key ) return;
|
||||
meshgrid.metadata = value["grid"];
|
||||
});
|
||||
|
||||
if ( ext::json::isObject( meshgrid.metadata ) ) {
|
||||
if ( meshgrid.metadata["size"].is<size_t>() ) {
|
||||
@ -267,6 +265,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
meshgrid.print = meshgrid.metadata["print"].as(meshgrid.print);
|
||||
meshgrid.cleanup = meshgrid.metadata["cleanup"].as(meshgrid.cleanup);
|
||||
}
|
||||
|
||||
|
||||
if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) {
|
||||
#define UF_GRAPH_MESH_FORMAT uf::graph::mesh::Skinned, uint32_t
|
||||
@ -505,7 +504,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
}
|
||||
// generate STs
|
||||
#if UF_USE_XATLAS
|
||||
{
|
||||
if ( graph.metadata["exporter"]["unwrap"].as<bool>() ) {
|
||||
UF_MSG_DEBUG( "Generating ST's..." );
|
||||
size_t atlases = ext::xatlas::unwrap( graph );
|
||||
UF_MSG_DEBUG( "Generated ST's for " << atlases << " lightmaps" );
|
||||
@ -514,6 +513,10 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
|
||||
if ( graph.metadata["exporter"]["enabled"].as<bool>() ) {
|
||||
uf::graph::save( graph, filename );
|
||||
// disable baking, doesn't output right if baking from a gltf imported model
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
// disable lightmap loading, 99.999% of the time a previously baked lightmap will not work due to changing STs
|
||||
graph.metadata["lightmap"] = false;
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
|
||||
@ -155,6 +155,8 @@ for ( auto& p : m.primitives ) {
|
||||
#undef COPY_INDICES
|
||||
}
|
||||
|
||||
|
||||
|
||||
meshlet.primitive.instance.materialID = p.material;
|
||||
meshlet.primitive.instance.primitiveID = meshlets.size() - 1;
|
||||
meshlet.primitive.instance.meshID = meshID;
|
||||
@ -195,8 +197,7 @@ if ( meshgrid.grid.divisions.x > 1 && meshgrid.grid.divisions.y > 1 && meshgrid.
|
||||
.materialID = meshlet.primitive.drawCommand.materialID,
|
||||
.vertices = meshlet.vertices.size(),
|
||||
});
|
||||
//UF_MSG_DEBUG( );
|
||||
|
||||
|
||||
primitives.emplace_back( meshlet.primitive );
|
||||
|
||||
indexID += meshlet.indices.size();
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
#if UF_USE_XATLAS
|
||||
#include <xatlas/xatlas.h>
|
||||
|
||||
#define UF_XATLAS_UNWRAP_MULTITHREAD 1
|
||||
#define UF_XATLAS_LAZY 1 // i do not understand why it needs to insert extra vertices for it to not even be used in the indices buffer, this flag avoids having to account for it
|
||||
|
||||
size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
struct Entry {
|
||||
size_t index = 0;
|
||||
@ -134,15 +137,37 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
packOptions.bilinear = true;
|
||||
|
||||
// pack
|
||||
pod::Thread::container_t jobs;
|
||||
|
||||
for ( auto& pair : atlases ) {
|
||||
jobs.emplace_back([&]{
|
||||
auto& atlas = pair.second;
|
||||
::xatlas::Generate(atlas.pointer, chartOptions, packOptions);
|
||||
/*
|
||||
// get vertices size ahead of time
|
||||
for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) {
|
||||
auto& xmesh = atlas.pointer->meshes[i];
|
||||
auto& entry = atlas.entries[i];
|
||||
// atlas.vertices += xmesh.vertexCount;
|
||||
sizes[entry.index] += xmesh.vertexCount;
|
||||
}
|
||||
*/
|
||||
});
|
||||
}
|
||||
|
||||
#if UF_XATLAS_UNWRAP_MULTITHREAD
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
|
||||
#else
|
||||
for ( auto& job : jobs ) job();
|
||||
#endif
|
||||
|
||||
#if !UF_XATLAS_LAZY
|
||||
for ( auto& pair : atlases ) {
|
||||
auto& atlas = pair.second;
|
||||
::xatlas::Generate(atlas.pointer, chartOptions, packOptions);
|
||||
|
||||
// get vertices size ahead of time
|
||||
for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) {
|
||||
auto& xmesh = atlas.pointer->meshes[i];
|
||||
auto& entry = atlas.entries[i];
|
||||
// atlas.vertices += xmesh.vertexCount;
|
||||
sizes[entry.index] += xmesh.vertexCount;
|
||||
}
|
||||
}
|
||||
@ -151,13 +176,16 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
for ( auto i = 0; i < graph.meshes.size(); ++i ) {
|
||||
auto& name = graph.meshes[i];
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
|
||||
|
||||
mesh.resizeVertices( sizes[i] );
|
||||
mesh.updateDescriptor();
|
||||
if ( sizes[i] != mesh.vertex.count ) {
|
||||
mesh.resizeVertices( sizes[i] );
|
||||
mesh.updateDescriptor();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// update vertices
|
||||
for ( auto& pair : atlases ) {
|
||||
size_t vertexIDOffset = 0;
|
||||
auto& atlas = pair.second;
|
||||
for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) {
|
||||
auto& xmesh = atlas.pointer->meshes[i];
|
||||
@ -166,32 +194,47 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
|
||||
auto& source = sources[entry.index];
|
||||
|
||||
|
||||
// draw commands
|
||||
if ( mesh.indirect.count ) {
|
||||
// vertices
|
||||
auto srcInput = source.remapVertexInput( entry.commandID );
|
||||
auto dstInput = mesh.remapVertexInput( entry.commandID );
|
||||
auto vertexCount = xmesh.vertexCount;
|
||||
|
||||
#if UF_XATLAS_LAZY
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
|
||||
for ( auto k = 0; k < srcInput.attributes.size(); ++k ) {
|
||||
auto dstAttribute = dstInput.attributes[k];
|
||||
if ( dstAttribute.descriptor.name != "st" ) continue;
|
||||
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (ref + dstInput.first) );
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
|
||||
}
|
||||
}
|
||||
#else
|
||||
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
|
||||
|
||||
drawCommands[entry.commandID].vertices = vertexCount;
|
||||
primitives[entry.commandID].drawCommand.vertices = vertexCount;
|
||||
bool mismatched = xmesh.vertexCount != drawCommands[entry.commandID].vertices;
|
||||
vertexIDOffset += xmesh.vertexCount - drawCommands[entry.commandID].vertices;
|
||||
|
||||
drawCommands[entry.commandID].vertices = xmesh.vertexCount;
|
||||
primitives[entry.commandID].drawCommand.vertices = xmesh.vertexCount;
|
||||
drawCommands[entry.commandID].vertexID += vertexIDOffset;
|
||||
primitives[entry.commandID].drawCommand.vertexID += vertexIDOffset;
|
||||
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
|
||||
// auto srcAttribute = source.remapVertexAttribute( source.vertex.attributes[k], entry.commandID );
|
||||
// auto dstAttribute = mesh.remapVertexAttribute( mesh.vertex.attributes[k], entry.commandID );
|
||||
|
||||
auto srcAttribute = source.vertex.attributes[k];
|
||||
auto dstAttribute = mesh.vertex.attributes[k];
|
||||
|
||||
for ( auto k = 0; k < srcInput.attributes.size(); ++k ) {
|
||||
auto srcAttribute = srcInput.attributes[k];
|
||||
auto dstAttribute = dstInput.attributes[k];
|
||||
|
||||
if ( dstAttribute.descriptor.name == "st" ) {
|
||||
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) );
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
|
||||
} else {
|
||||
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride );
|
||||
}
|
||||
@ -211,12 +254,29 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
uf::Mesh::Attribute stAttribute;
|
||||
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
|
||||
UF_ASSERT( stAttribute.descriptor.name == "st" );
|
||||
|
||||
// vertices
|
||||
#if UF_XATLAS_LAZY
|
||||
auto srcInput = source.vertex;
|
||||
auto dstInput = mesh.vertex;
|
||||
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
|
||||
for ( auto k = 0; k < srcInput.attributes.size(); ++k ) {
|
||||
auto dstAttribute = dstInput.attributes[k];
|
||||
if ( dstAttribute.descriptor.name != "st" ) continue;
|
||||
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (ref + dstInput.first) );
|
||||
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
|
||||
auto& vertex = xmesh.vertexArray[j];
|
||||
auto ref = vertex.xref;
|
||||
@ -265,12 +325,13 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
mesh.updateDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
#if !UF_XATLAS_LAZY
|
||||
// update vertexID offsets for indirect commands
|
||||
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
|
||||
auto& name = graph.meshes[index];
|
||||
@ -281,6 +342,7 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
|
||||
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
|
||||
|
||||
|
||||
size_t vertexID = 0;
|
||||
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
|
||||
auto& primitive = primitives[i];
|
||||
@ -292,6 +354,7 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
|
||||
vertexID += drawCommand.vertices;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// cleanup
|
||||
size_t atlasCount = 0;
|
||||
|
||||
@ -4295,8 +4295,8 @@ static NLMatrix nlCRSMatrixNewFromSparseMatrix(NLSparseMatrix* M)
|
||||
CRS->sliceptr[0] = 0;
|
||||
for (slice = 1; slice < nslices; ++slice) {
|
||||
while (cur_NNZ < cur_bound && cur_row < M->m) {
|
||||
++cur_row;
|
||||
cur_NNZ += CRS->rowptr[cur_row + 1] - CRS->rowptr[cur_row];
|
||||
++cur_row;
|
||||
}
|
||||
CRS->sliceptr[slice] = cur_row;
|
||||
cur_bound += slice_size;
|
||||
@ -4754,13 +4754,10 @@ public:
|
||||
Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
|
||||
v[m_numVertices] = v[0];
|
||||
m_area = 0;
|
||||
float centroidx = 0, centroidy = 0;
|
||||
for (uint32_t k = 0; k < m_numVertices; k++) {
|
||||
// http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
|
||||
float f = v[k].x * v[k + 1].y - v[k + 1].x * v[k].y;
|
||||
m_area += f;
|
||||
centroidx += f * (v[k].x + v[k + 1].x);
|
||||
centroidy += f * (v[k].y + v[k + 1].y);
|
||||
}
|
||||
m_area = 0.5f * fabsf(m_area);
|
||||
}
|
||||
@ -9090,7 +9087,6 @@ AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountH
|
||||
const uint32_t kMaxWarnings = 50;
|
||||
uint32_t warningCount = 0;
|
||||
internal::Array<uint32_t> triIndices;
|
||||
uint32_t firstFaceIndex = 0;
|
||||
internal::Triangulator triangulator;
|
||||
for (uint32_t face = 0; face < faceCount; face++) {
|
||||
// Decode face indices.
|
||||
@ -9200,7 +9196,6 @@ AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountH
|
||||
for (uint32_t i = 0; i < triIndices.size(); i++)
|
||||
meshPolygonMapping->triangleToPolygonIndicesMap.push_back(triIndices[i]);
|
||||
}
|
||||
firstFaceIndex += faceVertexCount;
|
||||
}
|
||||
if (warningCount > kMaxWarnings)
|
||||
XA_PRINT(" %u additional warnings truncated\n", warningCount - kMaxWarnings);
|
||||
|
||||
@ -66,14 +66,6 @@ void UF_API uf::thread::batchWorker( const pod::Thread::function_t& function, co
|
||||
return batchWorkers( { function }, false, name );
|
||||
}
|
||||
void UF_API uf::thread::batchWorkers( const uf::stl::vector<pod::Thread::function_t>& functions, bool wait, const uf::stl::string& name ) {
|
||||
if ( uf::thread::async ) {
|
||||
uf::stl::vector<std::future<void>> futures;
|
||||
futures.reserve(functions.size());
|
||||
for ( auto& function : functions ) futures.emplace_back(std::async( std::launch::async, function ));
|
||||
if ( wait ) for ( auto& future : futures ) future.wait();
|
||||
return;
|
||||
}
|
||||
|
||||
uf::stl::vector<pod::Thread*> workers;
|
||||
for ( auto& function : functions ) {
|
||||
auto& worker = uf::thread::fetchWorker( name );
|
||||
@ -82,6 +74,14 @@ void UF_API uf::thread::batchWorkers( const uf::stl::vector<pod::Thread::functio
|
||||
}
|
||||
if ( wait ) for ( auto& worker : workers ) uf::thread::wait( *worker );
|
||||
}
|
||||
void UF_API uf::thread::batchWorkers_Async( const uf::stl::vector<pod::Thread::function_t>& functions, bool wait, const uf::stl::string& name ) {
|
||||
// if ( uf::thread::async )
|
||||
uf::stl::vector<std::future<void>> futures;
|
||||
futures.reserve(functions.size());
|
||||
for ( auto& function : functions ) futures.emplace_back(std::async( std::launch::async, function ));
|
||||
if ( wait ) for ( auto& future : futures ) future.wait();
|
||||
return;
|
||||
}
|
||||
void UF_API uf::thread::add( pod::Thread& thread, const pod::Thread::function_t& function, bool temporary ) {
|
||||
if ( thread.mutex != NULL ) thread.mutex->lock();
|
||||
temporary ? thread.temps.push( function ) : thread.consts.push_back( function );
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
#include "../light/behavior.h"
|
||||
#include "../scene/behavior.h"
|
||||
|
||||
#define UF_BAKER_SAVE_MULTITHREAD 1
|
||||
|
||||
UF_BEHAVIOR_REGISTER_CPP(ext::BakingBehavior)
|
||||
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = false)
|
||||
#define this (&self)
|
||||
@ -39,14 +41,15 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
metadata.output = this->grabURI( metadataJson["baking"]["output"].as<uf::stl::string>(), metadataJson["baking"]["root"].as<uf::stl::string>() );
|
||||
metadata.renderModeName = "B:" + std::to_string((int) this->getUid());
|
||||
|
||||
metadata.trigger.mode = metadataJson["baking"]["trigger"]["mode"].as<uf::stl::string>();
|
||||
metadata.trigger.value = metadataJson["baking"]["trigger"]["value"].as<uf::stl::string>();
|
||||
metadata.trigger.mode = metadataJson["baking"]["trigger"]["mode"].as( metadata.trigger.mode );
|
||||
metadata.trigger.value = metadataJson["baking"]["trigger"]["value"].as( metadata.trigger.value );
|
||||
metadata.trigger.quits = metadataJson["baking"]["trigger"]["quits"].as( metadata.trigger.quits );
|
||||
|
||||
if ( metadataJson["baking"]["resolution"].is<size_t>() )
|
||||
metadata.size = { metadataJson["baking"]["resolution"].as<size_t>(), metadataJson["baking"]["resolution"].as<size_t>() };
|
||||
|
||||
metadata.max.shadows = metadataJson["baking"]["shadows"].as<size_t>(metadata.max.shadows);
|
||||
metadata.max.layers = metadataJson["baking"]["layers"].as<size_t>(metadata.max.layers);
|
||||
metadata.max.layers = std::max( metadataJson["baking"]["layers"].as<size_t>(metadata.max.layers), (size_t) 1 );
|
||||
|
||||
metadata.cull = metadataJson["baking"]["cull"].as<bool>();
|
||||
|
||||
@ -113,20 +116,30 @@ PREPARE: {
|
||||
renderMode.setTarget("");
|
||||
uf::renderer::states::rebuild = true;
|
||||
|
||||
UF_MSG_DEBUG("Graphic configured, ready to bake");
|
||||
UF_MSG_DEBUG("Graphic configured, ready to bake " << metadata.max.layers << " lightmaps");
|
||||
return;
|
||||
}
|
||||
SAVE: {
|
||||
#if 1
|
||||
renderMode.execute = false;
|
||||
UF_MSG_DEBUG("Baking...");
|
||||
|
||||
pod::Thread::container_t jobs;
|
||||
|
||||
for ( size_t i = 0; i < metadata.max.layers; ++i ) {
|
||||
// auto image = renderMode.screenshot(0, i);
|
||||
auto image = metadata.buffers.baked.screenshot(i);
|
||||
uf::stl::string filename = uf::string::replace( metadata.output, "%i", std::to_string(i) );
|
||||
bool status = image.save(filename);
|
||||
UF_MSG_DEBUG("Writing to " << filename << ": " << status);
|
||||
jobs.emplace_back([&, i]{
|
||||
// auto image = renderMode.screenshot(0, i);
|
||||
auto image = metadata.buffers.baked.screenshot(i);
|
||||
uf::stl::string filename = uf::string::replace( metadata.output, "%i", std::to_string(i) );
|
||||
bool status = image.save(filename);
|
||||
UF_MSG_DEBUG("Writing to " << filename << ": " << status);
|
||||
});
|
||||
}
|
||||
#if UF_BAKER_SAVE_MULTITHREAD
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
|
||||
#else
|
||||
for ( auto& job : jobs ) job();
|
||||
#endif
|
||||
UF_MSG_DEBUG("Baked.");
|
||||
metadata.initialized.map = true;
|
||||
|
||||
@ -142,6 +155,8 @@ SAVE: {
|
||||
ext::json::Value payload;
|
||||
payload["uid"] = this->getUid();
|
||||
uf::scene::getCurrentScene().queueHook("system:Destroy", payload);
|
||||
|
||||
if ( metadata.trigger.quits ) uf::scene::getCurrentScene().queueHook("system:Quit", payload);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <uf/engine/entity/entity.h>
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/utils/math/vector.h>
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
|
||||
namespace ext {
|
||||
namespace BakingBehavior {
|
||||
@ -39,8 +40,9 @@ namespace ext {
|
||||
size_t update = 0;
|
||||
} previous;
|
||||
struct {
|
||||
uf::stl::string mode = "key";
|
||||
uf::stl::string mode = "rendered";
|
||||
uf::stl::string value = "";
|
||||
bool quits = true;
|
||||
} trigger;
|
||||
struct {
|
||||
bool renderMode = false;
|
||||
|
||||
@ -214,6 +214,9 @@ void EXT_API ext::initialize() {
|
||||
{
|
||||
uf::Entity::deleteChildrenOnDestroy = ::json["engine"]["debug"]["entity"]["delete children on destroy"].as( uf::Entity::deleteChildrenOnDestroy );
|
||||
uf::Entity::deleteComponentsOnDestroy = ::json["engine"]["debug"]["entity"]["delete components on destroy"].as( uf::Entity::deleteComponentsOnDestroy );
|
||||
|
||||
uf::Object::assertionLoad = ::json["engine"]["debug"]["loader"]["assert"].as( uf::Object::assertionLoad );
|
||||
uf::Asset::assertionLoad = ::json["engine"]["debug"]["loader"]["assert"].as( uf::Asset::assertionLoad );
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user