From 60cb5bd23657e3f30da53e3c17ed70691ba1d603 Mon Sep 17 00:00:00 2001 From: mrq Date: Tue, 27 Jul 2021 22:27:00 -0500 Subject: [PATCH] Commit for 2021.07.27 22-27-21.7z --- Makefile | 17 +- bin/data/config.json | 20 +- bin/data/entities/player.json | 12 +- bin/data/entities/playerModel.json | 1 + bin/data/scenes/construct/scene.json | 5 - bin/data/scenes/mcdonalds/mcdonalds.json | 9 +- bin/data/scenes/mcdonalds/scene.json | 5 - bin/data/scenes/sh2_mcdonalds/scene.json | 5 - bin/data/scenes/ss2/medsci.json | 6 +- bin/data/scenes/ss2/scene.json | 9 - bin/data/shaders/common/lambert.h | 27 ++ bin/data/shaders/common/pbr.h | 11 +- bin/data/shaders/graph/baking/bake.frag.glsl | 32 +- bin/data/shaders/graph/baking/bake.vert.glsl | 79 +--- bin/data/shaders/graph/base.frag.h | 2 +- bin/data/shaders/graph/base.vert.h | 13 +- bin/data/shaders/graph/cull.comp.glsl | 18 +- bin/data/shaders/graph/voxelize.frag.h | 2 +- bin/dreamcast/config.json | 29 +- client/client/ext.cpp | 24 -- client/main.cpp | 14 +- engine/inc/uf/engine/graph/mesh.inl | 19 +- engine/inc/uf/ext/bullet/bullet.h | 6 +- engine/inc/uf/ext/lua/lua.h | 1 + engine/inc/uf/ext/meshopt/meshopt.h | 1 + engine/inc/uf/ext/oal/oal.h | 13 +- engine/inc/uf/ext/opengl/commands.h | 2 + engine/inc/uf/macros.h | 29 +- engine/inc/uf/utils/audio/audio.h | 9 + engine/inc/uf/utils/math/matrix.h | 12 +- engine/inc/uf/utils/math/matrix/pod.inl | 81 ++-- engine/inc/uf/utils/math/physics.h | 10 +- engine/inc/uf/utils/math/vector.h | 77 ++-- engine/inc/uf/utils/math/vector/pod.inl | 119 +++--- .../inc/uf/utils/math/vector/redundancy.inl | 80 ++-- engine/inc/uf/utils/mesh/mesh.h | 10 +- engine/inc/uf/utils/mesh/mesh.inl | 163 -------- engine/inc/uf/utils/time/time.h | 62 +-- engine/inc/uf/utils/time/time.inl | 8 + engine/src/engine/behavior/behavior.cpp | 20 +- engine/src/engine/graph/graph.cpp | 30 +- engine/src/engine/object/behaviors/lua.cpp | 2 + engine/src/ext/bullet/bullet.cpp | 17 +- engine/src/ext/gltf/gltf.cpp | 395 ++++++++++++------ engine/src/ext/lua/lua.cpp | 5 + engine/src/ext/meshopt/meshopt.cpp | 2 +- engine/src/ext/oal/oal.cpp | 57 ++- engine/src/ext/opengl/commands.cpp | 179 +++++--- engine/src/ext/opengl/graphic.cpp | 281 +------------ engine/src/ext/opengl/opengl.cpp | 9 + engine/src/ext/opengl/shader.cpp | 2 + engine/src/ext/vorbis/vorbis.cpp | 6 +- engine/src/ext/vulkan/shader.cpp | 47 ++- engine/src/ext/xatlas/xatlas.cpp | 8 +- engine/src/utils/audio/audio.cpp | 10 +- engine/src/utils/math/physics.cpp | 10 +- engine/src/utils/mesh/mesh.cpp | 28 +- ext/behaviors/baking/behavior.cpp | 12 +- ext/behaviors/baking/behavior.h | 3 +- ext/behaviors/player/behavior.cpp | 281 +++++-------- ext/behaviors/player/behavior.h | 2 + ext/behaviors/player/model/behavior.cpp | 11 +- ext/behaviors/scene/behavior.cpp | 33 +- ext/behaviors/scene/behavior.h | 2 +- ext/behaviors/soundemitter/behavior.cpp | 9 +- ext/main.cpp | 54 ++- 66 files changed, 1192 insertions(+), 1365 deletions(-) create mode 100644 bin/data/shaders/common/lambert.h delete mode 100644 engine/inc/uf/utils/mesh/mesh.inl diff --git a/Makefile b/Makefile index 34b3cac6..437c3309 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ CC = $(shell cat "./bin/exe/default.config") TARGET_NAME = program TARGET_EXTENSION = exe TARGET_LIB_EXTENSION = dll +RENDERER = vulkan include makefiles/$(ARCH).$(CC).make @@ -44,11 +45,11 @@ LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS) DEPS += ifneq (,$(findstring win64,$(ARCH))) - REQ_DEPS += vulkan json:nlohmann png zlib openal ogg freetype ncurses curl luajit bullet meshoptimizer xatlas simd ctti # openvr draco discord + REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype ncurses curl luajit bullet meshoptimizer xatlas simd ctti # openvr draco discord FLAGS += DEPS += -lgdi32 else ifneq (,$(findstring dreamcast,$(ARCH))) - REQ_DEPS += opengl gldc json:nlohmann bullet lua freetype png zlib ctti # ogg openal meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord + REQ_DEPS += opengl gldc json:nlohmann bullet lua freetype png zlib ctti ogg openal aldc # ogg openal meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord endif ifneq (,$(findstring vulkan,$(REQ_DEPS))) FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN @@ -82,12 +83,16 @@ ifneq (,$(findstring png,$(REQ_DEPS))) DEPS += -lpng -lz endif ifneq (,$(findstring openal,$(REQ_DEPS))) - FLAGS += -DUF_USE_OPENAL + FLAGS += -DUF_USE_OPENAL -DUF_USE_ALUT ifneq (,$(findstring dreamcast,$(ARCH))) - DEPS += -lAL + ifneq (,$(findstring aldc,$(REQ_DEPS))) + DEPS += -lALdc + FLAGS += -DUF_USE_OPENGL_ALDC + else + DEPS += -lAL + endif else - FLAGS += -DUF_USE_ALUT - DEPS += -lopenal -lalut + DEPS += -lopenal -lalut endif endif ifneq (,$(findstring ogg,$(REQ_DEPS))) diff --git a/bin/data/config.json b/bin/data/config.json index d38294c6..503fcf3c 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -1,7 +1,7 @@ { "engine": { "scenes": { - "start": "SH2_McDonalds", + "start": "SS2", "meshes": { "interleave": false }, @@ -28,10 +28,10 @@ }, "vxgi": { "limiter": 0.125, - "size": 64, + "size": 128, "dispatch": 8, - "cascades": 6, - "cascadePower": 2, + "cascades": 3, + "cascadePower": 3, "shadows": 0, "granularity": 4, "extents": { @@ -80,7 +80,7 @@ "vsync": true, "hdr": false, "vxgi": true, - "deferred sampling": true, + "deferred sampling": false, "culling": true, "bloom": true }, @@ -152,6 +152,7 @@ } }, "lua": { + "enabled": true, "main": "/main.lua", "modules": { "json": "/json.lua" @@ -193,6 +194,11 @@ "size": 32768, "count": 4 }, + "volumes": { + "sfx": 0.25, + "bgm": 0.15, + "voice": 1.0 + }, "streams by default": true }, "memory pool": { @@ -252,10 +258,10 @@ }, "mode" : "windowed", // fullscreen, borderless, windowed "icon" : "./data/textures/icon.png", - // "size" : [ 1920, 1080 ], + "size" : [ 1920, 1080 ], // "size" : [ 1280, 720 ], // "size" : [ 960, 540 ], - "size" : [ 640, 480 ], + // "size" : [ 640, 480 ], "title" : "Grimgram", "visible" : true } diff --git a/bin/data/entities/player.json b/bin/data/entities/player.json index b0b8d0a9..006fbeb6 100644 --- a/bin/data/entities/player.json +++ b/bin/data/entities/player.json @@ -24,11 +24,11 @@ "gravity": [ 0, -9.81, 0 ], "inertia": [ 10, 10, 10 ], "walk": 1, - "move": 4, - "run": 8, - "rotate": 1.25, + "move": 8, + "run": 12, + "rotate": 2, "crouch": 1, - "jump": [ 0, 4, 0 ], + "jump": [ 0, 6, 0 ], "type": "Capsule", "radius": 1, @@ -62,8 +62,8 @@ "footstep": { "volume": 0.5, "list": [ - "./data/audio/footstep/1.ogg", - "./data/audio/footstep/2.ogg" + "/footstep/1.ogg", + "/footstep/2.ogg" ] } }, diff --git a/bin/data/entities/playerModel.json b/bin/data/entities/playerModel.json index 636af02f..f5344c2a 100644 --- a/bin/data/entities/playerModel.json +++ b/bin/data/entities/playerModel.json @@ -12,6 +12,7 @@ ], "transform": { "position": [ 0, -2.0, 0 ], + // "position": [ 12.5715, 3.53811, 7.6238 ], "rotation": { "axis": [ 0, 1, 0 ], "angle": 0 diff --git a/bin/data/scenes/construct/scene.json b/bin/data/scenes/construct/scene.json index 44129421..882923ce 100644 --- a/bin/data/scenes/construct/scene.json +++ b/bin/data/scenes/construct/scene.json @@ -25,11 +25,6 @@ "menus": { "pause": "/gui/pause/menu.json" }, - "volumes": { - "sfx": 0.25, - "bgm": 0.15, - "voice": 1.0 - }, "light": { "exposure": 1.0, "gamma": 1.0, diff --git a/bin/data/scenes/mcdonalds/mcdonalds.json b/bin/data/scenes/mcdonalds/mcdonalds.json index 4b9faa7c..f17c8b28 100644 --- a/bin/data/scenes/mcdonalds/mcdonalds.json +++ b/bin/data/scenes/mcdonalds/mcdonalds.json @@ -5,9 +5,9 @@ "assets": [ // { "filename": "./static.json", "delay": 8 }, - { "filename": "./models/mcdonalds.glb", "delay": 0, "single threaded": false } + // { "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/mcdonalds/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } ], "behaviors": [ "LoadingBehavior" @@ -54,10 +54,9 @@ "SEPARATE": false, "NORMALS": false }, - "lightmap": "", - // "lightmap": "./lightmap.png", + "lightmap": "./lightmap.png", // "cull mode": "none", - // "filter": "NEAREST", + "filter": "NEAREST", "lights": { "shadows": true }, diff --git a/bin/data/scenes/mcdonalds/scene.json b/bin/data/scenes/mcdonalds/scene.json index bb196f40..599252e1 100644 --- a/bin/data/scenes/mcdonalds/scene.json +++ b/bin/data/scenes/mcdonalds/scene.json @@ -24,11 +24,6 @@ "menus": { "pause": "/gui/pause/menu.json" }, - "volumes": { - "sfx": 0.25, - "bgm": 0.75, - "voice": 1.0 - }, "bloom": { "scale": 1.0, "strength": 0.5, diff --git a/bin/data/scenes/sh2_mcdonalds/scene.json b/bin/data/scenes/sh2_mcdonalds/scene.json index dae96142..2150374c 100644 --- a/bin/data/scenes/sh2_mcdonalds/scene.json +++ b/bin/data/scenes/sh2_mcdonalds/scene.json @@ -24,11 +24,6 @@ "menus": { "pause": "/gui/pause/menu.json" }, - "volumes": { - "sfx": 0.25, - "bgm": 0.75, - "voice": 1.0 - }, "bloom": { "scale": 1.0, "strength": 0.5, diff --git a/bin/data/scenes/ss2/medsci.json b/bin/data/scenes/ss2/medsci.json index fd48e36c..5653fb97 100644 --- a/bin/data/scenes/ss2/medsci.json +++ b/bin/data/scenes/ss2/medsci.json @@ -5,9 +5,9 @@ "assets": [ // { "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": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" } // { "filename": "./models/msci/graph.json", "delay": 0, "single threaded": false, "category": "models" } // { "filename": "./models/msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } @@ -58,7 +58,7 @@ }, */ // "lightmap": "./lightmap.min.png", - "lightmap": "./lightmap.png", + // "lightmap": "./lightmap.png", "filter": "NEAREST", "flags": { "ATLAS": false, diff --git a/bin/data/scenes/ss2/scene.json b/bin/data/scenes/ss2/scene.json index 015e1ea0..be1c81d5 100644 --- a/bin/data/scenes/ss2/scene.json +++ b/bin/data/scenes/ss2/scene.json @@ -2,7 +2,6 @@ "import": "/scene.json", "assets": [ { "filename": "./audio/music/medsci1.ogg", "category": "audio-stream", "override": true, "streamed": true }, - // "./audio/music/medsci1.ogg", "./loading.json" ], "system": { @@ -21,17 +20,9 @@ } }, "metadata": { - "debug": { - "target": 0 - }, "menus": { "pause": "/gui/pause/menu.json" }, - "volumes": { - "sfx": 0.25, - "bgm": 0.15, - "voice": 1.0 - }, "bloom": { "scale": 1.0, "strength": 0.125, diff --git a/bin/data/shaders/common/lambert.h b/bin/data/shaders/common/lambert.h new file mode 100644 index 00000000..5418b2aa --- /dev/null +++ b/bin/data/shaders/common/lambert.h @@ -0,0 +1,27 @@ +float shadowFactor( const Light light, float def ); +void lambert() { + 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; + const vec3 Lp = light.position; + // const vec3 Liu = light.position - surface.position.world; + const vec3 Liu = vec3(ubo.eyes[surface.pass].view * vec4(light.position, 1)) - surface.position.eye; + const float La = 1.0 / (PI * pow(length(Liu), 2.0)); + const float Ls = shadowFactor( light, 0.0 ); + if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue; + + const vec3 Li = normalize(Liu); + const vec3 Lr = light.color.rgb * light.power * La * Ls; + // const float cosLi = abs(dot(surface.normal.world, Li)); + const float cosLi = max(0.0, dot(surface.normal.eye, Li)); + + 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; + } +} \ No newline at end of file diff --git a/bin/data/shaders/common/pbr.h b/bin/data/shaders/common/pbr.h index bb62c9e1..723f6e0e 100644 --- a/bin/data/shaders/common/pbr.h +++ b/bin/data/shaders/common/pbr.h @@ -13,7 +13,10 @@ 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 void pbr() { + if ( validTextureIndex( surface.material.lightmapID ) ) return; + const float Rs = 4.0; // specular lighting looks gross without this const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic); const vec3 Lo = normalize( -surface.position.eye ); @@ -31,10 +34,6 @@ void pbr() { const float cosLi = max(0.0, dot(surface.normal.eye, 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.eye, Lh)); @@ -43,7 +42,6 @@ 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); - #endif // lightmapped, compute only specular if ( light.type >= 0 && validTextureIndex( surface.material.lightmapID ) ) surface.fragment.rgb += (specular) * Lr * cosLi; // point light, compute only diffuse @@ -51,4 +49,5 @@ void pbr() { else surface.fragment.rgb += (diffuse + specular) * Lr * cosLi; surface.fragment.a += light.power * La * Ls; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/bin/data/shaders/graph/baking/bake.frag.glsl b/bin/data/shaders/graph/baking/bake.frag.glsl index 6397eb57..0d8d356f 100644 --- a/bin/data/shaders/graph/baking/bake.frag.glsl +++ b/bin/data/shaders/graph/baking/bake.frag.glsl @@ -11,12 +11,16 @@ layout (binding = 5) uniform samplerCube samplerCubemaps[CUBEMAPS]; #define SHADOW_SAMPLES 16 -#define PBR 0 -#define LAMBERT 1 +#define BAKING 1 +#define PBR 1 +#define LAMBERT 0 #include "../../common/macros.h" #include "../../common/structs.h" #include "../../common/functions.h" #include "../../common/shadows.h" +#if PBR +#include "../../common/pbr.h" +#endif layout (std140, binding = 6) readonly buffer Instances { Instance instances[]; @@ -60,13 +64,16 @@ void main() { surface.fragment = material.colorEmissive; surface.material.albedo = vec4(1); - { 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]; + const mat4 mat = light.view; // inverse(light.view); + const vec3 position = surface.position.world; + // const vec3 position = vec3( mat * vec4(surface.position.world, 1.0) ); + const vec3 normal = surface.normal.world; + // const vec3 normal = vec3( mat * vec4(surface.normal.world, 0.0) ); + if ( light.power <= LIGHT_POWER_CUTOFF ) continue; const vec3 Lp = light.position; const vec3 Liu = light.position - surface.position.world; @@ -74,18 +81,23 @@ void main() { const float Ls = shadowFactor( light, 0.0 ); if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue; + const vec3 Lo = normalize( -position ); + const float cosLo = max(0.0, dot(normal, Lo)); + const vec3 Li = normalize(Liu); const vec3 Lr = light.color.rgb * light.power * La * Ls; - const float cosLi = abs(dot(surface.normal.world, Li));// max(0.0, dot(N, Li)); + // const float cosLi = max(0.0, dot(normal, Li)); + const float cosLi = abs(dot(normal, Li)); #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(N, Lh)); + // const float cosLh = max(0.0, dot(normal, Lh)); + const float cosLh = abs(dot(normal, Lh)); const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) ); - const float D = ndfGGX( cosLh, surface.material.roughness ); + const float D = 1; // 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); @@ -98,8 +110,8 @@ void main() { #define EXPOSURE 1 #define GAMMA 1 - surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * EXPOSURE); - surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / GAMMA)); +// surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * EXPOSURE); +// surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / GAMMA)); outAlbedo = vec4(surface.fragment.rgb, 1); } \ No newline at end of file diff --git a/bin/data/shaders/graph/baking/bake.vert.glsl b/bin/data/shaders/graph/baking/bake.vert.glsl index d0d3ae46..7e5ae878 100644 --- a/bin/data/shaders/graph/baking/bake.vert.glsl +++ b/bin/data/shaders/graph/baking/bake.vert.glsl @@ -4,82 +4,5 @@ #define INSTANCED 1 #define SKINNED 0 #define BAKING 1 -#if 1 + #include "../base.vert.h" -#else -#extension GL_ARB_shader_draw_parameters : enable -#include "../../common/structs.h" - -layout (constant_id = 0) const uint PASSES = 6; -layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUv; -layout (location = 2) in vec2 inSt; -layout (location = 3) in vec3 inNormal; -layout (location = 4) in vec4 inTangent; -#if SKINNED - layout (location = 5) in uvec4 inJoints; - layout (location = 6) in vec4 inWeights; -#endif - -layout( push_constant ) uniform PushBlock { - uint pass; - uint draw; -} PushConstant; - -/* -layout (std140, binding = 0) readonly buffer DrawCommands { - DrawCommand drawCommands[]; -}; -*/ -layout (std140, binding = 1) readonly buffer Instances { - Instance instances[]; -}; - -#if SKINNED - layout (std140, binding = 2) readonly buffer Joints { - mat4 joints[]; - }; -#endif - -layout (location = 0) out vec2 outUv; -layout (location = 1) out vec2 outSt; -layout (location = 2) out vec4 outColor; -layout (location = 3) out vec3 outNormal; -layout (location = 4) out mat3 outTBN; -layout (location = 7) out vec3 outPosition; -layout (location = 8) flat out uvec4 outId; - -out gl_PerVertex { - vec4 gl_Position; -}; - -void main() { - outUv = inUv; - outSt = inSt; - -#if SKINNED - const mat4 skinned = joints.length() <= 0 ? mat4(1.0) : inWeights.x * joints[int(inJoints.x)] + inWeights.y * joints[int(inJoints.y)] + inWeights.z * joints[int(inJoints.z)] + inWeights.w * joints[int(inJoints.w)]; -#else - const mat4 skinned = mat4(1.0); -#endif - const uint drawID = gl_DrawIDARB; -// const DrawCommand drawCommand = drawCommands[drawID]; - const uint instanceID = gl_InstanceIndex; - const Instance instance = instances[instanceID]; - const uint materialID = instance.materialID; - const mat4 model = instances.length() <= 0 ? skinned : (instance.model * skinned); - - outId = ivec4(drawID, instanceID, materialID, PushConstant.pass); - outColor = instance.color; - outPosition = vec3(model * vec4(inPos.xyz, 1.0)); - outNormal = vec3(model * vec4(inNormal.xyz, 0.0)); - outNormal = normalize(outNormal); - - vec3 T = vec3(model * vec4(inTangent.xyz, 0.0)); - vec3 N = outNormal; - vec3 B = cross(N, T) * inTangent.w; - outTBN = mat3( T, B, N ); - - gl_Position = vec4(inSt * 2.0 - 1.0, 0.0, 1.0); -} -#endif \ No newline at end of file diff --git a/bin/data/shaders/graph/base.frag.h b/bin/data/shaders/graph/base.frag.h index 9294d28f..a3fd4a40 100644 --- a/bin/data/shaders/graph/base.frag.h +++ b/bin/data/shaders/graph/base.frag.h @@ -83,7 +83,7 @@ void main() { const Texture t = textures[instance.lightmapID]; const float gamma = LIGHTMAP_GAMMA; const vec4 L = pow(textureLod( samplerTextures[nonuniformEXT(t.index)], inSt, mip ), vec4(1.0 / gamma)); - A *= L; + A.rgb *= L.rgb; #endif } #endif diff --git a/bin/data/shaders/graph/base.vert.h b/bin/data/shaders/graph/base.vert.h index 7809b9c4..d11bab49 100644 --- a/bin/data/shaders/graph/base.vert.h +++ b/bin/data/shaders/graph/base.vert.h @@ -3,13 +3,14 @@ layout (constant_id = 0) const uint PASSES = 6; #include "../common/structs.h" layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUv; -layout (location = 2) in vec2 inSt; -layout (location = 3) in vec3 inNormal; -layout (location = 4) in vec4 inTangent; +layout (location = 1) in vec4 inColor; +layout (location = 2) in vec2 inUv; +layout (location = 3) in vec2 inSt; +layout (location = 4) in vec3 inNormal; +layout (location = 5) in vec4 inTangent; #if SKINNED - layout (location = 5) in uvec4 inJoints; - layout (location = 6) in vec4 inWeights; + layout (location = 6) in uvec4 inJoints; + layout (location = 7) in vec4 inWeights; #endif layout( push_constant ) uniform PushBlock { diff --git a/bin/data/shaders/graph/cull.comp.glsl b/bin/data/shaders/graph/cull.comp.glsl index 37ef73a4..8eb2a849 100644 --- a/bin/data/shaders/graph/cull.comp.glsl +++ b/bin/data/shaders/graph/cull.comp.glsl @@ -32,20 +32,6 @@ struct Frustum { vec4 planes[6]; }; -float inside( vec3 v, vec3 min, vec3 max ) { - vec3 s = step(min, v) - step(max, v); - return s.x * s.y * s.z; -} -/* - T f = 1 / tan( fov / 2 ); - return pod::Matrix4t({ - f / raidou, 0, 0, 0, - 0, -f, 0, 0, - 0, 0, 0, 1, - 0, 0, znear, 0 - }); -*/ - vec4 normalizePlane( vec4 p ) { return p / length(p.xyz); } @@ -59,8 +45,8 @@ bool frustumCull( uint id ) { bool visible = false; for ( uint pass = 0; pass < PushConstant.passes; ++pass ) { // return if our camera position is inside the AABB - vec3 camPos = vec3( inverse(camera.viewport[pass].view)[3] ); - if ( instance.bounds.min.x <= camPos.x && camPos.x <= instance.bounds.max.x && instance.bounds.min.y <= camPos.y && camPos.y <= instance.bounds.max.y && instance.bounds.min.z <= camPos.z && camPos.z <= instance.bounds.max.z ) return true; +// vec3 camPos = vec3( inverse(camera.viewport[pass].view)[3] ); +// if ( instance.bounds.min.x <= camPos.x && camPos.x <= instance.bounds.max.x && instance.bounds.min.y <= camPos.y && camPos.y <= instance.bounds.max.y && instance.bounds.min.z <= camPos.z && camPos.z <= instance.bounds.max.z ) return true; // sphere based one, source of this block uses reverse infinite Z, but would be nice if it used AABB // doesn't work #if 0 diff --git a/bin/data/shaders/graph/voxelize.frag.h b/bin/data/shaders/graph/voxelize.frag.h index 643bbd33..5ca2e4e9 100644 --- a/bin/data/shaders/graph/voxelize.frag.h +++ b/bin/data/shaders/graph/voxelize.frag.h @@ -95,7 +95,7 @@ void main() { Texture t = textures[instance.lightmapID]; const float gamma = LIGHTMAP_GAMMA; const vec4 L = pow(textureLod( samplerTextures[nonuniformEXT(t.index)], inSt, mip ), vec4(1.0 / gamma)); - A *= L; + A.rgb *= L.rgb; #endif } #endif diff --git a/bin/dreamcast/config.json b/bin/dreamcast/config.json index b706058d..90af07b1 100644 --- a/bin/dreamcast/config.json +++ b/bin/dreamcast/config.json @@ -21,11 +21,11 @@ }, "textures": { "max": { - "2D": 256, - "cube": 16, + "2D": 192, + "cube": 8, "3D": 1 } - }, + } }, "ext": { "opengl": { @@ -45,11 +45,12 @@ "deferred mode": "", "deferred reconstruct position": true, "deferred alias output to swapchain": true, - "hdr": false + "hdr": false, + "culling": true }, "formats": { "depth": "D32_SFLOAT", - "color": "R8G8B8A8_UNORM", // "R32G32B32A32_SFLOAT", + "color": "R8G8B8A8_UNORM", "normal": "R16G16B16A16_SFLOAT", "position": "R16G16B16A16_SFLOAT" }, @@ -60,6 +61,7 @@ } }, "lua": { + "enabled": false, "main": "/main.lua", "modules": { "json": "/json.lua" @@ -83,17 +85,22 @@ "audio": { "mute": false, "buffers": { - "size": 32768, - "count": 4 + "size": 16384, + "count": 2 + }, + "volumes": { + "sfx": 1.0, + "bgm": 1.0, + "voice": 1.0 }, "streams by default": true }, "memory pool": { - "enabled": false, + "enabled": true, "subPools": true, "alignment": 32, "override": true, - "size": "6 MiB", + "size": "8 MiB", "pools": { "entity": "96 KiB", "userdata": "96 KiB", @@ -107,7 +114,7 @@ "multiview stereo deferred": false }, "limiters": { - "deltaTime": 20, + "deltaTime": 5, "framerate": "auto" }, "threads": { @@ -143,7 +150,7 @@ "visible" : true, "center" : false }, - "mode" : "windowed", // fullscreen, borderless, windowed + "mode" : "windowed", "icon" : "./data/textures/icon.png", "size" : [ 640, 480 ], "title" : "Grimgram", diff --git a/client/client/ext.cpp b/client/client/ext.cpp index f301f31e..493a5d43 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -64,19 +64,6 @@ void client::initialize() { client::window.setTitle(title); #endif } - - #if UF_USE_OPENAL - /* Initialize OpenAL */ { - ext::al::initialize(); - /* - if ( !ext::al::initialize() ) { - std::cerr << "[ERROR] AL failed to initialize!" << std::endl; - std::exit(EXIT_SUCCESS); - return; - } - */ - } - #endif /* Initialize hooks */ { uf::hooks.addHook( "window:Mouse.CursorVisibility", [&]( ext::json::Value& json ){ @@ -179,15 +166,4 @@ void client::terminate() { } client::window.terminate(); - - #if UF_USE_OPENAL - ext::al::destroy(); -/* - if ( !ext::al::destroy() ) { - std::cerr << "[ERROR] AL failed to terminate!" << std::endl; - std::exit(EXIT_SUCCESS); - return; - } -*/ - #endif } \ No newline at end of file diff --git a/client/main.cpp b/client/main.cpp index 0faedcdf..523c9242 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -85,8 +85,12 @@ int main(int argc, char** argv){ uf::hooks.call(hook, json); } #if UF_ENV_DREAMCAST + // UF_TIMER_MULTITRACE_START("Starting"); ext::render(); + // UF_TIMER_MULTITRACE("render"); ext::tick(); + // UF_TIMER_MULTITRACE("tick"); + // UF_TIMER_MULTITRACE_END("Finished"); #else client::tick(); client::render(); @@ -96,14 +100,18 @@ int main(int argc, char** argv){ #if HANDLE_EXCEPTIONS } catch ( std::runtime_error& e ) { UF_MSG_ERROR("RUNTIME ERROR: " << e.what()); - break; + abort(); } catch ( std::exception& e ) { UF_MSG_ERROR("EXCEPTION ERROR: " << e.what()); - throw e; + abort(); } catch ( bool handled ) { - if (!handled) UF_MSG_ERROR("UNHANDLED ERROR: " << "???"); + if (!handled) { + UF_MSG_ERROR("UNHANDLED ERROR: " << "???"); + abort(); + } } catch ( ... ) { UF_MSG_ERROR("UNKNOWN ERROR: " << "???"); + abort(); } #endif } diff --git a/engine/inc/uf/engine/graph/mesh.inl b/engine/inc/uf/engine/graph/mesh.inl index 33ea0d9c..3593970f 100644 --- a/engine/inc/uf/engine/graph/mesh.inl +++ b/engine/inc/uf/engine/graph/mesh.inl @@ -1,40 +1,27 @@ namespace uf { namespace graph { namespace mesh { - typedef uint16_t id_t; - struct Base { pod::Vector3f position; - pod::Vector2f uv; - pod::Vector2f st; - - static UF_API uf::stl::vector descriptor; - }; - struct ID { - pod::Vector3f position; + pod::ColorRgba color; pod::Vector2f uv; pod::Vector2f st; pod::Vector3f normal; - pod::Vector3f tangent; static UF_API uf::stl::vector descriptor; }; struct Skinned { pod::Vector3f position; + pod::ColorRgba color; pod::Vector2f uv; pod::Vector2f st; pod::Vector3f normal; pod::Vector3f tangent; - pod::Vector joints; + pod::Vector joints; pod::Vector4f weights; static UF_API uf::stl::vector descriptor; }; } - /* - typedef uf::Mesh base_mesh_t; - typedef uf::Mesh id_mesh_t; - typedef uf::Mesh skinned_mesh_t; - */ } } \ No newline at end of file diff --git a/engine/inc/uf/ext/bullet/bullet.h b/engine/inc/uf/ext/bullet/bullet.h index 8bf66238..913d816f 100644 --- a/engine/inc/uf/ext/bullet/bullet.h +++ b/engine/inc/uf/ext/bullet/bullet.h @@ -79,13 +79,17 @@ namespace ext { // directly move a transform void UF_API applyMovement( pod::Bullet&, const pod::Vector3f& ); // directly apply a velocity + void UF_API setVelocity( pod::Bullet&, const pod::Vector3f& ); void UF_API applyVelocity( pod::Bullet&, const pod::Vector3f& ); // directly rotate a transform void UF_API applyRotation( pod::Bullet&, const pod::Quaternion<>& ); void UF_API applyRotation( pod::Bullet&, const pod::Vector3f&, float ); // picks an appropriate movement option - void UF_API move( pod::Bullet&, const pod::Vector3f&, bool = false ); + // void UF_API move( pod::Bullet&, const pod::Vector3f&, bool = false ); + + // ray casting + float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& ); // allows noclip void UF_API activateCollision( pod::Bullet&, bool = true ); diff --git a/engine/inc/uf/ext/lua/lua.h b/engine/inc/uf/ext/lua/lua.h index fc3af410..c52b670d 100644 --- a/engine/inc/uf/ext/lua/lua.h +++ b/engine/inc/uf/ext/lua/lua.h @@ -29,6 +29,7 @@ namespace pod { namespace ext { namespace lua { + extern UF_API bool enabled; extern UF_API sol::state state; extern UF_API uf::stl::string main; extern UF_API uf::stl::unordered_map modules; diff --git a/engine/inc/uf/ext/meshopt/meshopt.h b/engine/inc/uf/ext/meshopt/meshopt.h index 39557c27..a8b6f098 100644 --- a/engine/inc/uf/ext/meshopt/meshopt.h +++ b/engine/inc/uf/ext/meshopt/meshopt.h @@ -2,6 +2,7 @@ #include #include +#include namespace ext { namespace meshopt { diff --git a/engine/inc/uf/ext/oal/oal.h b/engine/inc/uf/ext/oal/oal.h index 94bd9c70..ff5aa0af 100644 --- a/engine/inc/uf/ext/oal/oal.h +++ b/engine/inc/uf/ext/oal/oal.h @@ -3,10 +3,15 @@ #include #if UF_USE_OPENAL -#include -#include -#include - +#if UF_ENV_DREAMCAST && UF_USE_OPENAL_ALDC + #include + #include + #include +#else + #include + #include + #include +#endif #include #include diff --git a/engine/inc/uf/ext/opengl/commands.h b/engine/inc/uf/ext/opengl/commands.h index eb0fcc5f..a015f756 100644 --- a/engine/inc/uf/ext/opengl/commands.h +++ b/engine/inc/uf/ext/opengl/commands.h @@ -52,6 +52,8 @@ namespace ext { uf::Mesh::Attribute st = {}; uf::Mesh::Attribute normal = {}; uf::Mesh::Attribute color = {}; + uf::Mesh::Attribute instance = {}; + uf::Mesh::Attribute indirect = {}; } attributes; struct { diff --git a/engine/inc/uf/macros.h b/engine/inc/uf/macros.h index 35516d9b..dafa8abf 100644 --- a/engine/inc/uf/macros.h +++ b/engine/inc/uf/macros.h @@ -3,20 +3,37 @@ #define UF_NS_GET_LAST(name) uf::string::replace( uf::string::split( #name, "::" ).back(), "<>", "" ) -#define TIMER(x, ...) auto TOKEN_PASTE(TIMER, __LINE__) = []( double every = 1 ) {\ +/* +#define TIMER(x, ...) auto TOKEN_PASTE(TIMER, __LINE__) = []( uf::physics::num_t every = 1 ) {\ static uf::Timer timer(false);\ if ( !timer.running() ) {\ timer.start(uf::Time(-x * 1000, uf::Time::milliseconds));\ }\ - double time = 0;\ - if ( (time = timer.elapsed().asDouble()) >= every ) {\ + uf::physics::num_t time = 0;\ + if ( (time = timer.elapsed()) >= every ) {\ timer.reset();\ }\ static bool first = true; if ( first ) { first = false; return every; }\ return time;\ };\ - double time = 0;\ + uf::physics::num_t time = 0;\ if ( __VA_ARGS__ (time = TOKEN_PASTE(TIMER, __LINE__)(x)) >= x ) +*/ +#define TIMER_LAMBDA(x) []() {\ + static uf::Timer timer(false);\ + if ( !timer.running() ) timer.start(uf::Time(-x * 1000, uf::Time::milliseconds));\ + uf::physics::num_t time = timer.elapsed();\ + if ( time >= every ) timer.reset();\ + static bool first = true; if ( first ) { first = false; return every; }\ + return time;\ +}; + +#define TIMER(x, ...)\ + static uf::Timer timer(false);\ + if ( !timer.running() ) timer.start(uf::Time(-x * 1000, uf::Time::milliseconds));\ + uf::physics::num_t time = timer.elapsed();\ + if ( time >= x ) timer.reset();\ + if ( __VA_ARGS__ time >= x ) #define UF_DEBUG 1 #if UF_DEBUG @@ -97,7 +114,7 @@ #define TYPE_NAME(T) TYPE(T).name() #endif -#define MIN(X, Y) X < Y ? X : Y -#define MAX(X, Y) X > Y ? X : Y +#define MIN(X, Y) (X) < (Y) ? (X) : (Y) +#define MAX(X, Y) (X) > (Y) ? (X) : (Y) #define LENGTH_OF(X) *(&X + 1) - X #define FOR_ARRAY(X) for ( auto i = 0; i < LENGTH_OF(X); ++i ) \ No newline at end of file diff --git a/engine/inc/uf/utils/audio/audio.h b/engine/inc/uf/utils/audio/audio.h index f291b264..35e20300 100644 --- a/engine/inc/uf/utils/audio/audio.h +++ b/engine/inc/uf/utils/audio/audio.h @@ -29,6 +29,15 @@ namespace uf { extern UF_API bool streamsByDefault; extern UF_API uint8_t buffers; extern UF_API size_t bufferSize; + #if UF_AUDIO_MAPPED_VOLUMES + extern UF_API uf::stl::unordered_map volumes; + #else + namespace volumes { + extern UF_API float bgm; + extern UF_API float sfx; + extern UF_API float voice; + }; + #endif } class UF_API Audio { public: diff --git a/engine/inc/uf/utils/math/matrix.h b/engine/inc/uf/utils/math/matrix.h index f8e79be9..7070cb01 100644 --- a/engine/inc/uf/utils/math/matrix.h +++ b/engine/inc/uf/utils/math/matrix.h @@ -72,17 +72,17 @@ namespace uf { template T /*UF_API*/ multiplyAll( const T& matrix, typename T::type_t scalar ); template T /*UF_API*/ add( const T& lhs, const T& rhs ); // Writes to first value - // template pod::Matrix& /*UF_API*/ multiply( T& left, const T& right ); // Multiplies two matrices of same type and size together - template pod::Matrix multiply( T& left, const U& right ); // Multiplies two matrices of same type and size together - template pod::Matrix multiply( T& left, const T& right ); template T& /*UF_API*/ invert( T& matrix ); // Flip sign of all components + // template pod::Matrix& /*UF_API*/ multiply_( T& left, const T& right ); // Multiplies two matrices of same type and size together + template pod::Matrix multiply_( T& left, const U& right ); // Multiplies two matrices of same type and size together + template pod::Matrix multiply_( T& left, const T& right ); + template T& /*UF_API*/ translate_( T& matrix, const pod::Vector3t& vector ); + template T& /*UF_API*/ rotate_( T& matrix, const pod::Vector3t& vector ); + template T& /*UF_API*/ scale_( T& matrix, const pod::Vector3t& vector ); // Complex arithmetic template T /*UF_API*/ translate( const T& matrix, const pod::Vector3t& vector ); template T /*UF_API*/ rotate( const T& matrix, const pod::Vector3t& vector ); template T /*UF_API*/ scale( const T& matrix, const pod::Vector3t& vector ); - template T& /*UF_API*/ translate( T& matrix, const pod::Vector3t& vector ); - template T& /*UF_API*/ rotate( T& matrix, const pod::Vector3t& vector ); - template T& /*UF_API*/ scale( T& matrix, const pod::Vector3t& vector ); template pod::Vector3t /*UF_API*/ eulerAngles( const T& matrix ); template pod::Matrix4t /*UF_API*/ orthographic( T, T, T, T, T, T ); diff --git a/engine/inc/uf/utils/math/matrix/pod.inl b/engine/inc/uf/utils/math/matrix/pod.inl index b3f2364b..c68ea49d 100644 --- a/engine/inc/uf/utils/math/matrix/pod.inl +++ b/engine/inc/uf/utils/math/matrix/pod.inl @@ -424,11 +424,6 @@ template T uf::matrix::inverse( const T& matrix ) { return inverted; } -// Writes to first value -// Multiplies two matrices of same type and size together -template pod::Matrix uf::matrix::multiply( T& left, const T& right ) { - return left = uf::matrix::multiply((const T&) left, right); -} template pod::Vector3t uf::matrix::multiply( const pod::Matrix4t& mat, const pod::Vector3t& vector, T w, bool div ) { return uf::matrix::multiply( mat, pod::Vector4t{ vector[0], vector[1], vector[2], w }, div ); } @@ -450,10 +445,51 @@ template pod::Vector4t uf::matrix::multiply( const pod::Matrix4t< return res; #endif } +// Writes to first value +// Multiplies two matrices of same type and size together // Flip sign of all components template T& uf::matrix::invert( T& matrix ) { return matrix = uf::matrix::inverse((const T&) matrix); } + +template pod::Matrix uf::matrix::multiply_( T& left, const T& right ) { + return left = uf::matrix::multiply((const T&) left, right); +} +template T& uf::matrix::translate_( T& matrix, const pod::Vector3t& vector ) { + matrix[12] = vector.x; + matrix[13] = vector.y; + matrix[14] = vector.z; + return matrix; +} +template T& uf::matrix::rotate_( T& matrix, const pod::Vector3t& vector ) { + if ( vector.x != 0 ) { + matrix[5] = cos( vector.x ); + matrix[6] = sin( vector.x ); + matrix[9] = -1 * sin( vector.x ); + matrix[10] = cos( vector.x ); + } + + if ( vector.y != 0 ) { + matrix[0] = cos( vector.y ); + matrix[2] = -1 * sin( vector.y ); + matrix[8] = sin( vector.y ); + matrix[10] = cos( vector.y ); + } + + if ( vector.z != 0 ) { + matrix[0] = cos( vector.z ); + matrix[1] = sin( vector.z ); + matrix[4] = -1 * sin( vector.z ); + matrix[5] = cos( vector.z ); + } + return matrix; +} +template T& uf::matrix::scale_( T& matrix, const pod::Vector3t& vector ) { + matrix[0] = vector.x; + matrix[5] = vector.y; + matrix[10] = vector.z; + return matrix; +} // Complex arithmetic template T uf::matrix::translate( const T& matrix, const pod::Vector3t& vector ) { alignas(16) T res = matrix; @@ -493,41 +529,6 @@ template T uf::matrix::scale( const T& matrix, const pod::Vector3t T& uf::matrix::translate( T& matrix, const pod::Vector3t& vector ) { - matrix[12] = vector.x; - matrix[13] = vector.y; - matrix[14] = vector.z; - return matrix; -} -template T& uf::matrix::rotate( T& matrix, const pod::Vector3t& vector ) { - if ( vector.x != 0 ) { - matrix[5] = cos( vector.x ); - matrix[6] = sin( vector.x ); - matrix[9] = -1 * sin( vector.x ); - matrix[10] = cos( vector.x ); - } - - if ( vector.y != 0 ) { - matrix[0] = cos( vector.y ); - matrix[2] = -1 * sin( vector.y ); - matrix[8] = sin( vector.y ); - matrix[10] = cos( vector.y ); - } - - if ( vector.z != 0 ) { - matrix[0] = cos( vector.z ); - matrix[1] = sin( vector.z ); - matrix[4] = -1 * sin( vector.z ); - matrix[5] = cos( vector.z ); - } - return matrix; -} -template T& uf::matrix::scale( T& matrix, const pod::Vector3t& vector ) { - matrix[0] = vector.x; - matrix[5] = vector.y; - matrix[10] = vector.z; - return matrix; -} template pod::Matrix4t /*UF_API*/ uf::matrix::orthographic( T l, T r, T b, T t, T f, T n ) { alignas(16) pod::Matrix4t m = uf::matrix::identity(); diff --git a/engine/inc/uf/utils/math/physics.h b/engine/inc/uf/utils/math/physics.h index e1ea1814..5061e84d 100644 --- a/engine/inc/uf/utils/math/physics.h +++ b/engine/inc/uf/utils/math/physics.h @@ -20,12 +20,14 @@ namespace pod { namespace uf { namespace physics { + typedef pod::Math::num_t num_t; namespace time { + extern UF_API uf::Timer<> timer; - extern UF_API double current; - extern UF_API double previous; - extern UF_API double delta; - extern UF_API double clamp; + extern UF_API uf::physics::num_t current; + extern UF_API uf::physics::num_t previous; + extern UF_API uf::physics::num_t delta; + extern UF_API uf::physics::num_t clamp; } void UF_API tick(); template pod::Transform& update( pod::Transform& transform, pod::Physics& physics ); diff --git a/engine/inc/uf/utils/math/vector.h b/engine/inc/uf/utils/math/vector.h index 0ec5bd35..c205ebfa 100644 --- a/engine/inc/uf/utils/math/vector.h +++ b/engine/inc/uf/utils/math/vector.h @@ -15,18 +15,18 @@ namespace pod { // Simple vectors (designed [to store in arrays] with minimal headaches) - template + template struct /*UF_API*/ Vector { // n-dimensional/unspecialized vector access T components[N]; // POD information typedef T type_t; typedef T* container_t; - static const std::size_t size = N; + static const size_t size = N; // Overload access // Accessing via subscripts - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + T& operator[](size_t i); + const T& operator[](size_t i) const; // Arithmetic Vector operator()() const; // Negation Vector operator-() const; // Negation @@ -110,27 +110,28 @@ namespace uf { template bool /*UF_API*/ equals( const T& left, const T& right ); // Equality check between two vectors (equals) // Basic arithmetic template T /*UF_API*/ add( const T& left, const T& right ); // Adds two vectors of same type and size together - template T /*UF_API*/ add( const T& left, const typename T::type_t& scalar ); // Adds two vectors of same type and size together + template T /*UF_API*/ add( const T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Adds two vectors of same type and size together template T /*UF_API*/ subtract( const T& left, const T& right ); // Subtracts two vectors of same type and size together - template T /*UF_API*/ subtract( const T& left, const typename T::type_t& scalar ); // Subtracts two vectors of same type and size together + template T /*UF_API*/ subtract( const T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Subtracts two vectors of same type and size together template T /*UF_API*/ multiply( const T& left, const T& right ); // Multiplies two vectors of same type and size together - template T /*UF_API*/ multiply( const T& vector, const typename T::type_t& scalar ); // Multiplies this vector by a scalar + template T /*UF_API*/ multiply( const T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ); // Multiplies this vector by a scalar template T /*UF_API*/ divide( const T& left, const T& right ); // Divides two vectors of same type and size together - template T /*UF_API*/ divide( const T& left, const typename T::type_t& scalar ); // Divides this vector by a scalar + template T /*UF_API*/ divide( const T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Divides this vector by a scalar template typename T::type_t /*UF_API*/ sum( const T& vector ); // Compute the sum of all components template typename T::type_t /*UF_API*/ product( const T& vector ); // Compute the product of all components template T /*UF_API*/ negate( const T& vector ); // Flip sign of all components // Writes to first value - template T& /*UF_API*/ add( T& left, const T& right ); // Adds two vectors of same type and size together - template T& /*UF_API*/ add( T& left, const typename T::type_t& scalar ); // Adds two vectors of same type and size together - template T& /*UF_API*/ subtract( T& left, const T& right ); // Subtracts two vectors of same type and size together - template T& /*UF_API*/ subtract( T& left, const typename T::type_t& scalar ); // Subtracts two vectors of same type and size together - template T& /*UF_API*/ multiply( T& left, const T& right ); // Multiplies two vectors of same type and size together - template T& /*UF_API*/ multiply( T& vector, const typename T::type_t& scalar ); // Multiplies this vector by a scalar - template T& /*UF_API*/ divide( T& left, const T& right ); // Divides two vectors of same type and size together - template T& /*UF_API*/ divide( T& left, const typename T::type_t& scalar ); // Divides this vector by a scalar - template T& /*UF_API*/ negate( T& vector ); // Flip sign of all components - template T& /*UF_API*/ normalize( T& vector ); // Normalizes a vector + template T& /*UF_API*/ add_( T& left, const T& right ); // Adds two vectors of same type and size together + template T& /*UF_API*/ add_( T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Adds two vectors of same type and size together + template T& /*UF_API*/ subtract_( T& left, const T& right ); // Subtracts two vectors of same type and size together + template T& /*UF_API*/ subtract_( T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Subtracts two vectors of same type and size together + template T& /*UF_API*/ multiply_( T& left, const T& right ); // Multiplies two vectors of same type and size together + template T& /*UF_API*/ multiply_( T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ); // Multiplies this vector by a scalar + template T& /*UF_API*/ divide_( T& left, const T& right ); // Divides two vectors of same type and size together + template T& /*UF_API*/ divide_( T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Divides this vector by a scalar + template T& /*UF_API*/ negate_( T& vector ); // Flip sign of all components + template T& /*UF_API*/ normalize_( T& vector ); // Normalizes a vector + template T /*UF_API*/ min( const T& left, const T& right ); // template T /*UF_API*/ max( const T& left, const T& right ); // template T /*UF_API*/ ceil( const T& vector ); // @@ -149,8 +150,8 @@ namespace uf { template typename T::type_t /*UF_API*/ distanceSquared( const T& a, const T& b ); // Compute the distance between two vectors (doesn't sqrt) template typename T::type_t /*UF_API*/ distance( const T& a, const T& b ); // Compute the distance between two vectors - template typename T::type_t /*UF_API*/ magnitude( const T& vector ); // Gets the magnitude of the vector template typename T::type_t /*UF_API*/ norm( const T& vector ); // Compute the norm of the vector + template typename T::type_t /*UF_API*/ magnitude( const T& vector ); // Gets the magnitude of the vector template T /*UF_API*/ normalize( const T& vector ); // Normalizes a vector template void /*UF_API*/ orthonormalize( T& x, T& y ); // Normalizes a vector template T /*UF_API*/ orthonormalize( const T& x, const T& y ); // Normalizes a vector @@ -166,7 +167,7 @@ namespace uf { namespace uf { // Provides operations for POD vector - template + template class /*UF_API*/ Vector { public: // Easily access POD's type @@ -174,7 +175,7 @@ namespace uf { // Replicate POD information typedef T type_t; typedef T* container_t; - static const std::size_t size = N; + static const size_t size = N; protected: // POD storage Vector::pod_t m_pod; @@ -194,11 +195,11 @@ namespace uf { // Alternative POD access T* get(); // Returns a pointer to the entire array const T* get() const; // Returns a const-pointer to the entire array - T& getComponent( std::size_t i ); // Returns a reference to a single element - const T& getComponent( std::size_t i ) const; // Returns a const-reference to a single element + T& getComponent( size_t i ); // Returns a reference to a single element + const T& getComponent( size_t i ) const; // Returns a const-reference to a single element // POD manipulation T* set(const T components[N]); // Sets the entire array - T& setComponent( std::size_t i, const T& value ); // Sets a single element + T& setComponent( size_t i, const T& value ); // Sets a single element // Validation bool isValid() const; // Checks if all components are valid (non NaN, inf, etc.) // Basic arithmetic @@ -230,8 +231,8 @@ namespace uf { inline uf::stl::string toString() const; // Overloaded ops // Accessing via subscripts - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + T& operator[](size_t i); + const T& operator[](size_t i) const; // Arithmetic inline Vector operator-() const; // Negation inline Vector operator+( const Vector& vector ) const; // Addition between two vectors @@ -325,11 +326,11 @@ namespace pod { // POD information typedef T type_t; typedef T* container_t; - static const std::size_t size = 1; + static const size_t size = 1; // Overload access // Accessing via subscripts - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + T& operator[](size_t i); + const T& operator[](size_t i) const; // Arithmetic inline Vector operator()() const; // Creation inline Vector operator-() const; // Negation @@ -375,11 +376,11 @@ namespace pod { // POD information typedef T type_t; typedef T* container_t; - static const std::size_t size = 2; + static const size_t size = 2; // Overload access // Accessing via subscripts - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + T& operator[](size_t i); + const T& operator[](size_t i) const; // Arithmetic inline Vector operator()() const; // Creation inline Vector operator-() const; // Negation @@ -426,11 +427,11 @@ namespace pod { // POD information typedef T type_t; typedef T* container_t; - static const std::size_t size = 3; + static const size_t size = 3; // Overload access // Accessing via subscripts - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + T& operator[](size_t i); + const T& operator[](size_t i) const; // Arithmetic inline Vector operator()() const; // Creation inline Vector operator-() const; // Negation @@ -483,11 +484,11 @@ namespace pod { // POD information typedef T type_t; typedef T* container_t; - static const std::size_t size = 4; + static const size_t size = 4; // Overload access // Accessing via subscripts - T& operator[](std::size_t i); - const T& operator[](std::size_t i) const; + T& operator[](size_t i); + const T& operator[](size_t i) const; // Arithmetic inline Vector operator()() const; // Creation inline Vector operator-() const; // Negation diff --git a/engine/inc/uf/utils/math/vector/pod.inl b/engine/inc/uf/utils/math/vector/pod.inl index 1dd322df..33d14b01 100644 --- a/engine/inc/uf/utils/math/vector/pod.inl +++ b/engine/inc/uf/utils/math/vector/pod.inl @@ -22,7 +22,7 @@ template pod::Vector /*UF_API*/ uf::vector::cast( const U& from ) { alignas(16) pod::Vector to; #pragma unroll // GCC unroll N - for ( uint_fast8_t i = 0; i < N && i < U::size; ++i ) + for ( auto i = 0; i < N && i < U::size; ++i ) to[i] = from[i]; return to; } @@ -35,7 +35,7 @@ template // Equality check between two vectors (equal bool /*UF_API*/ uf::vector::equals( const T& left, const T& right ) { // return uf::vector::compareTo(left, right) == 0; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) if ( left[i] != right[i] ) return false; return true; } @@ -47,18 +47,18 @@ T /*UF_API*/ uf::vector::add( const T& left, const T& right ) { #endif alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = left[i] + right[i]; return res; } template // Multiplies this vector by a scalar -T /*UF_API*/ uf::vector::add( const T& vector, const typename T::type_t& scalar ) { +T /*UF_API*/ uf::vector::add( const T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return uf::simd::add( vector, scalar ); #endif alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = vector[i] + scalar; return res; } @@ -69,18 +69,18 @@ T /*UF_API*/ uf::vector::subtract( const T& left, const T& right ) { #endif alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = left[i] - right[i]; return res; } template // Multiplies this vector by a scalar -T /*UF_API*/ uf::vector::subtract( const T& vector, const typename T::type_t& scalar ) { +T /*UF_API*/ uf::vector::subtract( const T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return uf::simd::sub( vector, scalar ); #endif alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = vector[i] - scalar; return res; } @@ -91,18 +91,18 @@ T /*UF_API*/ uf::vector::multiply( const T& left, const T& right ) { #endif alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = left[i] * right[i]; return res; } template // Multiplies this vector by a scalar -T /*UF_API*/ uf::vector::multiply( const T& vector, const typename T::type_t& scalar ) { +T /*UF_API*/ uf::vector::multiply( const T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return uf::simd::mul( vector, scalar ); #endif alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = vector[i] * scalar; return res; } @@ -113,32 +113,34 @@ T /*UF_API*/ uf::vector::divide( const T& left, const T& right ) { #elif UF_ENV_DREAMCAST alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = MATH_Fast_Divide(left[i], right[i]); return res; #else alignas(16) T res; + scalar = 1.0 / scalar; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) - res[i] = left[i] / right[i]; + for ( auto i = 0; i < T::size; ++i ) + res[i] = left[i] * right[i]; return res; #endif } template // Divides this vector by a scalar -T /*UF_API*/ uf::vector::divide( const T& vector, const typename T::type_t& scalar ) { +T /*UF_API*/ uf::vector::divide( const T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return uf::simd::div( vector, scalar ); #elif UF_ENV_DREAMCAST alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = MATH_Fast_Divide(vector[i], scalar); return res; #else alignas(16) T res; + scalar = 1.0 / scalar; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) - res[i] = vector[i] / scalar; + for ( auto i = 0; i < T::size; ++i ) + res[i] = vector[i] * scalar; return res; #endif } @@ -146,7 +148,7 @@ template // Compute the sum of all components typename T::type_t /*UF_API*/ uf::vector::sum( const T& vector ) { typename T::type_t res = 0; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res += vector[i]; return res; } @@ -154,7 +156,7 @@ template // Compute the product of all components typename T::type_t /*UF_API*/ uf::vector::product( const T& vector ) { typename T::type_t res = 0; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res *= vector[i]; return res; } @@ -165,135 +167,135 @@ T /*UF_API*/ uf::vector::negate( const T& vector ) { #endif alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = -vector[i]; return res; } // Writes to first value template // Adds two vectors of same type and size together -T& /*UF_API*/ uf::vector::add( T& left, const T& right ) { +T& /*UF_API*/ uf::vector::add_( T& left, const T& right ) { #if UF_USE_SIMD return left = uf::vector::add( (const T&) left, right ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) left[i] += right[i]; return left; } template // Multiplies this vector by a scalar -T& /*UF_API*/ uf::vector::add( T& vector, const typename T::type_t& scalar ) { +T& /*UF_API*/ uf::vector::add_( T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return vector = uf::vector::add( (const T&) vector, scalar ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) vector[i] += scalar; return vector; } template // Subtracts two vectors of same type and size together -T& /*UF_API*/ uf::vector::subtract( T& left, const T& right ) { +T& /*UF_API*/ uf::vector::subtract_( T& left, const T& right ) { #if UF_USE_SIMD return left = uf::vector::subtract( (const T&) left, right ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) left[i] -= right[i]; return left; } template // Multiplies this vector by a scalar -T& /*UF_API*/ uf::vector::subtract( T& vector, const typename T::type_t& scalar ) { +T& /*UF_API*/ uf::vector::subtract_( T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return vector = uf::vector::subtract( (const T&) vector, scalar ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) vector[i] -= scalar; return vector; } template // Multiplies two vectors of same type and size together -T& /*UF_API*/ uf::vector::multiply( T& left, const T& right ) { +T& /*UF_API*/ uf::vector::multiply_( T& left, const T& right ) { #if UF_USE_SIMD return left = uf::vector::multiply( (const T&) left, right ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) left[i] *= right[i]; return left; } template // Multiplies this vector by a scalar -T& /*UF_API*/ uf::vector::multiply( T& vector, const typename T::type_t& scalar ) { +T& /*UF_API*/ uf::vector::multiply_( T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return vector = uf::vector::multiply( (const T&) vector, scalar ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) vector[i] *= scalar; return vector; } template // Divides two vectors of same type and size together -T& /*UF_API*/ uf::vector::divide( T& left, const T& right ) { +T& /*UF_API*/ uf::vector::divide_( T& left, const T& right ) { #if UF_USE_SIMD return left = uf::vector::divide( (const T&) left, right ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) left[i] /= right[i]; return left; } template // Divides this vector by a scalar -T& /*UF_API*/ uf::vector::divide( T& vector, const typename T::type_t& scalar ) { +T& /*UF_API*/ uf::vector::divide_( T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ) { #if UF_USE_SIMD return vector = uf::vector::divide( (const T&) vector, scalar ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) vector[i] /= scalar; return vector; } template // Flip sign of all components -T& /*UF_API*/ uf::vector::negate( T& vector ) { +T& /*UF_API*/ uf::vector::negate_( T& vector ) { #if UF_USE_SIMD return vector = uf::vector::negate( (const T&) vector ); #endif #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) vector[i] = -vector[i]; return vector; } template // Normalizes a vector -T& /*UF_API*/ uf::vector::normalize( T& vector ) { +T& /*UF_API*/ uf::vector::normalize_( T& vector ) { typename T::type_t norm = uf::vector::norm(vector); if ( norm == 0 ) return vector; - return uf::vector::divide(vector, norm); + return vector = uf::vector::divide((const T&) vector, norm); } template // T /*UF_API*/ uf::vector::min( const T& left, const T& right ) { T res = left; - for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::min( left[i], right[i] ); + for ( auto i = 0; i < T::size; ++i ) res[i] = std::min( left[i], right[i] ); return res; } template // T /*UF_API*/ uf::vector::max( const T& left, const T& right ) { T res; - for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::max( left[i], right[i] ); + for ( auto i = 0; i < T::size; ++i ) res[i] = std::max( left[i], right[i] ); return res; } template // T /*UF_API*/ uf::vector::ceil( const T& vector ) { T res; - for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::ceil( vector[i] ); + for ( auto i = 0; i < T::size; ++i ) res[i] = std::ceil( vector[i] ); return res; } template // T /*UF_API*/ uf::vector::floor( const T& vector ) { T res; - for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = std::floor( vector[i] ); + for ( auto i = 0; i < T::size; ++i ) res[i] = std::floor( vector[i] ); return res; } template // T /*UF_API*/ uf::vector::round( const T& vector ) { T res; - for ( uint_fast8_t i = 0; i < T::size; ++i ) res[i] = ::round( vector[i] ); + for ( auto i = 0; i < T::size; ++i ) res[i] = ::round( vector[i] ); return res; } // Complex arithmetic @@ -317,7 +319,7 @@ T /*UF_API*/ uf::vector::lerp( const T& from, const T& to, double delta, bool cl #if UF_ENV_DREAMCAST alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = MATH_Lerp( from[i], to[i], delta ); return res; #elif UF_USE_SIMD @@ -332,7 +334,7 @@ T /*UF_API*/ uf::vector::lerp( const T& from, const T& to, const T& delta, bool #if UF_ENV_DREAMCAST alignas(16) T res; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < T::size; ++i ) + for ( auto i = 0; i < T::size; ++i ) res[i] = MATH_Lerp( from[i], to[i], delta[i] ); return res; #elif UF_USE_SIMD @@ -370,11 +372,16 @@ typename T::type_t /*UF_API*/ uf::vector::distanceSquared( const T& a, const T& return MATH_Sum_of_Squares( UF_EZ_VEC4( delta, T::size ) ); #elif UF_USE_SIMD uf::simd::value delta = uf::simd::sub( b, a ); - return uf::vector::sum( uf::simd::vector( uf::simd::mul( delta, delta ) ) ); +// return uf::vector::sum( uf::simd::vector( uf::simd::mul( delta, delta ) ) ); + return uf::simd::dot( delta, delta ); #else + alignas(16) T delta = uf::vector::subtract(b, a); + return uf::vector::dot( delta, delta ); +/* alignas(16) T delta = uf::vector::subtract(b, a); uf::vector::multiply( delta, delta ); return uf::vector::sum(delta); +*/ #endif } template // Compute the distance between two vectors @@ -455,7 +462,7 @@ uf::stl::string /*UF_API*/ uf::vector::toString( const T& v ) { uf::stl::stringstream ss; ss << "Vector("; #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < size; ++i ) { + for ( auto i = 0; i < size; ++i ) { ss << v[i]; if ( i + 1 < size ) ss << ", "; } @@ -468,11 +475,11 @@ ext::json::Value /*UF_API*/ uf::vector::encode( const pod::Vector& v, const ext::json::Value json; if ( settings.quantize ) #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < N; ++i ) + for ( auto i = 0; i < N; ++i ) json[i] = uf::math::quantizeShort( v[i] ); else #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < N; ++i ) + for ( auto i = 0; i < N; ++i ) json[i] = v[i]; return json; } @@ -480,10 +487,10 @@ template pod::Vector& /*UF_API*/ uf::vector::decode( const ext::json::Value& json, pod::Vector& v ) { if ( ext::json::isArray(json) ) #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < N; ++i ) + for ( auto i = 0; i < N; ++i ) v[i] = json[i].as(v[i]); else if ( ext::json::isObject(json) ) { - uint_fast8_t i = 0; + auto i = 0; ext::json::forEach(json, [&](const ext::json::Value& c){ if ( i >= N ) return; v[i] = uf::math::unquantize( c.as(v[i]) ); @@ -497,10 +504,10 @@ pod::Vector /*UF_API*/ uf::vector::decode( const ext::json::Value& json, co pod::Vector v = _v; if ( ext::json::isArray(json) ) #pragma unroll // GCC unroll T::size - for ( uint_fast8_t i = 0; i < N; ++i ) + for ( auto i = 0; i < N; ++i ) v[i] = json[i].as(_v[i]); else if ( ext::json::isObject(json) ) { - uint_fast8_t i = 0; + auto i = 0; ext::json::forEach(json, [&](const ext::json::Value& c){ if ( i >= N ) return; v[i] = c.as(_v[i]); diff --git a/engine/inc/uf/utils/math/vector/redundancy.inl b/engine/inc/uf/utils/math/vector/redundancy.inl index d2a01267..cf7fa3ed 100644 --- a/engine/inc/uf/utils/math/vector/redundancy.inl +++ b/engine/inc/uf/utils/math/vector/redundancy.inl @@ -47,35 +47,35 @@ inline pod::Vector pod::Vector::operator/( T scalar ) const { } template // Addition set between two vectors inline pod::Vector& pod::Vector::operator +=( const pod::Vector& vector ) { - return uf::vector::add( *this, vector ); + return uf::vector::add_( *this, vector ); } template // Subtraction set between two vectors inline pod::Vector& pod::Vector::operator -=( const pod::Vector& vector ) { - return uf::vector::subtract( *this, vector ); + return uf::vector::subtract_( *this, vector ); } template // Multiplication set between two vectors inline pod::Vector& pod::Vector::operator *=( const pod::Vector& vector ) { - return uf::vector::multiply( *this, vector ); + return uf::vector::multiply_( *this, vector ); } template // Division set between two vectors inline pod::Vector& pod::Vector::operator /=( const pod::Vector& vector ) { - return uf::vector::divide( *this, vector ); + return uf::vector::divide_( *this, vector ); } template // Multiplication set with scalar inline pod::Vector& pod::Vector::operator +=( T scalar ) { - return uf::vector::add( *this, scalar ); + return uf::vector::add_( *this, scalar ); } template // Multiplication set with scalar inline pod::Vector& pod::Vector::operator -=( T scalar ) { - return uf::vector::subtract( *this, scalar ); + return uf::vector::subtract_( *this, scalar ); } template // Multiplication set with scalar inline pod::Vector& pod::Vector::operator *=( T scalar ) { - return uf::vector::multiply( *this, scalar ); + return uf::vector::multiply_( *this, scalar ); } template // Division set with scalar inline pod::Vector& pod::Vector::operator /=( T scalar ) { - return uf::vector::divide( *this, scalar ); + return uf::vector::divide_( *this, scalar ); } template // Equality check between two vectors (equals) inline bool pod::Vector::operator==( const pod::Vector& vector ) const { @@ -170,35 +170,35 @@ inline pod::Vector pod::Vector::operator/( T scalar ) const { } template // Addition set between two vectors inline pod::Vector& pod::Vector::operator +=( const pod::Vector& vector ) { - return uf::vector::add( *this, vector ); + return uf::vector::add_( *this, vector ); } template // Subtraction set between two vectors inline pod::Vector& pod::Vector::operator -=( const pod::Vector& vector ) { - return uf::vector::subtract( *this, vector ); + return uf::vector::subtract_( *this, vector ); } template // Multiplication set between two vectors inline pod::Vector& pod::Vector::operator *=( const pod::Vector& vector ) { - return uf::vector::multiply( *this, vector ); + return uf::vector::multiply_( *this, vector ); } template // Division set between two vectors inline pod::Vector& pod::Vector::operator /=( const pod::Vector& vector ) { - return uf::vector::divide( *this, vector ); + return uf::vector::divide_( *this, vector ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator +=( T scalar ) { - return uf::vector::add( *this, scalar ); + return uf::vector::add_( *this, scalar ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator -=( T scalar ) { - return uf::vector::subtract( *this, scalar ); + return uf::vector::subtract_( *this, scalar ); } template // Multiplication set with scalar inline pod::Vector& pod::Vector::operator *=( T scalar ) { - return uf::vector::multiply( *this, scalar ); + return uf::vector::multiply_( *this, scalar ); } template // Division set with scalar inline pod::Vector& pod::Vector::operator /=( T scalar ) { - return uf::vector::divide( *this, scalar ); + return uf::vector::divide_( *this, scalar ); } template // Equality check between two vectors (equals) inline bool pod::Vector::operator==( const pod::Vector& vector ) const { @@ -292,35 +292,35 @@ inline pod::Vector pod::Vector::operator/( T scalar ) const { } template // Addition set between two vectors inline pod::Vector& pod::Vector::operator +=( const pod::Vector& vector ) { - return uf::vector::add( *this, vector ); + return uf::vector::add_( *this, vector ); } template // Subtraction set between two vectors inline pod::Vector& pod::Vector::operator -=( const pod::Vector& vector ) { - return uf::vector::subtract( *this, vector ); + return uf::vector::subtract_( *this, vector ); } template // Multiplication set between two vectors inline pod::Vector& pod::Vector::operator *=( const pod::Vector& vector ) { - return uf::vector::multiply( *this, vector ); + return uf::vector::multiply_( *this, vector ); } template // Division set between two vectors inline pod::Vector& pod::Vector::operator /=( const pod::Vector& vector ) { - return uf::vector::divide( *this, vector ); + return uf::vector::divide_( *this, vector ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator+=( T scalar ) { - return uf::vector::add( *this, scalar ); + return uf::vector::add_( *this, scalar ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator-=( T scalar ) { - return uf::vector::subtract( *this, scalar ); + return uf::vector::subtract_( *this, scalar ); } template // Multiplication set with scalar inline pod::Vector& pod::Vector::operator *=( T scalar ) { - return uf::vector::multiply( *this, scalar ); + return uf::vector::multiply_( *this, scalar ); } template // Division set with scalar inline pod::Vector& pod::Vector::operator /=( T scalar ) { - return uf::vector::divide( *this, scalar ); + return uf::vector::divide_( *this, scalar ); } template // Equality check between two vectors (equals) inline bool pod::Vector::operator==( const pod::Vector& vector ) const { @@ -414,35 +414,35 @@ inline pod::Vector pod::Vector::operator/( T scalar ) const { } template // Addition set between two vectors inline pod::Vector& pod::Vector::operator +=( const pod::Vector& vector ) { - return uf::vector::add( *this, vector ); + return uf::vector::add_( *this, vector ); } template // Subtraction set between two vectors inline pod::Vector& pod::Vector::operator -=( const pod::Vector& vector ) { - return uf::vector::subtract( *this, vector ); + return uf::vector::subtract_( *this, vector ); } template // Multiplication set between two vectors inline pod::Vector& pod::Vector::operator *=( const pod::Vector& vector ) { - return uf::vector::multiply( *this, vector ); + return uf::vector::multiply_( *this, vector ); } template // Division set between two vectors inline pod::Vector& pod::Vector::operator /=( const pod::Vector& vector ) { - return uf::vector::divide( *this, vector ); + return uf::vector::divide_( *this, vector ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator +=( T scalar ) { - return uf::vector::add( *this, scalar ); + return uf::vector::add_( *this, scalar ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator -=( T scalar ) { - return uf::vector::subtract( *this, scalar ); + return uf::vector::subtract_( *this, scalar ); } template // Multiplication set with scalar inline pod::Vector& pod::Vector::operator *=( T scalar ) { - return uf::vector::multiply( *this, scalar ); + return uf::vector::multiply_( *this, scalar ); } template // Division set with scalar inline pod::Vector& pod::Vector::operator /=( T scalar ) { - return uf::vector::divide( *this, scalar ); + return uf::vector::divide_( *this, scalar ); } template // Equality check between two vectors (equals) inline bool pod::Vector::operator==( const pod::Vector& vector ) const { @@ -549,35 +549,35 @@ inline pod::Vector pod::Vector::operator/( T scalar ) const { } template // Addition set between two vectors inline pod::Vector& pod::Vector::operator +=( const pod::Vector& vector ) { - return uf::vector::add( *this, vector ); + return uf::vector::add_( *this, vector ); } template // Subtraction set between two vectors inline pod::Vector& pod::Vector::operator -=( const pod::Vector& vector ) { - return uf::vector::subtract( *this, vector ); + return uf::vector::subtract_( *this, vector ); } template // Multiplication set between two vectors inline pod::Vector& pod::Vector::operator *=( const pod::Vector& vector ) { - return uf::vector::multiply( *this, vector ); + return uf::vector::multiply_( *this, vector ); } template // Division set between two vectors inline pod::Vector& pod::Vector::operator /=( const pod::Vector& vector ) { - return uf::vector::divide( *this, vector ); + return uf::vector::divide_( *this, vector ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator+=( T scalar ) { - return uf::vector::add( *this, scalar ); + return uf::vector::add_( *this, scalar ); } template // Multiplication with scalar inline pod::Vector& pod::Vector::operator-=( T scalar ) { - return uf::vector::subtract( *this, scalar ); + return uf::vector::subtract_( *this, scalar ); } template // Multiplication set with scalar inline pod::Vector& pod::Vector::operator *=( T scalar ) { - return uf::vector::multiply( *this, scalar ); + return uf::vector::multiply_( *this, scalar ); } template // Division set with scalar inline pod::Vector& pod::Vector::operator /=( T scalar ) { - return uf::vector::divide( *this, scalar ); + return uf::vector::divide_( *this, scalar ); } template // Equality check between two vectors (equals) inline bool pod::Vector::operator==( const pod::Vector& vector ) const { diff --git a/engine/inc/uf/utils/mesh/mesh.h b/engine/inc/uf/utils/mesh/mesh.h index 527b842c..601c45ca 100644 --- a/engine/inc/uf/utils/mesh/mesh.h +++ b/engine/inc/uf/utils/mesh/mesh.h @@ -31,13 +31,15 @@ namespace ext { ext::RENDERER::enums::Type::type_t type = 0; size_t components = 0; - bool operator==( const AttributeDescriptor& right ) const { return + bool operator==( const AttributeDescriptor& right ) const { return name == right.name; + /* offset == right.offset && size == right.size && format == right.format && name == right.name && type == right.type && components == right.components; + */ } bool operator!=( const AttributeDescriptor& right ) const { return !(*this == right); }; }; @@ -323,8 +325,4 @@ namespace pod { static UF_API uf::stl::vector descriptor; }; -} - - -#include -#include "mesh.inl" \ No newline at end of file +} \ No newline at end of file diff --git a/engine/inc/uf/utils/mesh/mesh.inl b/engine/inc/uf/utils/mesh/mesh.inl deleted file mode 100644 index ae9335a2..00000000 --- a/engine/inc/uf/utils/mesh/mesh.inl +++ /dev/null @@ -1,163 +0,0 @@ -#if 0 -template -void uf::Mesh::initialize( size_t o ) { - this->optimize(o); - if ( this->indices.empty() ) this->generateIndices(); - this->updateDescriptor(); -} -template -void uf::Mesh::expand( bool check ) { - if ( this->indices.empty() ) return; - uf::stl::vector _vertices = std::move( this->vertices ); - this->vertices.clear(); - this->vertices.reserve( this->indices.size() ); - if ( !check ) { - for ( auto& index : this->indices ) this->vertices.emplace_back( _vertices[index] ); - } else { - uf::stl::vector cache; - bool valid = true; - cache.reserve(3); - for ( auto& index : this->indices ) { - // flush cache - if ( cache.size() == 3 ) { - if ( valid ) { - this->vertices.emplace_back(cache[0]); - this->vertices.emplace_back(cache[1]); - this->vertices.emplace_back(cache[2]); - } - cache.clear(); - valid = true; - } - // invalid index, mark cache as invalid - if ( index >= _vertices.size() ) { - UF_MSG_DEBUG("Invalid index: Max: " << _vertices.size() << "\tGot: " << index); - valid = false; - cache.emplace_back( cache.empty() ? vertex_t{} : cache.back() ); - continue; - } - // fill cache - cache.emplace_back( _vertices[index] ); - } - } - this->generateIndices(); - this->updateDescriptor(); -} -template -void uf::Mesh::updateDescriptor() { - attributes.vertex.size = sizeof(vertex_t); - attributes.vertex.length = this->vertices.size(); - attributes.vertex.pointer = &this->vertices[0]; - attributes.vertex.descriptor = vertex_t::descriptor; - - attributes.index.size = sizeof(indices_t); - attributes.index.length = this->indices.size(); - attributes.index.pointer = &this->indices[0]; -} -template -void uf::Mesh::destroy() { - this->indices.clear(); - this->vertices.clear(); -} - -template -uf::Mesh uf::Mesh::simplify( float threshold ) { - size_t target = size_t(this->indices.size() * threshold); - float error = 1e-2f; - uf::Mesh lod; - lod.indices.resize(this->indices.size()); - lod.indices.resize(meshopt_simplify(&lod.indices[0], &this->indices[0], this->indices.size(), (float*) &this->vertices[0].position, this->vertices.size(), sizeof(T), target, error)); - lod.vertices.resize(lod.indices.size() < this->vertices.size() ? lod.indices.size() : this->vertices.size()); // note: this is just to reduce the cost of resize() - lod.vertices.resize(meshopt_optimizeVertexFetch(&lod.vertices[0], &lod.indices[0], lod.indices.size(), &this->vertices[0], this->vertices.size(), sizeof(T))); - return lod; -} -template -void uf::Mesh::optimize( size_t o ) { -#if UF_USE_MESHOPTIMIZER - ext::meshopt::optimize( *this, o ); -#endif - this->updateDescriptor(); -} -template -void uf::Mesh::insert( const uf::Mesh& mesh ) { - size_t startVertices = this->vertices.size(); - size_t startIndices = this->indices.size(); - - this->vertices.reserve( startVertices + mesh.vertices.size() ); - this->indices.reserve( startIndices + mesh.indices.size() ); - for ( auto& v : mesh.vertices ) this->vertices.emplace_back( v ); - for ( auto& i : mesh.indices ) this->indices.emplace_back( i + startVertices ); - this->updateDescriptor(); -} - -template -void uf::Mesh::resizeVertices( size_t n ) { - this->vertices.resize(n); - this->updateDescriptor(); -} -template -void uf::Mesh::resizeIndices( size_t n ) { - this->indices.resize(n); - this->updateDescriptor(); -} - -// - -template -bool pod::VaryingMesh::is() const { -#if 0 - return uf::pointeredUserdata::is>(); -#else - if ( attributes.vertex.descriptor.size() != T::descriptor.size() || - // vertex types are the same size - attributes.vertex.size != sizeof(T) || - // index types are the same size - attributes.index.size != sizeof(U) ) return false; - - for ( size_t i = 0; i < attributes.vertex.descriptor.size(); ++i ) { - if ( attributes.vertex.descriptor[i].offset != attributes.vertex.descriptor[i].offset || attributes.vertex.descriptor[i].size != attributes.vertex.descriptor[i].size || attributes.vertex.descriptor[i].components != attributes.vertex.descriptor[i].components ) return false; - } - return true; -#if 0 -return - // descriptors are the same size - attributes.vertex.descriptor.size() == T::descriptor.size() && - // vertex types are the same size - attributes.vertex.size == sizeof(T) && - // index types are the same size - attributes.index.size == sizeof(U) && - // attributes are the same - std::equal( attributes.vertex.descriptor.begin(), attributes.vertex.descriptor.end(), T::descriptor.begin() ); -#endif -#endif -} - -template -uf::Mesh& pod::VaryingMesh::get() { - if ( !userdata.data ) set(); - return uf::pointeredUserdata::get>( userdata ); -} - -template -const uf::Mesh& pod::VaryingMesh::get() const { - UF_ASSERT( userdata.data ); - return uf::pointeredUserdata::get>( userdata ); -} - -template -void pod::VaryingMesh::set( const uf::Mesh& mesh ) { - if ( userdata.data ) uf::pointeredUserdata::destroy( userdata ); - userdata = uf::pointeredUserdata::create( mesh ); - attributes = mesh.attributes; -} - -template -void pod::VaryingMesh::insert( const pod::VaryingMesh& mesh ) { - get().insert( mesh.get() ); - updateDescriptor(); -} -template -void pod::VaryingMesh::insert( const uf::Mesh& mesh ) { - get().insert( mesh ); - updateDescriptor(); -} -#endif \ No newline at end of file diff --git a/engine/inc/uf/utils/time/time.h b/engine/inc/uf/utils/time/time.h index bafe7ead..8e33047d 100644 --- a/engine/inc/uf/utils/time/time.h +++ b/engine/inc/uf/utils/time/time.h @@ -6,7 +6,7 @@ namespace uf { template - class UF_API Time { + class /*UF_API*/ Time { public: typedef T time_t; typedef spec::Time::exp_t exp_t; @@ -19,39 +19,41 @@ namespace uf { static const uf::Time::exp_t microseconds = -6; static const uf::Time::exp_t nanoseconds = -9; - UF_API_CALL Time(uf::Time::time_t t = 0, uf::Time::exp_t b = spec::Time::unit ); + Time(uf::Time::time_t t = 0, uf::Time::exp_t b = spec::Time::unit ); - void UF_API_CALL set(uf::Time::time_t t); - void UF_API_CALL set(uf::Time::time_t t, uf::Time::exp_t b); - inline void UF_API_CALL fromSeconds(uf::Time::time_t t); - inline void UF_API_CALL fromMilliseconds(uf::Time::time_t t); - inline void UF_API_CALL fromMicroseconds(uf::Time::time_t t); - inline void UF_API_CALL fromNanoseconds(uf::Time::time_t t); + void set(uf::Time::time_t t); + void set(uf::Time::time_t t, uf::Time::exp_t b); + inline void fromSeconds(uf::Time::time_t t); + inline void fromMilliseconds(uf::Time::time_t t); + inline void fromMicroseconds(uf::Time::time_t t); + inline void fromNanoseconds(uf::Time::time_t t); - uf::Time::time_t UF_API_CALL get() const; - uf::Time::exp_t UF_API_CALL getBase() const; + uf::Time::time_t get() const; + uf::Time::exp_t getBase() const; - uf::Time::time_t UF_API_CALL asBase(uf::Time::exp_t base = spec::Time::unit ); - inline uf::Time::time_t UF_API_CALL asSeconds(); - inline uf::Time::time_t UF_API_CALL asMilliseconds(); - inline uf::Time::time_t UF_API_CALL asMicroseconds(); - inline uf::Time::time_t UF_API_CALL asNanoseconds(); - double UF_API_CALL asDouble(); + uf::Time::time_t asBase(uf::Time::exp_t base = spec::Time::unit ); + inline uf::Time::time_t asSeconds(); + inline uf::Time::time_t asMilliseconds(); + inline uf::Time::time_t asMicroseconds(); + inline uf::Time::time_t asNanoseconds(); + float asFloat(); + double asDouble(); - uf::Time& UF_API_CALL operator=( const uf::Time::time_t& t ); - UF_API_CALL operator double(); - bool UF_API_CALL operator>( const uf::Time::time_t& t ); - bool UF_API_CALL operator>=( const uf::Time::time_t& t ); - bool UF_API_CALL operator<( const uf::Time::time_t& t ); - bool UF_API_CALL operator<=( const uf::Time::time_t& t ); - bool UF_API_CALL operator==( const uf::Time::time_t& t ); - bool UF_API_CALL operator>( const uf::Time& t ); - bool UF_API_CALL operator>=( const uf::Time& t ); - bool UF_API_CALL operator<( const uf::Time& t ); - bool UF_API_CALL operator<=( const uf::Time& t ); - bool UF_API_CALL operator==( const uf::Time& t ); - uf::Time UF_API_CALL operator-( const uf::Time& t ); - uf::Time UF_API_CALL operator+( const uf::Time& t ); + uf::Time& operator=( const uf::Time::time_t& t ); + operator float(); + operator double(); + bool operator>( const uf::Time::time_t& t ); + bool operator>=( const uf::Time::time_t& t ); + bool operator<( const uf::Time::time_t& t ); + bool operator<=( const uf::Time::time_t& t ); + bool operator==( const uf::Time::time_t& t ); + bool operator>( const uf::Time& t ); + bool operator>=( const uf::Time& t ); + bool operator<( const uf::Time& t ); + bool operator<=( const uf::Time& t ); + bool operator==( const uf::Time& t ); + uf::Time operator-( const uf::Time& t ); + uf::Time operator+( const uf::Time& t ); }; template class /*UF_API*/ Timer { diff --git a/engine/inc/uf/utils/time/time.inl b/engine/inc/uf/utils/time/time.inl index 116e46d9..14ba0e8d 100644 --- a/engine/inc/uf/utils/time/time.inl +++ b/engine/inc/uf/utils/time/time.inl @@ -61,6 +61,10 @@ inline typename uf::Time::time_t uf::Time::asNanoseconds() { return this->asBase( uf::Time::nanoseconds ); } template +float uf::Time::asFloat() { + return this->m_time * pow(10.0f, this->m_exp); +} +template double uf::Time::asDouble() { return this->m_time * pow(10.0, this->m_exp); } @@ -75,6 +79,10 @@ uf::Time::operator double() { return this->asDouble(); } template +uf::Time::operator float() { + return this->asFloat(); +} +template bool uf::Time::operator>( const uf::Time::time_t& t ) { return this->m_time > t; } diff --git a/engine/src/engine/behavior/behavior.cpp b/engine/src/engine/behavior/behavior.cpp index 66a0208c..9b197b0f 100644 --- a/engine/src/engine/behavior/behavior.cpp +++ b/engine/src/engine/behavior/behavior.cpp @@ -65,7 +65,7 @@ void uf::Behaviors::generateGraph() { } } -#define UF_BEHAVIOR_POLYFILL UF_BEHAVIOR_POLYFILL_FAST +#define UF_BEHAVIOR_POLYFILL UF_BEHAVIOR_POLYFILL_GRAPH #define UF_BEHAVIOR_POLYFILL_SAFE(f)\ const bool forwardIteration = true;\ if ( forwardIteration ) for ( auto& behavior : m_behaviors ) behavior.f(self);\ @@ -82,12 +82,30 @@ void uf::Behaviors::initialize() { void uf::Behaviors::tick() { uf::Object& self = *((uf::Object*) this); if ( !self.isValid() ) return; + if ( m_graph.tick.empty() ) return; // if ( !m_graph.tickMT.empty() ) uf::thread::batchWorkers(m_graph.tickMT, false); +/* + UF_TIMER_MULTITRACE_START("Starting " << self.getName() << ": " << self.getUid()); + for ( auto& fun : m_graph.tick ) { + fun(self); + UF_TIMER_MULTITRACE(""); + } + UF_TIMER_MULTITRACE_END("Finished " << self.getName() << ": " << self.getUid()) +*/ UF_BEHAVIOR_POLYFILL(tick) } void uf::Behaviors::render() { uf::Object& self = *((uf::Object*) this); if ( !self.isValid() ) return; + if ( m_graph.render.empty() ) return; +/* + UF_TIMER_MULTITRACE_START("Starting " << self.getName() << ": " << self.getUid()); + for ( auto& fun : m_graph.render ) { + fun(self); + UF_TIMER_MULTITRACE(""); + } + UF_TIMER_MULTITRACE_END("Finished " << self.getName() << ": " << self.getUid()) +*/ UF_BEHAVIOR_POLYFILL(render) } void uf::Behaviors::destroy() { diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index c1497c5d..4fa96d3f 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -23,18 +23,14 @@ pod::Graph::Storage uf::graph::storage; UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Base, UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32B32_SFLOAT, position) + UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R8G8B8A8_UNORM, color) UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32_SFLOAT, uv) UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32_SFLOAT, st) -); -UF_VERTEX_DESCRIPTOR(uf::graph::mesh::ID, - UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32B32_SFLOAT, position) - UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32_SFLOAT, uv) - UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32_SFLOAT, st) - UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32B32_SFLOAT, normal) - UF_VERTEX_DESCRIPTION(uf::graph::mesh::ID, R32G32B32_SFLOAT, tangent) + UF_VERTEX_DESCRIPTION(uf::graph::mesh::Base, R32G32B32_SFLOAT, normal) ); UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Skinned, UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, position) + UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R8G8B8A8_UNORM, color) UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32_SFLOAT, uv) UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32_SFLOAT, st) UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32_SFLOAT, normal) @@ -355,14 +351,14 @@ void uf::graph::process( pod::Graph& graph ) { auto& image = uf::graph::storage.images[keyName]; auto& texture = uf::graph::storage.texture2Ds[keyName]; if ( !texture.generated() ) { - texture.loadFromImage( image ); - #if UF_ENV_DREAMCAST - image.clear(); - #endif if ( graph.metadata["filter"].as() == "NEAREST" ) { texture.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST; texture.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST; } + texture.loadFromImage( image ); + #if UF_ENV_DREAMCAST + image.clear(); + #endif } } @@ -468,7 +464,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) if ( uf::string::split( node.name, "_" ).back() == "Orientation" ) return; // for dreamcast, ignore lights if we're baked #if UF_USE_OPENGL - if ( graph.metadata["lightmapped"].as() ) if ( graph.lights.count(node.name) > 0 ) return; +// if ( graph.metadata["lightmapped"].as() ) + if ( graph.lights.count(node.name) > 0 ) return; #endif //UF_MSG_DEBUG( "Loading " << node.name ); // create child if requested @@ -814,8 +811,10 @@ void uf::graph::initialize( pod::Graph& graph ) { }); } -void uf::graph::animate( pod::Graph& graph, const uf::stl::string& name, float speed, bool immediate ) { +void uf::graph::animate( pod::Graph& graph, const uf::stl::string& _name, float speed, bool immediate ) { if ( !(graph.metadata["flags"]["SKINNED"].as()) ) return; + const uf::stl::string name = graph.name + "/" + _name; +// UF_MSG_DEBUG( graph.name << " " << name ); // if ( graph.animations.count( name ) > 0 ) { if ( uf::graph::storage.animations.map.count( name ) > 0 ) { // if already playing, ignore it @@ -844,12 +843,13 @@ void uf::graph::update( pod::Graph& graph, float delta ) { // no skins if ( !(graph.metadata["flags"]["SKINNED"].as()) ) return; + if ( graph.sequence.empty() ) goto UPDATE; if ( graph.settings.animations.override.a >= 0 ) goto OVERRIDE; { uf::stl::string name = graph.sequence.front(); pod::Animation* animation = &uf::graph::storage.animations.map[name]; // &graph.animations[name]; - // std::cout << "ANIMATION: " << name << "\t" << animation->cur << std::endl; + // UF_MSG_DEBUG("ANIMATION: " << name << "\t" << animation->cur); animation->cur += delta * graph.settings.animations.speed; // * graph.settings.animations.override.speed; if ( animation->end < animation->cur ) { animation->cur = graph.settings.animations.loop ? animation->cur - animation->end : 0; @@ -884,7 +884,7 @@ void uf::graph::update( pod::Graph& graph, float delta ) { goto UPDATE; } OVERRIDE: - // std::cout << "OVERRIDED: " << graph.settings.animations.override.a << "\t" << -std::numeric_limits::max() << std::endl; +// UF_MSG_DEBUG("OVERRIDED: " << graph.settings.animations.override.a << "\t" << -std::numeric_limits::max()); for ( auto pair : graph.settings.animations.override.map ) { graph.nodes[pair.first].transform.position = uf::vector::mix( pair.second.first.position, pair.second.second.position, graph.settings.animations.override.a ); graph.nodes[pair.first].transform.orientation = uf::quaternion::normalize( uf::quaternion::slerp(pair.second.first.orientation, pair.second.second.orientation, graph.settings.animations.override.a) ); diff --git a/engine/src/engine/object/behaviors/lua.cpp b/engine/src/engine/object/behaviors/lua.cpp index c9f6be96..85846fcb 100644 --- a/engine/src/engine/object/behaviors/lua.cpp +++ b/engine/src/engine/object/behaviors/lua.cpp @@ -17,6 +17,8 @@ UF_BEHAVIOR_TRAITS_CPP(uf::LuaBehavior, ticks = false, renders = false, multithr #define this (&self) void uf::LuaBehavior::initialize( uf::Object& self ) { #if UF_USE_LUA + if ( !ext::lua::enabled ) return; + this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){ uf::stl::string filename = json["filename"].as(); uf::stl::string category = json["category"].as(); diff --git a/engine/src/ext/bullet/bullet.cpp b/engine/src/ext/bullet/bullet.cpp index e3b9c236..da80d82d 100644 --- a/engine/src/ext/bullet/bullet.cpp +++ b/engine/src/ext/bullet/bullet.cpp @@ -490,7 +490,7 @@ pod::Bullet& ext::bullet::create( uf::Object& object, float radius, float height return collider; } -void UF_API ext::bullet::move( pod::Bullet& collider, const pod::Vector3f& v, bool override ) { +void UF_API ext::bullet::setVelocity( pod::Bullet& collider, const pod::Vector3f& v ) { if ( !collider.body ) return; collider.body->setLinearVelocity( btVector3( v.x, v.y, v.z ) ); } @@ -537,6 +537,21 @@ void UF_API ext::bullet::activateCollision( pod::Bullet& collider, bool enabled collider.body->activate(enabled); } +float UF_API ext::bullet::rayCast( const pod::Vector3f& from, const pod::Vector3f& to ) { + btVector3 _from(from.x, from.y, from.z); + btVector3 _to(to.x, to.y, to.z); + + btCollisionWorld::ClosestRayResultCallback res(_from, _to); + ext::bullet::dynamicsWorld->rayTest(_from, _to, res); + if ( !res.hasHit() ) return -1.0; +/* + float length = uf::vector::distanceSquared( from, to ); + float depth = uf::vector::distanceSquared( from, pod::Vector3f{ res.m_hitPointWorld.getX(), res.m_hitPointWorld.getY(), res.m_hitPointWorld.getZ() } ); + return depth / length; +*/ + return uf::vector::distance( from, pod::Vector3f{ res.m_hitPointWorld.getX(), res.m_hitPointWorld.getY(), res.m_hitPointWorld.getZ() } ); +} + void UF_API ext::bullet::debugDraw( uf::Object& object ) { auto& mesh = ext::bullet::debugDrawer.getMesh(); if ( !mesh.vertex.count ) return; diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 5a80e8a4..906d395f 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -232,149 +232,288 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize auto& primitives = /*graph.storage*/uf::graph::storage.primitives[keyName]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[keyName]; mesh.bindIndirect(); - mesh.bind(); - /* - size_t primitiveID = 0; - */ - uf::stl::vector vertices; - uf::stl::vector indices; - for ( auto& p : m.primitives ) { - vertices.clear(); - indices.clear(); - auto& primitive = primitives.emplace_back(); + #if UF_USE_VULKAN + bool full = true; + #else + bool full = graph.metadata["flags"]["SKINNED"].as(); + #endif + if ( full ) { + mesh.bind(); + uf::stl::vector vertices; + uf::stl::vector indices; + for ( auto& p : m.primitives ) { + vertices.clear(); + indices.clear(); + auto& primitive = primitives.emplace_back(); - struct Attribute { - uf::stl::string name = ""; - size_t components = 1; - uf::stl::vector floats; - uf::stl::vector ints; - }; + struct Attribute { + uf::stl::string name = ""; + size_t components = 1; + uf::stl::vector floats; + uf::stl::vector ints; + }; - uf::stl::unordered_map attributes = { - {"POSITION", {}}, - {"TEXCOORD_0", {}}, - {"NORMAL", {}}, - {"TANGENT", {}}, - {"JOINTS_0", {}}, - {"WEIGHTS_0", {}}, - }; + uf::stl::unordered_map attributes = { + {"POSITION", {}}, + {"TEXCOORD_0", {}}, + {"NORMAL", {}}, + {"TANGENT", {}}, + {"JOINTS_0", {}}, + {"WEIGHTS_0", {}}, + }; - for ( auto& kv : attributes ) { - auto& attribute = kv.second; - attribute.name = kv.first; - auto it = p.attributes.find(attribute.name); - if ( it == p.attributes.end() ) continue; + for ( auto& kv : attributes ) { + auto& attribute = kv.second; + attribute.name = kv.first; + auto it = p.attributes.find(attribute.name); + if ( it == p.attributes.end() ) continue; - auto& accessor = model.accessors[it->second]; - auto& view = model.bufferViews[accessor.bufferView]; - - if ( attribute.name == "POSITION" ) { - vertices.resize(accessor.count); - primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] }; - primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] }; + auto& accessor = model.accessors[it->second]; + auto& view = model.bufferViews[accessor.bufferView]; + + if ( attribute.name == "POSITION" ) { + vertices.resize(accessor.count); + primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] }; + primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] }; + if ( !(graph.metadata["flags"]["INVERT"].as()) ){ + primitive.instance.bounds.min.x = -primitive.instance.bounds.min.x; + primitive.instance.bounds.max.x = -primitive.instance.bounds.max.x; + } + } + if ( attribute.name == "JOINTS_0" ) { + auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + attribute.components = accessor.ByteStride(view) / sizeof(uint16_t); + size_t len = accessor.count * attribute.components; + attribute.ints.assign( &buffer[0], &buffer[len] ); + } else { + auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + attribute.components = accessor.ByteStride(view) / sizeof(float); + size_t len = accessor.count * attribute.components; + attribute.floats.assign( &buffer[0], &buffer[len] ); + } + } + + for ( size_t i = 0; i < vertices.size(); ++i ) { + #define ITERATE_ATTRIBUTE( name, member )\ + if ( !attributes[name].ints.empty() ) { \ + for ( size_t j = 0; j < attributes[name].components; ++j )\ + vertex.member[j] = attributes[name].ints[i * attributes[name].components + j];\ + } else if ( !attributes[name].floats.empty() ) { \ + for ( size_t j = 0; j < attributes[name].components; ++j )\ + vertex.member[j] = attributes[name].floats[i * attributes[name].components + j];\ + } + + auto& vertex = vertices[i]; + ITERATE_ATTRIBUTE("POSITION", position); + ITERATE_ATTRIBUTE("TEXCOORD_0", uv); + ITERATE_ATTRIBUTE("NORMAL", normal); + ITERATE_ATTRIBUTE("TANGENT", tangent); + ITERATE_ATTRIBUTE("JOINTS_0", joints); + ITERATE_ATTRIBUTE("WEIGHTS_0", weights); + + #undef ITERATE_ATTRIBUTE + + // required due to reverse-Z projection matrix flipping the X axis as well + // default is to proceed with this if ( !(graph.metadata["flags"]["INVERT"].as()) ){ - primitive.instance.bounds.min.x = -primitive.instance.bounds.min.x; - primitive.instance.bounds.max.x = -primitive.instance.bounds.max.x; + vertex.position.x = -vertex.position.x; + vertex.normal.x = -vertex.normal.x; + vertex.tangent.x = -vertex.tangent.x; } } - if ( attribute.name == "JOINTS_0" ) { - auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - attribute.components = accessor.ByteStride(view) / sizeof(uint16_t); - size_t len = accessor.count * attribute.components; - attribute.ints.assign( &buffer[0], &buffer[len] ); - } else { - auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); - attribute.components = accessor.ByteStride(view) / sizeof(float); - size_t len = accessor.count * attribute.components; - attribute.floats.assign( &buffer[0], &buffer[len] ); + + if ( p.indices > -1 ) { + auto& accessor = model.accessors[p.indices]; + auto& view = model.bufferViews[accessor.bufferView]; + auto& buffer = model.buffers[view.buffer]; + + indices.reserve( static_cast(accessor.count) ); + + #define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]); + + const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]); + switch (accessor.componentType) { + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { + auto* buf = static_cast( pointer ); + COPY_INDICES() + break; + } + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { + auto* buf = static_cast( pointer ); + COPY_INDICES() + break; + } + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { + auto* buf = static_cast( pointer ); + COPY_INDICES() + break; + } + } + #undef COPY_INDICES } + + primitive.instance.materialID = p.material; + primitive.instance.primitiveID = primitives.size() - 1; + primitive.instance.meshID = meshID; + primitive.instance.objectID = 0; + + primitive.drawCommand.indices = indices.size(); + primitive.drawCommand.instances = 1; + primitive.drawCommand.indexID = 0; + primitive.drawCommand.vertexID = 0; + primitive.drawCommand.instanceID = 0; + primitive.drawCommand.vertices = vertices.size(); + + auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ + .indices = indices.size(), + .instances = 1, + .indexID = mesh.index.count, + .vertexID = mesh.vertex.count, + .instanceID = 0, + + + .vertices = vertices.size(), + }); + + mesh.insertVertices(vertices); + mesh.insertIndices(indices); } + } else { + mesh.bind(); + uf::stl::vector vertices; + uf::stl::vector indices; + for ( auto& p : m.primitives ) { + vertices.clear(); + indices.clear(); + auto& primitive = primitives.emplace_back(); - for ( size_t i = 0; i < vertices.size(); ++i ) { - #define ITERATE_ATTRIBUTE( name, member )\ - if ( !attributes[name].ints.empty() ) { \ - for ( size_t j = 0; j < attributes[name].components; ++j )\ - vertex.member[j] = attributes[name].ints[i * attributes[name].components + j];\ - } else if ( !attributes[name].floats.empty() ) { \ - for ( size_t j = 0; j < attributes[name].components; ++j )\ - vertex.member[j] = attributes[name].floats[i * attributes[name].components + j];\ + struct Attribute { + uf::stl::string name = ""; + size_t components = 1; + uf::stl::vector floats; + uf::stl::vector ints; + }; + + uf::stl::unordered_map attributes = { + {"POSITION", {}}, + {"TEXCOORD_0", {}}, + {"NORMAL", {}}, + }; + + for ( auto& kv : attributes ) { + auto& attribute = kv.second; + attribute.name = kv.first; + auto it = p.attributes.find(attribute.name); + if ( it == p.attributes.end() ) continue; + + auto& accessor = model.accessors[it->second]; + auto& view = model.bufferViews[accessor.bufferView]; + + if ( attribute.name == "POSITION" ) { + vertices.resize(accessor.count); + primitive.instance.bounds.min = pod::Vector3f{ accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] }; + primitive.instance.bounds.max = pod::Vector3f{ accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] }; + + if ( !(graph.metadata["flags"]["INVERT"].as()) ){ + primitive.instance.bounds.min.x = -primitive.instance.bounds.min.x; + primitive.instance.bounds.max.x = -primitive.instance.bounds.max.x; + } } - - auto& vertex = vertices[i]; - ITERATE_ATTRIBUTE("POSITION", position); - ITERATE_ATTRIBUTE("TEXCOORD_0", uv); - ITERATE_ATTRIBUTE("NORMAL", normal); - ITERATE_ATTRIBUTE("TANGENT", tangent); - ITERATE_ATTRIBUTE("JOINTS_0", joints); - ITERATE_ATTRIBUTE("WEIGHTS_0", weights); - - #undef ITERATE_ATTRIBUTE - - // required due to reverse-Z projection matrix flipping the X axis as well - // default is to proceed with this - if ( !(graph.metadata["flags"]["INVERT"].as()) ){ - vertex.position.x = -vertex.position.x; - vertex.normal.x = -vertex.normal.x; - vertex.tangent.x = -vertex.tangent.x; - } - } - - if ( p.indices > -1 ) { - auto& accessor = model.accessors[p.indices]; - auto& view = model.bufferViews[accessor.bufferView]; - auto& buffer = model.buffers[view.buffer]; - - indices.reserve( static_cast(accessor.count) ); - - #define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]); - - const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]); - switch (accessor.componentType) { - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { - auto* buf = static_cast( pointer ); - COPY_INDICES() - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { - auto* buf = static_cast( pointer ); - COPY_INDICES() - break; - } - case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { - auto* buf = static_cast( pointer ); - COPY_INDICES() - break; + if ( attribute.name == "JOINTS_0" ) { + auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + attribute.components = accessor.ByteStride(view) / sizeof(uint16_t); + size_t len = accessor.count * attribute.components; + attribute.ints.assign( &buffer[0], &buffer[len] ); + } else { + auto* buffer = reinterpret_cast(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset])); + attribute.components = accessor.ByteStride(view) / sizeof(float); + size_t len = accessor.count * attribute.components; + attribute.floats.assign( &buffer[0], &buffer[len] ); } } - #undef COPY_INDICES + + for ( size_t i = 0; i < vertices.size(); ++i ) { + #define ITERATE_ATTRIBUTE( name, member )\ + if ( !attributes[name].ints.empty() ) { \ + for ( size_t j = 0; j < attributes[name].components; ++j )\ + vertex.member[j] = attributes[name].ints[i * attributes[name].components + j];\ + } else if ( !attributes[name].floats.empty() ) { \ + for ( size_t j = 0; j < attributes[name].components; ++j )\ + vertex.member[j] = attributes[name].floats[i * attributes[name].components + j];\ + } + + auto& vertex = vertices[i]; + ITERATE_ATTRIBUTE("POSITION", position); + ITERATE_ATTRIBUTE("TEXCOORD_0", uv); + ITERATE_ATTRIBUTE("NORMAL", normal); + + #undef ITERATE_ATTRIBUTE + + // required due to reverse-Z projection matrix flipping the X axis as well + // default is to proceed with this + if ( !(graph.metadata["flags"]["INVERT"].as()) ){ + vertex.position.x = -vertex.position.x; + vertex.normal.x = -vertex.normal.x; + } + } + + if ( p.indices > -1 ) { + auto& accessor = model.accessors[p.indices]; + auto& view = model.bufferViews[accessor.bufferView]; + auto& buffer = model.buffers[view.buffer]; + + indices.reserve( static_cast(accessor.count) ); + + #define COPY_INDICES() for (size_t index = 0; index < accessor.count; index++) indices.emplace_back(buf[index]); + + const void* pointer = &(buffer.data[accessor.byteOffset + view.byteOffset]); + switch (accessor.componentType) { + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT: { + auto* buf = static_cast( pointer ); + COPY_INDICES() + break; + } + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: { + auto* buf = static_cast( pointer ); + COPY_INDICES() + break; + } + case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: { + auto* buf = static_cast( pointer ); + COPY_INDICES() + break; + } + } + #undef COPY_INDICES + } + + primitive.instance.materialID = p.material; + primitive.instance.primitiveID = primitives.size() - 1; + primitive.instance.meshID = meshID; + primitive.instance.objectID = 0; + + primitive.drawCommand.indices = indices.size(); + primitive.drawCommand.instances = 1; + primitive.drawCommand.indexID = 0; + primitive.drawCommand.vertexID = 0; + primitive.drawCommand.instanceID = 0; + primitive.drawCommand.vertices = vertices.size(); + + auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ + .indices = indices.size(), + .instances = 1, + .indexID = mesh.index.count, + .vertexID = mesh.vertex.count, + .instanceID = 0, + + + .vertices = vertices.size(), + }); + + mesh.insertVertices(vertices); + mesh.insertIndices(indices); } - - primitive.instance.materialID = p.material; - primitive.instance.primitiveID = primitives.size() - 1; - primitive.instance.meshID = meshID; - primitive.instance.objectID = 0; - - primitive.drawCommand.indices = indices.size(); - primitive.drawCommand.instances = 1; - primitive.drawCommand.indexID = 0; - primitive.drawCommand.vertexID = 0; - primitive.drawCommand.instanceID = 0; - primitive.drawCommand.vertices = vertices.size(); - - auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ - .indices = indices.size(), - .instances = 1, - .indexID = mesh.index.count, - .vertexID = mesh.vertex.count, - .instanceID = 0, - - - .vertices = vertices.size(), - }); - - mesh.insertVertices(vertices); - mesh.insertIndices(indices); } mesh.insertIndirects(drawCommands); mesh.updateDescriptor(); diff --git a/engine/src/ext/lua/lua.cpp b/engine/src/ext/lua/lua.cpp index 91189bc6..fa08fd28 100644 --- a/engine/src/ext/lua/lua.cpp +++ b/engine/src/ext/lua/lua.cpp @@ -1,5 +1,6 @@ #include #if UF_USE_LUA +bool ext::lua::enabled = true; sol::state ext::lua::state; uf::stl::string ext::lua::main = uf::io::root + "/scripts/main.lua"; uf::stl::unordered_map ext::lua::modules; @@ -162,6 +163,8 @@ namespace binds { } void ext::lua::initialize() { + if ( !ext::lua::enabled ) return; + state.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table, sol::lib::math, sol::lib::string, sol::lib::ffi, sol::lib::jit); // load modules @@ -269,6 +272,8 @@ bool ext::lua::run( const uf::stl::string& s, bool safe ) { pod::LuaScript ext::lua::script( const uf::stl::string& filename ) { pod::LuaScript script; + if ( !ext::lua::enabled ) return script; + script.file = filename; script.env = sol::environment( ext::lua::state, sol::create, ext::lua::state.globals() ); return script; diff --git a/engine/src/ext/meshopt/meshopt.cpp b/engine/src/ext/meshopt/meshopt.cpp index 44566bb2..4c069725 100644 --- a/engine/src/ext/meshopt/meshopt.cpp +++ b/engine/src/ext/meshopt/meshopt.cpp @@ -1,4 +1,4 @@ -#include +#include #if UF_USE_MESHOPTIMIZER #include #endif diff --git a/engine/src/ext/oal/oal.cpp b/engine/src/ext/oal/oal.cpp index 6cbcd802..f83a577b 100644 --- a/engine/src/ext/oal/oal.cpp +++ b/engine/src/ext/oal/oal.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace { @@ -13,37 +14,51 @@ namespace { } void ext::al::initialize() { -/* - this->m_device = alcOpenDevice(NULL); - if ( !this->m_device ) { this->checkError(__LINE__); - return false; +#if UF_USE_ALUT + ::device = alcOpenDevice(alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); + assert(::device); + + ::context = alcCreateContext(::device, NULL); + assert(::context); + alcMakeContextCurrent(::context); + + if ( alutInit(NULL, NULL) != AL_TRUE ) { + uf::audio::muted = true; + UF_EXCEPTION("AL error: " << alutGetErrorString( alutGetError() ) ); + } +#else + ::device = alcOpenDevice(NULL); + if ( !::device ) { + UF_EXCEPTION(ext::al::getError()); } ALboolean enumeration = alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"); - if (enumeration == AL_FALSE) { this->checkError(__LINE__); + if (enumeration == AL_FALSE) { // do something - std::cout << "Device enumeration not available" << std::endl; + UF_EXCEPTION("Device enumeration not available"); } - this->m_context = alcCreateContext(this->m_device, NULL); - if ( !alcMakeContextCurrent(this->m_context) ) { - this->checkError(__LINE__); - return false; - } - return this->m_initialized = true; -*/ - if ( alutInit(NULL, NULL) != AL_TRUE ) { - UF_EXCEPTION("AL error: " << alutGetErrorString( alutGetError() ) ); + ::context = alcCreateContext(::device, NULL); + if ( !alcMakeContextCurrent(::context) ) { + UF_EXCEPTION(ext::al::getError()); } +#endif } void ext::al::destroy() { -/* - this->m_device = alcGetContextsDevice(this->m_context); +#if UF_USE_ALUT + ::context = alcGetCurrentContext(); alcMakeContextCurrent(NULL); - alcDestroyContext(this->m_context); - alcCloseDevice(this->m_device); -*/ + alcDestroyContext(::context); + alcCloseDevice(::device); + + alutExit(); +#else + ::device = alcGetContextsDevice(::context); + alcMakeContextCurrent(NULL); + alcDestroyContext(::context); + alcCloseDevice(::device); +#endif } #if 0 void ext::al::listener( ALenum name, ALfloat x ) { AL_CHECK_RESULT(alListenerf( name, x )); } @@ -89,7 +104,7 @@ uf::audio::Metadata* ext::al::create( const uf::stl::string& filename, bool stre uf::audio::Metadata* pointer = (memoryPool) ? &memoryPool->alloc() : new uf::audio::Metadata; #endif uf::audio::Metadata& metadata = *pointer; - metadata.filename = filename; + metadata.filename = uf::io::resolveURI(filename); metadata.settings.streamed = streamed; metadata.settings.buffers = buffers; metadata.extension = uf::io::extension( metadata.filename ); diff --git a/engine/src/ext/opengl/commands.cpp b/engine/src/ext/opengl/commands.cpp index d59363db..1550f5c8 100644 --- a/engine/src/ext/opengl/commands.cpp +++ b/engine/src/ext/opengl/commands.cpp @@ -13,8 +13,10 @@ #define VERBOSE false #define VERBOSE_SUBMIT false +namespace { + size_t culled = 0; +} size_t ext::opengl::CommandBuffer::preallocate = 8; - void ext::opengl::CommandBuffer::initialize( Device& device ) { this->device = &device; if ( !this->mutex ) this->mutex = new std::mutex; @@ -93,16 +95,8 @@ void ext::opengl::CommandBuffer::record( const CommandBuffer& commandBuffer ) { } void ext::opengl::CommandBuffer::submit() { if ( infos.empty() ) return; - mutex->lock(); -#if UF_ENV_DREAMCAST - static GLint maxTextures = 80; -#else - static GLint maxTextures = 0; - if ( maxTextures <= 0 ) { - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextures); - } -#endif + //UF_TIMER_MULTITRACE_START("Starting command buffer submission: " << this); for ( auto& info : infos ) { CommandBuffer::Info* header = (CommandBuffer::Info*) (void*) info; switch ( header->type ) { @@ -112,23 +106,32 @@ void ext::opengl::CommandBuffer::submit() { GL_ERROR_CHECK(glClearDepth(info->depth)); GL_ERROR_CHECK(glClear(info->bits)); // GL_ERROR_CHECK(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &info->color[0])); + //UF_TIMER_MULTITRACE("Command::CLEAR"); } break; case ext::opengl::enums::Command::VIEWPORT: { InfoViewport* info = (InfoViewport*) header; GL_ERROR_CHECK(glViewport(info->corner[0], info->corner[1], info->size[0], info->size[1])); + //UF_TIMER_MULTITRACE("Command::VIEWPORT"); } break; case ext::opengl::enums::Command::VARIANT: { InfoVariant* info = (InfoVariant*) header; if ( info->lambda ) info->lambda(); + //UF_TIMER_MULTITRACE("Command::VARIANT"); } break; case ext::opengl::enums::Command::DRAW: { InfoDraw* info = (InfoDraw*) header; drawIndexed( *info ); + //UF_TIMER_MULTITRACE("Command::DRAW"); } break; default: { } break; } } + if ( ::culled ) { + // UF_MSG_DEBUG("Culled " << ::culled << " meshes."); + ::culled = 0; + } + //UF_TIMER_MULTITRACE_END("Finished command buffer submission: " << this); state = 3; mutex->unlock(); } @@ -156,28 +159,106 @@ pod::Matrix4f ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer return uniform->projection * uniform->modelView; #endif } -void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::InfoDraw& drawInfo ) { - if ( drawInfo.matrices.model && drawInfo.matrices.view && drawInfo.matrices.projection ) { - pod::Matrix4f modelView = uf::matrix::multiply( *drawInfo.matrices.view, *drawInfo.matrices.model ); - GL_ERROR_CHECK(glMatrixMode(GL_MODELVIEW)); - GL_ERROR_CHECK(glLoadMatrixf( &modelView[0] )); +namespace { + bool inside( const pod::Instance& instance, const pod::Matrix4f& mat ) { + bool visible = false; + #if 1 + pod::Vector4f corners[8] = { + pod::Vector4f{ instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.max.y, instance.bounds.min.z, 1.0f }, + pod::Vector4f{ instance.bounds.min.x, instance.bounds.max.y, instance.bounds.min.z, 1.0f }, - GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION)); - GL_ERROR_CHECK(glLoadMatrixf( (float*) drawInfo.matrices.projection )); - } else if ( drawInfo.matrices.model && drawInfo.matrices.projection ) { - GL_ERROR_CHECK(glMatrixMode(GL_MODELVIEW)); - GL_ERROR_CHECK(glLoadMatrixf( (float*) drawInfo.matrices.model )); + pod::Vector4f{ instance.bounds.min.x, instance.bounds.min.y, instance.bounds.max.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.min.y, instance.bounds.max.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f }, + pod::Vector4f{ instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f }, + }; + //#pragma unroll + for ( uint p = 0; p < 8; ++p ) { + pod::Vector4f t = uf::matrix::multiply( mat, corners[p] ); + float w = t.w * 1.25f; + if ( -w <= t.x && t.x <= w && -w <= t.y && t.y <= w && -w <= t.z && t.z <= w ) return true; + } + #else + pod::Vector4f planes[6]; { + //#pragma unroll + for ( auto i = 0; i < 3; ++i ) + //#pragma unroll + for ( auto j = 0; j < 2; ++j) { + float x = mat[4*0+3] + (j == 0 ? mat[4*0+i] : -mat[4*0+i]); + float y = mat[4*1+3] + (j == 0 ? mat[4*1+i] : -mat[4*1+i]); + float z = mat[4*2+3] + (j == 0 ? mat[4*2+i] : -mat[4*2+i]); + float w = mat[4*3+3] + (j == 0 ? mat[4*3+i] : -mat[4*3+i]); + float length = 1.0f / sqrt( x * x + y * y + z * z ); + + planes[i*2+j] = pod::Vector4f{ x * length, y * length, z * length, w * length }; + } + } + #if 0 + //#pragma unroll + for ( auto p = 0; p < 6; ++p ) { + float d = std::max(instance.bounds.min.x * planes[p].x, instance.bounds.max.x * planes[p].x) + + std::max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y); + + std::max(instance.bounds.min.z * planes[p].z, instance.bounds.max.z * planes[p].z); + if ( d > -planes[p].w ) return true; + } + #else + pod::Vector4f corners[8] = { + pod::Vector4f{ instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.max.y, instance.bounds.min.z, 1.0f }, + pod::Vector4f{ instance.bounds.min.x, instance.bounds.max.y, instance.bounds.min.z, 1.0f }, - GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION)); - GL_ERROR_CHECK(glLoadMatrixf( (float*) drawInfo.matrices.projection )); - } else if ( drawInfo.matrices.view && drawInfo.matrices.projection ) { - GL_ERROR_CHECK(glMatrixMode(GL_MODELVIEW)); - GL_ERROR_CHECK(glLoadMatrixf( (float*) drawInfo.matrices.view )); - - GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION)); - GL_ERROR_CHECK(glLoadMatrixf( (float*) drawInfo.matrices.projection )); + pod::Vector4f{ instance.bounds.min.x, instance.bounds.min.y, instance.bounds.max.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.min.y, instance.bounds.max.z, 1.0f }, + pod::Vector4f{ instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f }, + pod::Vector4f{ instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0f }, + }; + //#pragma unroll + for ( uint p = 0; p < 8; ++p ) corners[p] = uf::matrix::multiply( mat, corners[p] ); + //#pragma unroll + for ( uint p = 0; p < 6; ++p ) { + //#pragma unroll + for ( uint q = 0; q < 8; ++q ) { + if ( uf::vector::dot( corners[q], planes[p] ) > 0 ) return true; + } + return false; + } + #endif + #endif + return visible; } +} + +void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::InfoDraw& drawInfo ) { + pod::Matrix4f modelView = uf::matrix::identity(), projection = uf::matrix::identity(); + if ( drawInfo.matrices.model && drawInfo.matrices.view ) modelView = uf::matrix::multiply( *drawInfo.matrices.view, *drawInfo.matrices.model ); + else if ( drawInfo.matrices.model ) modelView = *drawInfo.matrices.model; + else if ( drawInfo.matrices.view ) modelView = *drawInfo.matrices.view; + if ( drawInfo.matrices.projection ) projection = *drawInfo.matrices.projection; + + if ( drawInfo.attributes.indirect.pointer && drawInfo.attributes.indirect.length == sizeof(pod::DrawCommand) ) { + pod::DrawCommand& drawCommand = *(pod::DrawCommand*) drawInfo.attributes.indirect.pointer; + if ( ext::opengl::settings::experimental::culling && drawInfo.attributes.instance.pointer && drawInfo.attributes.instance.length == sizeof(pod::Instance) ) { + pod::Instance& instance = *(pod::Instance*) drawInfo.attributes.instance.pointer; + pod::Matrix4f mat = (*drawInfo.matrices.projection) * (*drawInfo.matrices.view) * (*drawInfo.matrices.model); + // pod::Matrix4f mat = (*drawInfo.matrices.projection) * (*drawInfo.matrices.view) * (instance.model); + // pod::Matrix4f mat = uf::matrix::multiply( projection, modelView ); + + bool visible = inside( instance, mat ); + drawCommand.instances = visible ? 1 : 0; + if ( !visible ) ++::culled; + } + if ( drawCommand.instances == 0 ) return; + } + + GL_ERROR_CHECK(glMatrixMode(GL_MODELVIEW)); + GL_ERROR_CHECK(glLoadMatrixf( &modelView[0] )); + + GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION)); + GL_ERROR_CHECK(glLoadMatrixf( &projection[0] )); if ( drawInfo.descriptor.cullMode == GL_NONE ) { GL_ERROR_CHECK(glDisable(GL_CULL_FACE)); @@ -207,37 +288,35 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer:: } if ( drawInfo.textures.primary.image && drawInfo.attributes.uv.pointer ) { - static GLuint previous = 0; - if ( previous != drawInfo.textures.primary.image ) { - previous = drawInfo.textures.primary.image; - GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE0)); - GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE0)); - GL_ERROR_CHECK(glEnable(drawInfo.textures.primary.viewType)); - GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image)); - GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); - } + // static GLuint previous = 0; + // if ( previous != drawInfo.textures.primary.image ) previous = drawInfo.textures.primary.image; + + GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE0)); + GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE0)); + GL_ERROR_CHECK(glEnable(drawInfo.textures.primary.viewType)); + GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image)); + GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, drawInfo.attributes.uv.pointer)); } if ( drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer ) { - static GLuint previous = 0; - if ( previous != drawInfo.textures.secondary.image ) { - previous = drawInfo.textures.secondary.image; - GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE1)); - GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE1)); - GL_ERROR_CHECK(glEnable(drawInfo.textures.secondary.viewType)); - GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); - GL_ERROR_CHECK(glBindTexture(drawInfo.textures.secondary.viewType, drawInfo.textures.secondary.image)); - GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)); - GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, drawInfo.attributes.st.pointer)); - } + // static GLuint previous = 0; + // if ( previous != drawInfo.textures.secondary.image ) previous = drawInfo.textures.secondary.image; + + GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE1)); + GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE1)); + GL_ERROR_CHECK(glEnable(drawInfo.textures.secondary.viewType)); + GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + GL_ERROR_CHECK(glBindTexture(drawInfo.textures.secondary.viewType, drawInfo.textures.secondary.image)); + GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)); + GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, drawInfo.attributes.st.pointer)); #if UF_ENV_DREAMCAST GL_ERROR_CHECK(glDisable(GL_BLEND)); #endif } if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glNormalPointer(GL_FLOAT, drawInfo.attributes.normal.stride, drawInfo.attributes.normal.pointer)); - if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glColorPointer(3, GL_FLOAT, drawInfo.attributes.color.stride, drawInfo.attributes.color.pointer)); + if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glColorPointer(4, GL_UNSIGNED_BYTE, drawInfo.attributes.color.stride, drawInfo.attributes.color.pointer)); GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, drawInfo.attributes.position.stride, drawInfo.attributes.position.pointer)); GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.attributes.index.length, indicesType, drawInfo.attributes.index.pointer)); diff --git a/engine/src/ext/opengl/graphic.cpp b/engine/src/ext/opengl/graphic.cpp index fc48e6b0..e2838938 100644 --- a/engine/src/ext/opengl/graphic.cpp +++ b/engine/src/ext/opengl/graphic.cpp @@ -404,10 +404,16 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe if ( attribute.descriptor.name == "position" ) drawCommandInfo.attributes.position = attribute; else if ( attribute.descriptor.name == "uv" ) drawCommandInfo.attributes.uv = attribute; else if ( attribute.descriptor.name == "st" ) drawCommandInfo.attributes.st = attribute; - else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute; - else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute; + // else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute; + // else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute; } + drawCommandInfo.attributes.instance.pointer = &instance; + drawCommandInfo.attributes.instance.length = sizeof(instance); + + drawCommandInfo.attributes.indirect.pointer = &drawCommand; + drawCommandInfo.attributes.indirect.length = sizeof(drawCommand); + drawCommandInfo.matrices.model = &instance.model; drawCommandInfo.matrices.view = &viewports->matrices[0].view; drawCommandInfo.matrices.projection = &viewports->matrices[0].projection; @@ -528,275 +534,4 @@ ext::opengl::GraphicDescriptor::hash_t ext::opengl::GraphicDescriptor::hash() co return hash; } - -ext::json::Value ext::opengl::definitionToJson(/*const*/ ext::json::Value& definition ) { - ext::json::Value member; - // is object - if ( !ext::json::isNull(definition["members"]) ) { - ext::json::forEach(definition["members"], [&](/*const*/ ext::json::Value& value){ - uf::stl::string key = uf::string::split(value["name"].as(), " ").back(); - member[key] = ext::opengl::definitionToJson(value); - }); - // is primitive - } else if ( !ext::json::isNull(definition["value"]) ) { - // is array of structs - if ( definition["struct"].as() ) { - ext::json::forEach(definition["value"], [&](/*const*/ ext::json::Value& value){ - ext::json::Value parsed; - parsed["name"] = definition["name"]; - parsed["size"] = definition["size"]; - parsed["struct"] = definition["struct"]; - parsed["members"] = value; - parsed = ext::opengl::definitionToJson(parsed); - member.emplace_back(parsed); - }); - } else { - member = definition["value"]; - } - } - return member; -} -ext::opengl::userdata_t ext::opengl::jsonToUserdata( const ext::json::Value& payload, const ext::json::Value& definition ) { - size_t bufferLen = definition["size"].as(); - - ext::opengl::userdata_t userdata; - userdata.create(bufferLen); - - uint8_t* byteBuffer = (uint8_t*) (void*) userdata; - uint8_t* byteBufferStart = byteBuffer; - uint8_t* byteBufferEnd = byteBuffer + bufferLen; - -#if UF_JSON_NLOHMANN_ORDERED - // JSON is ordered, we can just push directly -#define UF_SHADER_TRACK_NAMES 0 -#if UF_SHADER_TRACK_NAMES - uf::stl::vector variableName; -#endif - std::function parse = [&]( const ext::json::Value& value ){ - // is array or object - #if UF_SHADER_TRACK_NAMES - if ( ext::json::isObject(value) ) { - ext::json::forEach(value, [&]( const uf::stl::string& name, const ext::json::Value& member ){ - #if UF_SHADER_TRACK_NAMES - variableName.emplace_back(name); - #endif - parse(member); - }); - #if UF_SHADER_TRACK_NAMES - if ( !variableName.empty() ) variableName.pop_back(); - #endif - return; - } - if ( ext::json::isArray(value) ) { - ext::json::forEach(value, [&]( size_t i, const ext::json::Value& element ){ - variableName.emplace_back("["+std::to_string(i)+"]"); - parse(element); - }); - #if UF_SHADER_TRACK_NAMES - if ( !variableName.empty() ) variableName.pop_back(); - #endif - return; - } - #else - if ( ext::json::isArray(value) || ext::json::isObject(value) ) { - ext::json::forEach(value, parse); - return; - } - #endif - #if UF_SHADER_TRACK_NAMES - uf::stl::string path = uf::string::join(variableName, "."); - path = uf::string::replace( path, ".[", "[" ); - GL_VALIDATION_MESSAGE("[" << (byteBuffer - byteBufferStart) << " / "<< (byteBufferEnd - byteBuffer) <<"]\tInserting: " << path << " = " << value.dump()); - #endif - // is strictly an int - if ( value.is(true) ) { - size_t size = sizeof(int32_t); - auto get = value.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - // is strictly an unsigned int - } else if ( value.is(true) ) { - size_t size = sizeof(uint32_t); - auto get = value.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - // is strictly a float - } else if ( value.is(true) ) { - size_t size = sizeof(float); - auto get = value.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } - #if UF_SHADER_TRACK_NAMES - if ( !variableName.empty() ) variableName.pop_back(); - #endif - }; -#if UF_SHADER_TRACK_NAMES - GL_VALIDATION_MESSAGE("Updating " << name << " in " << filename); - GL_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer)); -#endif - parse(payload); -#if UF_SHADER_TRACK_NAMES - GL_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer)); -#endif - -#else - auto pushValue = [&]( const uf::stl::string& primitive, const ext::json::Value& input ){ - if ( primitive == "bool" ) { - size_t size = sizeof(bool); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - auto get = input.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "int8_t" ) { - size_t size = sizeof(int8_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - - // auto get = input.as(); - // memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "uint8_t" ) { - size_t size = sizeof(uint8_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - // auto get = input.as(); - // memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "int16_t" ) { - size_t size = sizeof(int16_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - // auto get = input.as(); - // memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "uint16_t" ) { - size_t size = sizeof(uint16_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - // auto get = input.as(); - // memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "int32_t" ) { - size_t size = sizeof(int32_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - auto get = input.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "uint32_t" ) { - size_t size = sizeof(uint32_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - auto get = input.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "int64_t" ) { - size_t size = sizeof(int64_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - auto get = input.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "uint64_t" ) { - size_t size = sizeof(uint64_t); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - auto get = input.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "half" ) { - size_t size = sizeof(float); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - // auto get = input.as(); - // memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "float" ) { - size_t size = sizeof(float); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - auto get = input.as(); - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } else if ( primitive == "double" ) { - auto get = input.as(); - size_t size = sizeof(double); // v["size"].as(); - if ( byteBufferEnd < byteBuffer + size ) return false; // overflow - memcpy( byteBuffer, &get, size ); - byteBuffer += size; - } - return true; - }; - #define UF_SHADER_TRACK_NAMES 0 - #if UF_SHADER_TRACK_NAMES - bool SKIP_ADD = false; - uf::stl::vector variableName; - #endif - std::function parseDefinition = [&](const ext::json::Value& input, const ext::json::Value& definition ){ - #if UF_SHADER_TRACK_NAMES - if ( SKIP_ADD ) { - SKIP_ADD = false; - } else { - auto split = uf::string::split(definition["name"].as(), " "); - uf::stl::string type = split.front(); - uf::stl::string name = split.back(); - variableName.emplace_back(name); - } - #endif - // is object - if ( !ext::json::isNull(definition["members"]) ) { - ext::json::forEach(definition["members"], [&](const ext::json::Value& member){ - uf::stl::string key = uf::string::split(member["name"].as(), " ").back(); - parseDefinition(input[key], member); - }); - // is array or primitive - } else if ( !ext::json::isNull(definition["value"]) ) { - // is object - auto split = uf::string::split(definition["name"].as(), " "); - uf::stl::string type = split.front(); - uf::stl::string name = split.back(); - std::regex regex("^(?:(.+?)\\<)?(.+?)(?:\\>)?(?:\\[(\\d+)\\])?$"); - std::smatch match; - if ( !std::regex_search( type, match, regex ) ) { - std::cout << "Ill formatted typename: " << definition["name"].as() << std::endl; - return; - } - uf::stl::string vectorMatrix = match[1].str(); - uf::stl::string primitive = match[2].str(); - uf::stl::string arraySize = match[3].str(); - if ( ext::json::isObject(input) ) { - ext::json::Value cloned; - cloned["name"] = definition["name"]; - cloned["size"] = definition["size"].as() / definition["value"].size(); - cloned["members"] = definition["value"][0]; - parseDefinition( input, cloned ); - } - // is array - else if ( ext::json::isArray(input) ) { - ext::json::forEach( input, [&]( size_t i, const ext::json::Value& value){ - #if UF_SHADER_TRACK_NAMES - variableName.emplace_back("["+std::to_string(i)+"]"); - SKIP_ADD = true; - #endif - parseDefinition(input[i], definition); - }); - } - // is primitive - else { - #if UF_SHADER_TRACK_NAMES - uf::stl::string path = uf::string::join(variableName, "."); - path = uf::string::replace( path, ".[", "[" ); - GL_VALIDATION_MESSAGE("[" << (byteBuffer - byteBufferStart) << " / "<< (byteBufferEnd - byteBuffer) <<"]\tInserting: " << path << " = (" << primitive << ") " << input.dump()); - #endif - pushValue( primitive, input ); - } - } - #if UF_SHADER_TRACK_NAMES - if ( !variableName.empty() ) variableName.pop_back(); - #endif - }; - //auto& definitions = metadata["definitions"]["uniforms"][name]; -#if UF_SHADER_TRACK_NAMES - GL_VALIDATION_MESSAGE("Updating " << name << " in " << filename); - GL_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer)); -#endif - parseDefinition(payload, definition); -#if UF_SHADER_TRACK_NAMES - GL_VALIDATION_MESSAGE("Iterator: " << (void*) byteBuffer << "\t" << (void*) byteBufferEnd << "\t" << (byteBufferEnd - byteBuffer)); -#endif -#endif - return userdata; -} - #endif \ No newline at end of file diff --git a/engine/src/ext/opengl/opengl.cpp b/engine/src/ext/opengl/opengl.cpp index fc7a3f3a..456f1d67 100644 --- a/engine/src/ext/opengl/opengl.cpp +++ b/engine/src/ext/opengl/opengl.cpp @@ -169,6 +169,15 @@ void UF_API ext::opengl::initialize() { } if ( !jobs.empty() ) uf::thread::batchWorkers( jobs ); // bind shaders +/* + { + ext::opengl::Shader::bind( uf::io::root + "shaders/graph/cull.comp.spv", []( const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic ) { + uf::Mesh::Attribute position = {}; + uf::Mesh::Attribute index = {}; + uf::Mesh::Attribute indirect = {}; + }); + } +*/ #if 0 { ext::opengl::Shader::bind( uf::io::root + "shaders/graph/instanced.vert.spv", [](const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic, void* userdata) { diff --git a/engine/src/ext/opengl/shader.cpp b/engine/src/ext/opengl/shader.cpp index 6a31047e..e8b449ec 100644 --- a/engine/src/ext/opengl/shader.cpp +++ b/engine/src/ext/opengl/shader.cpp @@ -193,6 +193,7 @@ const ext::opengl::Buffer& ext::opengl::Shader::getStorageBuffer( const uf::stl: UF_EXCEPTION("buffer not found: " << name); } // JSON shit +#if 0 ext::opengl::userdata_t ext::opengl::Shader::getUniformUserdata( const uf::stl::string& name, const ext::json::Value& payload ) { if ( !hasUniform(name) ) return false; return jsonToUserdata(payload, metadata.json["definitions"]["uniforms"][name]); @@ -215,4 +216,5 @@ ext::opengl::userdata_t ext::opengl::Shader::getStorageUserdata( const uf::stl:: if ( !hasStorage(name) ) return false; return jsonToUserdata(payload, metadata.json["definitions"]["storage"][name]); } +#endif #endif \ No newline at end of file diff --git a/engine/src/ext/vorbis/vorbis.cpp b/engine/src/ext/vorbis/vorbis.cpp index 74ed724d..d052b23b 100644 --- a/engine/src/ext/vorbis/vorbis.cpp +++ b/engine/src/ext/vorbis/vorbis.cpp @@ -252,7 +252,8 @@ void ext::vorbis::update( uf::Audio::Metadata& metadata ) { if ( metadata.settings.loopMode == 1 ) metadata.al.source.set( AL_LOOPING, AL_FALSE ); ALint state; - metadata.al.source.get( AL_SOURCE_STATE, &state ); +// metadata.al.source.get( AL_SOURCE_STATE, &state ); + metadata.al.source.get( AL_SOURCE_STATE, state ); if ( state != AL_PLAYING ) { if ( !metadata.settings.loop && metadata.stream.consumed >= metadata.info.size ) { // UF_MSG_INFO("Vorbis stream finished: " << metadata.filename); @@ -264,7 +265,8 @@ void ext::vorbis::update( uf::Audio::Metadata& metadata ) { } ALint processed = 0; - metadata.al.source.get(AL_BUFFERS_PROCESSED, &processed); +// metadata.al.source.get(AL_BUFFERS_PROCESSED, &processed); + metadata.al.source.get(AL_BUFFERS_PROCESSED, processed); // no work need to be done if ( processed <= 0 ) return; diff --git a/engine/src/ext/vulkan/shader.cpp b/engine/src/ext/vulkan/shader.cpp index 9256d945..9c7a4b03 100644 --- a/engine/src/ext/vulkan/shader.cpp +++ b/engine/src/ext/vulkan/shader.cpp @@ -15,6 +15,8 @@ #define VK_DEBUG_VALIDATION_MESSAGE(x)\ // VK_VALIDATION_MESSAGE(x); +#define UF_SHADER_PARSE_AS_JSON 0 +#if UF_SHADER_PARSE_AS_JSON ext::json::Value ext::vulkan::definitionToJson(/*const*/ ext::json::Value& definition ) { ext::json::Value member; // is object @@ -284,7 +286,7 @@ ext::vulkan::userdata_t ext::vulkan::jsonToUserdata( const ext::json::Value& pay #endif return userdata; } - +#endif void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl::string& filename, VkShaderStageFlagBits stage ) { this->device = &device; ext::vulkan::Buffers::initialize( device ); @@ -327,7 +329,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl { spirv_cross::Compiler comp( (uint32_t*) &spirv[0], spirv.size() / 4 ); spirv_cross::ShaderResources res = comp.get_shader_resources(); - + #if UF_SHADER_PARSE_AS_JSON std::function parseMembers = [&]( spirv_cross::TypeID type_id ) { auto parseMember = [&]( auto type_id ){ uf::Serializer payload; @@ -434,7 +436,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl } return payload; }; - + #endif auto parseResource = [&]( const spirv_cross::Resource& resource, VkDescriptorType descriptorType, size_t index ) { const auto& type = comp.get_type(resource.type_id); const auto& base_type = comp.get_type(resource.base_type_id); @@ -461,11 +463,13 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl case spv::Dim::DimSubpassData: tname = "SubpassData"; break; } uf::stl::string key = std::to_string(binding); + #if UF_SHADER_PARSE_AS_JSON metadata.json["definitions"]["textures"][key]["name"] = name; metadata.json["definitions"]["textures"][key]["index"] = index; metadata.json["definitions"]["textures"][key]["binding"] = binding; metadata.json["definitions"]["textures"][key]["size"] = arraySize; metadata.json["definitions"]["textures"][key]["type"] = tname; + #endif metadata.definitions.textures[binding] = Shader::Metadata::Definition::Texture{ name, @@ -493,6 +497,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl // uniform.create( bufferSize ); } // generate definition to JSON + #if UF_SHADER_PARSE_AS_JSON { metadata.json["definitions"]["uniforms"][name]["name"] = name; metadata.json["definitions"]["uniforms"][name]["index"] = index; @@ -500,6 +505,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl metadata.json["definitions"]["uniforms"][name]["size"] = bufferSize; metadata.json["definitions"]["uniforms"][name]["members"] = parseMembers(resource.type_id); } + #endif // generate definition to unordered_map metadata.definitions.uniforms[name] = Shader::Metadata::Definition::Uniform{ name, @@ -510,12 +516,14 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl } break; case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: { // generate definition to JSON + #if UF_SHADER_PARSE_AS_JSON { metadata.json["definitions"]["storage"][name]["name"] = name; metadata.json["definitions"]["storage"][name]["index"] = index; metadata.json["definitions"]["storage"][name]["binding"] = binding; metadata.json["definitions"]["storage"][name]["members"] = parseMembers(resource.type_id); } + #endif metadata.definitions.storage[name] = Shader::Metadata::Definition::Storage{ name, index, @@ -524,10 +532,10 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl } break; } descriptorSetLayoutBindings.push_back( ext::vulkan::initializers::descriptorSetLayoutBinding( descriptorType, stage, binding, arraySize ) ); - }; - + }; //for ( const auto& resource : res.key ) { + #define LOOP_RESOURCES( key, type ) for ( size_t i = 0; i < res.key.size(); ++i ) {\ const auto& resource = res.key[i];\ VK_DEBUG_VALIDATION_MESSAGE("["<() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename ); metadata.json["specializationConstants"].emplace_back(member); + VK_DEBUG_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename ); + #endif memcpy( &s[offset], &buffer, size ); offset += size; @@ -869,7 +896,7 @@ bool ext::vulkan::Shader::updateStorage( const uf::stl::string& name, const void return true; } // JSON shit -/* +#if 0 && UF_SHADER_PARSE_AS_JSON uf::Serializer ext::vulkan::Shader::getUniformJson( const uf::stl::string& name, bool cache ) { if ( !hasUniform(name) ) return ext::json::null(); if ( cache && !ext::json::isNull(metadata.json["uniforms"][name]) ) return metadata.json["uniforms"][name]; @@ -897,5 +924,5 @@ ext::vulkan::userdata_t ext::vulkan::Shader::getStorageUserdata( const uf::stl:: if ( !hasStorage(name) ) return false; return jsonToUserdata(payload, metadata.json["definitions"]["storage"][name]); } -*/ +#endif #endif \ No newline at end of file diff --git a/engine/src/ext/xatlas/xatlas.cpp b/engine/src/ext/xatlas/xatlas.cpp index f2dc7ab1..b16ab273 100644 --- a/engine/src/ext/xatlas/xatlas.cpp +++ b/engine/src/ext/xatlas/xatlas.cpp @@ -2,6 +2,7 @@ #if UF_USE_XATLAS #include #endif +#if 0 pod::Vector2ui UF_API ext::xatlas::unwrap( uf::stl::vector& vertices, uf::stl::vector& indices ) { #if UF_USE_XATLAS uf::stl::vector source = std::move(vertices); @@ -41,6 +42,7 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( uf::stl::vector uf::audio::volumes; +#else + float uf::audio::volumes::bgm = 1.0f; + float uf::audio::volumes::sfx = 1.0f; + float uf::audio::volumes::voice = 1.0f; +#endif + bool uf::Audio::initialized() const { #if UF_USE_OPENAL return this->m_metadata && this->m_metadata->al.source.getIndex(); @@ -116,7 +124,7 @@ void uf::Audio::setTime( float v ) { void uf::Audio::setPosition( const pod::Vector3f& v ) { #if UF_USE_OPENAL if ( !this->m_metadata ) return; - this->m_metadata->al.source.set( AL_POSITION, &v[0] ); + this->m_metadata->al.source.set( AL_POSITION, v[0], v[1], v[2] ); #endif } void uf::Audio::setOrientation( const pod::Quaternion<>& v ) { diff --git a/engine/src/utils/math/physics.cpp b/engine/src/utils/math/physics.cpp index 9b2c51a5..1d74c9ea 100644 --- a/engine/src/utils/math/physics.cpp +++ b/engine/src/utils/math/physics.cpp @@ -1,16 +1,16 @@ #include uf::Timer<> uf::physics::time::timer; -double uf::physics::time::current; -double uf::physics::time::previous; -double uf::physics::time::delta; -double uf::physics::time::clamp; +uf::physics::num_t uf::physics::time::current; +uf::physics::num_t uf::physics::time::previous; +uf::physics::num_t uf::physics::time::delta; +uf::physics::num_t uf::physics::time::clamp; #include void UF_API uf::physics::tick() { uf::physics::time::previous = uf::physics::time::current; - uf::physics::time::current = uf::physics::time::timer.elapsed().asDouble(); + uf::physics::time::current = uf::physics::time::timer.elapsed(); uf::physics::time::delta = uf::physics::time::current - uf::physics::time::previous; if ( uf::physics::time::delta > uf::physics::time::clamp ) { uf::physics::time::delta = uf::physics::time::clamp; diff --git a/engine/src/utils/mesh/mesh.cpp b/engine/src/utils/mesh/mesh.cpp index c46eaaba..b68a9f11 100644 --- a/engine/src/utils/mesh/mesh.cpp +++ b/engine/src/utils/mesh/mesh.cpp @@ -293,22 +293,36 @@ uf::Mesh::Attribute uf::Mesh::_remapAttribute( const uf::Mesh::Input& input, con return res; } void uf::Mesh::_insertVs( uf::Mesh::Input& input, const uf::Mesh& mesh, const uf::Mesh::Input& srcInput ) { - if ( !_hasV( input, srcInput ) ) return; _reserveVs( input, input.count += srcInput.count ); // both meshes are interleaved, just copy directly if ( isInterleaved(input.interleaved) && isInterleaved(srcInput.interleaved) ) { + if ( !_hasV( input, srcInput ) ) return; auto& src = mesh.buffers[srcInput.interleaved]; auto& dst = buffers[input.interleaved]; dst.insert( dst.end(), src.begin(), src.end() ); // both meshes are de-interleaved, just copy directly } else if ( !isInterleaved(input.interleaved) && !isInterleaved(srcInput.interleaved) ) { - for ( auto i = 0; i < input.attributes.size(); ++i ) { - auto& srcAttribute = srcInput.attributes[i]; - auto& dstAttribute = input.attributes[i]; - auto& src = mesh.buffers[srcAttribute.buffer]; - auto& dst = buffers[dstAttribute.buffer]; - dst.insert( dst.end(), src.begin(), src.end() ); + if ( _hasV( input, srcInput ) ) { + for ( auto i = 0; i < input.attributes.size(); ++i ) { + auto& srcAttribute = srcInput.attributes[i]; + auto& dstAttribute = input.attributes[i]; + auto& src = mesh.buffers[srcAttribute.buffer]; + auto& dst = buffers[dstAttribute.buffer]; + dst.insert( dst.end(), src.begin(), src.end() ); + } + } else { + for ( auto& dstAttribute : input.attributes ) { + for ( auto& srcAttribute : srcInput.attributes ) { + if ( srcAttribute.descriptor != dstAttribute.descriptor ) continue; + + auto& src = mesh.buffers[srcAttribute.buffer]; + auto& dst = buffers[dstAttribute.buffer]; + dst.insert( dst.end(), src.begin(), src.end() ); + + break; + } + } } // not easy to convert, will implement later } else { diff --git a/ext/behaviors/baking/behavior.cpp b/ext/behaviors/baking/behavior.cpp index 7f4a59db..14043d04 100644 --- a/ext/behaviors/baking/behavior.cpp +++ b/ext/behaviors/baking/behavior.cpp @@ -35,15 +35,16 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { if ( metadataJson["baking"]["resolution"].is() ) metadata.size = { metadataJson["baking"]["resolution"].as(), metadataJson["baking"]["resolution"].as() }; - metadata.max.lights = metadataJson["baking"]["lights"].as(metadata.max.lights); metadata.max.shadows = metadataJson["baking"]["shadows"].as(metadata.max.shadows); metadata.cull = metadataJson["baking"]["cull"].as(); - metadata.previous.max = sceneMetadata.shadow.max; + metadata.previous.lights = sceneMetadata.light.max; + metadata.previous.shadows = sceneMetadata.shadow.max; metadata.previous.update = sceneMetadata.shadow.update; - sceneMetadata.shadow.max = 1024; - sceneMetadata.shadow.update = 1024; + sceneMetadata.light.max = metadata.max.shadows; + sceneMetadata.shadow.max = metadata.max.shadows; + sceneMetadata.shadow.update = metadata.max.shadows; UF_MSG_DEBUG("Temporarily altering shadow limits..."); auto& renderMode = this->getComponent(); @@ -172,7 +173,8 @@ SAVE: { auto& scene = uf::scene::getCurrentScene(); auto& sceneMetadata = scene.getComponent(); - sceneMetadata.shadow.max = metadata.previous.max; + sceneMetadata.light.max = metadata.previous.lights; + sceneMetadata.shadow.max = metadata.previous.shadows; sceneMetadata.shadow.update = metadata.previous.update; UF_MSG_DEBUG("Reverted shadow limits"); diff --git a/ext/behaviors/baking/behavior.h b/ext/behaviors/baking/behavior.h index 6000f55a..a0caa278 100644 --- a/ext/behaviors/baking/behavior.h +++ b/ext/behaviors/baking/behavior.h @@ -31,7 +31,8 @@ namespace ext { size_t shadows = 1024; } max; struct { - size_t max = 0; + size_t lights = 0; + size_t shadows = 0; size_t update = 0; } previous; struct { diff --git a/ext/behaviors/player/behavior.cpp b/ext/behaviors/player/behavior.cpp index 7e81afbf..0143957e 100644 --- a/ext/behaviors/player/behavior.cpp +++ b/ext/behaviors/player/behavior.cpp @@ -75,18 +75,14 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) { pod::Vector2 relta = { (float) sensitivity * payload.mouse.delta.x / payload.window.size.x, (float) sensitivity * payload.mouse.delta.y / payload.window.size.y }; if ( (payload.mouse.delta.x == 0 && payload.mouse.delta.y == 0) || !metadata.system.control ) return; - bool updateCamera = false; if ( payload.mouse.delta.x != 0 ) { if ( metadata.camera.invert.x ) relta.x *= -1; metadata.camera.limit.current.x += relta.x; if ( metadata.camera.limit.current.x != metadata.camera.limit.current.x || ( metadata.camera.limit.current.x < metadata.camera.limit.max.x && metadata.camera.limit.current.x > metadata.camera.limit.min.x ) ) { - if ( collider.body && !collider.shared ) { - #if UF_USE_BULLET - ext::bullet::applyRotation( collider, transform.up, relta.x ); - #endif - } else { - uf::transform::rotate( transform, transform.up, relta.x ), updateCamera = true; - } + #if UF_USE_BULLET + if ( collider.body && !collider.shared ) ext::bullet::applyRotation( collider, transform.up, relta.x ); else + #endif + uf::transform::rotate( transform, transform.up, relta.x ); } else metadata.camera.limit.current.x -= relta.x; } if ( payload.mouse.delta.y != 0 ) { @@ -98,10 +94,9 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) { // } else { uf::transform::rotate( cameraTransform, cameraTransform.right, relta.y ); // } - updateCamera = true; } else metadata.camera.limit.current.y -= relta.y; } - if ( updateCamera ) camera.update(true); + camera.update(true); }); #if UF_USE_DISCORD @@ -190,7 +185,6 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { } struct { - bool updateCamera = true; bool deltaCrouch = false; bool walking = false; bool floored = true; @@ -208,30 +202,37 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { stats.menu = metadata.system.menu; stats.impulse = metadata.system.physics.impulse; stats.noclipped = metadata.system.noclipped; - stats.floored = fabs(physics.linear.velocity.y) < 0.01f || stats.noclipped; + stats.floored = stats.noclipped; +#if UF_USE_BULLET + auto& collider = this->getComponent(); + if ( !stats.floored && collider.body && ext::bullet::rayCast( transform.position, transform.position - pod::Vector3f{0,1,0} ) >= 0.0f ) stats.floored = true; else +#endif + stats.floored |= fabs(physics.linear.velocity.y) < 0.01f; + struct { float move = 4; float walk = 1; float run = 8; - float rotate = uf::physics::time::delta; - float limitSquared = 4*4; + float rotate = 1; + float friction = 0.8f; } speed; { - speed.rotate *= metadata.system.physics.rotate; + speed.rotate = metadata.system.physics.rotate * uf::physics::time::delta; speed.move = metadata.system.physics.move; - speed.run = metadata.system.physics.run / speed.move; - speed.walk = metadata.system.physics.walk / speed.move; + speed.run = metadata.system.physics.run; + speed.walk = metadata.system.physics.walk; if ( stats.noclipped ) { speed.move *= 4.0; speed.run *= 2.0; } + if ( !stats.floored || stats.noclipped ) speed.friction = 1; + if ( stats.noclipped ) physics.linear.velocity = {}; } if ( !metadata.system.physics.collision ) { stats.impulse = true; } - if ( keys.running ) speed.move *= speed.run; - else if ( keys.walk ) speed.move *= speed.walk; - speed.limitSquared = speed.move * speed.move; + if ( keys.running ) speed.move = speed.run; + else if ( keys.walk ) speed.move = speed.walk; uf::Object* menu = (uf::Object*) scene.globalFindByName("Gui: Menu"); if ( !menu ) stats.menu = ""; @@ -250,44 +251,45 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { metadata.system.control = false; } metadata.system.menu = stats.menu; - auto& collider = this->getComponent(); - if ( metadata.system.control ) { - { - TIMER(0.25, keys.vee && ) { - bool state = !stats.noclipped; - metadata.system.noclipped = state; - - UF_MSG_DEBUG( (state ? "En" : "Dis") << "abled noclip: " << uf::vector::toString(transform.position)); - if ( state ) { - #if UF_USE_BULLET - if ( collider.body ) { - collider.body->setGravity(btVector3(0,0.0,0)); - collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); - collider.body->setActivationState(DISABLE_SIMULATION); - } - #endif - } else { - #if UF_USE_BULLET - if ( collider.body ) { - collider.body->setGravity(btVector3(0,-9.81,0)); - collider.body->setCollisionFlags(collider.body->getCollisionFlags() & ~btCollisionObject::CF_NO_CONTACT_RESPONSE); - collider.body->setActivationState(DISABLE_DEACTIVATION); - } - #endif - } - stats.noclipped = state; - } - } - if ( stats.floored ) { + if ( metadata.system.control ) { + // noclip handler + TIMER(0.25, keys.vee && ) { + bool state = !stats.noclipped; + metadata.system.noclipped = state; + + UF_MSG_DEBUG( (state ? "En" : "Dis") << "abled noclip: " << uf::vector::toString(transform.position)); + if ( state ) { + #if UF_USE_BULLET + if ( collider.body ) { + collider.body->setGravity(btVector3(0,0.0,0)); + collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); + collider.body->setActivationState(DISABLE_SIMULATION); + } + #endif + } else { + #if UF_USE_BULLET + if ( collider.body ) { + collider.body->setGravity(btVector3(0,-9.81,0)); + collider.body->setCollisionFlags(collider.body->getCollisionFlags() & ~btCollisionObject::CF_NO_CONTACT_RESPONSE); + collider.body->setActivationState(DISABLE_DEACTIVATION); + } + #endif + } + stats.noclipped = state; + } + // movement handler + { pod::Transform<> translator = transform; #if UF_USE_OPENVR + // use the orientation of our controller to determine our target if ( ext::openvr::context ) { bool useController = true; - translator.orientation = uf::quaternion::multiply( transform.orientation * pod::Vector4f{1,1,1,1}, useController ? (ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right ) * pod::Vector4f{1,1,1,1}) : ext::openvr::hmdQuaternion() ); + translator.orientation = uf::quaternion::multiply( transform.orientation, useController ? ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right ) : ext::openvr::hmdQuaternion() ); translator = uf::transform::reorient( translator ); + // flatten if not noclipped if ( !stats.noclipped ) { translator.forward *= { 1, 0, 1 }; translator.right *= { 1, 0, 1 }; @@ -297,155 +299,66 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { translator.right = uf::vector::normalize( translator.right ); } else #endif + // un-flatted if noclipped if ( stats.noclipped ){ auto& cameraTransform = camera.getTransform(); - // translator = uf::transform::flatten( cameraTransform ); translator.forward.y += cameraTransform.forward.y; + translator.forward = uf::vector::normalize( translator.forward ); } - pod::Vector3f queued = {}; - if ( keys.forward || keys.backwards ) { - float polarity = keys.forward ? 1 : -1; - float mag = uf::vector::magnitude(physics.linear.velocity); // * pod::Vector3{1, 0, 1}); - if ( mag < speed.limitSquared ) { - mag = uf::vector::magnitude(physics.linear.velocity + translator.forward * speed.move * polarity); - } else mag = speed.limitSquared; - pod::Vector3 correction = translator.forward * ::sqrt(mag) * polarity; - - if ( collider.body && !collider.shared ) { - queued += correction; - } else { - if ( stats.impulse && stats.noclipped ) { - physics.linear.velocity.x = correction.x; - physics.linear.velocity.z = correction.z; - - if ( stats.noclipped ) physics.linear.velocity.y = correction.y; - } else { - correction *= uf::physics::time::delta; - transform.position.x += correction.x; - transform.position.z += correction.z; - - if ( stats.noclipped ) transform.position.y += correction.y; - } - } - stats.updateCamera = (stats.walking = true); - } - if ( keys.left || keys.right ) { - float polarity = keys.right ? 1 : -1; - float mag = uf::vector::magnitude(physics.linear.velocity); // * pod::Vector3{1, 0, 1}); - if ( mag < speed.limitSquared ) { - mag = uf::vector::magnitude(physics.linear.velocity + translator.right * speed.move * polarity); - } else mag = speed.limitSquared; - pod::Vector3 correction = translator.right * ::sqrt(mag) * polarity; - - if ( collider.body && !collider.shared ) { - queued += correction; - } else { - if ( stats.impulse && stats.noclipped ) { - physics.linear.velocity.x = correction.x; - physics.linear.velocity.z = correction.z; - } else { - correction *= uf::physics::time::delta; - transform.position.x += correction.x; - transform.position.z += correction.z; - } - } - stats.updateCamera = (stats.walking = true); - } - if ( keys.left || keys.right || keys.forward || keys.backwards ) { - if ( collider.body && !collider.shared ) { - physics.linear.velocity.x = queued.x; - physics.linear.velocity.z = queued.z; - - if ( stats.noclipped ) physics.linear.velocity.y = queued.y; - #if UF_USE_BULLET - ext::bullet::move( collider, physics.linear.velocity ); - #endif - } - } - if ( !keys.forward && !keys.backwards && !keys.left && !keys.right ) { - if ( collider.body && !collider.shared ) { - physics.linear.velocity.x = 0; - physics.linear.velocity.z = 0; - - if ( stats.noclipped ) physics.linear.velocity.y = 0; - #if UF_USE_BULLET - ext::bullet::move( collider, physics.linear.velocity ); - #endif - } - } - if ( keys.jump ) { - pod::Vector3f yump = metadata.system.physics.jump; - if ( collider.body && !collider.shared ) { - if ( fabs(yump.x) > 0.001f ) physics.linear.velocity.x = yump.x; - if ( fabs(yump.y) > 0.001f ) physics.linear.velocity.y = yump.y; - if ( fabs(yump.z) > 0.001f ) physics.linear.velocity.z = yump.z; - #if UF_USE_BULLET - ext::bullet::move( collider, physics.linear.velocity ); - #endif - } else { - transform.position += uf::vector::multiply(yump, uf::physics::time::delta); - } - } - } - if ( keys.lookLeft ) { - if ( collider.body && !collider.shared ) { - #if UF_USE_BULLET - ext::bullet::applyRotation( collider, transform.up, -speed.rotate ); - #endif - } else { - uf::transform::rotate( transform, transform.up, -speed.rotate ); - } - stats.updateCamera = true; - } - if ( keys.lookRight ) { - if ( collider.body && !collider.shared ) { - #if UF_USE_BULLET - ext::bullet::applyRotation( collider, transform.up, speed.rotate ); - #endif - } else { - uf::transform::rotate( transform, transform.up, speed.rotate ); - } - stats.updateCamera = true; - } - if ( keys.crouch ) { - pod::Vector3f yump = metadata.system.physics.jump; - if ( stats.noclipped ) { - if ( collider.body && !collider.shared ) { - if ( fabs(yump.x) > 0.001f ) physics.linear.velocity.x = -yump.x; - if ( fabs(yump.y) > 0.001f ) physics.linear.velocity.y = -yump.y; - if ( fabs(yump.z) > 0.001f ) physics.linear.velocity.z = -yump.z; - #if UF_USE_BULLET - ext::bullet::move( collider, physics.linear.velocity ); - #endif - } - } else { - if ( !metadata.system.physics.collision ) { - transform.position -= uf::vector::multiply(yump, uf::physics::time::delta); + // setup desired direction + pod::Vector3f target = {}; + if ( keys.forward ^ keys.backwards ) target += translator.forward * (keys.forward ? 1 : -1); + if ( keys.left ^ keys.right ) target += translator.right * (keys.right ? 1 : -1); + target = uf::vector::normalize( target ); + + physics.linear.velocity *= { speed.friction, 1, speed.friction }; + + stats.walking = (keys.forward ^ keys.backwards) || (keys.left ^ keys.right); + if ( stats.walking ) { + if ( !true && stats.noclipped ) { + physics.linear.velocity = target * speed.move; } else { - if ( !metadata.system.crouching ) stats.deltaCrouch = true; - metadata.system.crouching = true; + physics.linear.velocity += target * std::clamp( speed.move * (stats.floored ? 1.0f : 0.5f) - uf::vector::dot( physics.linear.velocity, target ), 0.0f, speed.move * 10 * uf::physics::time::delta ); } } - } else { - if ( metadata.system.crouching ) stats.deltaCrouch = true; - metadata.system.crouching = false; + if ( !stats.floored ) stats.walking = false; } } - if ( stats.noclipped && !keys.forward && !keys.backwards && !keys.left && !keys.right && !keys.jump && !keys.crouch ) { - if ( collider.body && !collider.shared ) { - physics.linear.velocity = {}; - #if UF_USE_BULLET - ext::bullet::move( collider, physics.linear.velocity ); - #endif - } + if ( stats.floored && keys.jump ) { + physics.linear.velocity += metadata.system.physics.jump; } + if ( keys.crouch ) { + if ( stats.noclipped ) physics.linear.velocity -= metadata.system.physics.jump; + else { + if ( !metadata.system.crouching ) stats.deltaCrouch = true; + metadata.system.crouching = true; + } + } else { + if ( metadata.system.crouching ) stats.deltaCrouch = true; + metadata.system.crouching = false; + } + + if ( keys.lookRight ^ keys.lookLeft ) { + #if UF_USE_BULLET + if ( collider.body && !collider.shared ) ext::bullet::applyRotation( collider, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else + #endif + uf::transform::rotate( transform, transform.up, speed.rotate ); + } + { + #if UF_USE_BULLET + if ( collider.body && !collider.shared ) ext::bullet::setVelocity( collider, physics.linear.velocity ); else + #endif + transform.position += physics.linear.velocity * uf::physics::time::delta; + } + + if ( stats.deltaCrouch ) { float delta = metadata.system.physics.crouch; if ( metadata.system.crouching ) camera.getTransform().position.y -= delta; else camera.getTransform().position.y += delta; - stats.updateCamera = true; } + #if UF_USE_OPENAL if ( stats.floored ) { if ( stats.walking ) { @@ -525,7 +438,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { } } #endif - if ( stats.updateCamera ) camera.update(true); + camera.update(true); #if UF_ENTITY_METADATA_USE_JSON metadata.serialize(self, metadataJson); diff --git a/ext/behaviors/player/behavior.h b/ext/behaviors/player/behavior.h index 9e78ea58..75fd27a5 100644 --- a/ext/behaviors/player/behavior.h +++ b/ext/behaviors/player/behavior.h @@ -22,6 +22,8 @@ namespace ext { float run = 1.0f; float walk = 1.0f; pod::Vector3f jump = {0,8,0}; + + pod::Vector3f velocity = {0,0,0}; } physics; bool control = true; diff --git a/ext/behaviors/player/model/behavior.cpp b/ext/behaviors/player/model/behavior.cpp index 0c2cd9de..b751c92a 100644 --- a/ext/behaviors/player/model/behavior.cpp +++ b/ext/behaviors/player/model/behavior.cpp @@ -44,7 +44,7 @@ void ext::PlayerModelBehavior::tick( uf::Object& self ) { if ( !entity->hasComponent() ) return; auto& graphic = entity->getComponent(); auto& pipeline = graphic.getPipeline(); - pipeline.metadata.process = false; + pipeline.metadata.process = !metadata.hide; metadata.set = true; }); metadata.set = true; @@ -53,16 +53,17 @@ void ext::PlayerModelBehavior::tick( uf::Object& self ) { void ext::PlayerModelBehavior::render( uf::Object& self ){} void ext::PlayerModelBehavior::destroy( uf::Object& self ){} void ext::PlayerModelBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ){ + serializer["track"] = /*this->*/track; + serializer["hide"] = /*this->*/hide; +} +void ext::PlayerModelBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){ auto& transform = this->getComponent>(); /*this->*/track = serializer["track"].as(); /*this->*/hide = serializer["hide"].as(); /*this->*/scale = transform.scale; + /*this->*/set = false; transform.reference = /*this->*/track ? /*this->*/reference : NULL; } -void ext::PlayerModelBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){ - serializer["track"] = /*this->*/track; - serializer["hide"] = /*this->*/hide; -} #undef this \ No newline at end of file diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index f73f4e56..05430c7e 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -57,7 +57,11 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) { audio = std::move(asset); assetLoader.remove(filename); - audio.setVolume(metadataJson["volumes"]["bgm"].as()); + #if UF_AUDIO_MAPPED_VOLUMES + audio.setVolume(uf::audio::volumes.count("bgm") > 0 ? uf::audio::volumes.at("bgm") : 1.0); + #else + audio.setVolume(uf::audio::volumes::bgm); + #endif audio.loop( true ); audio.play(); }); @@ -175,11 +179,8 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) { image.open(filename); image.flip(); - if ( size.x == 0 && size.y == 0 ) { - size = image.getDimensions(); - } else if ( size != image.getDimensions() ) { - UF_MSG_ERROR("ERROR: MISMATCH CUBEMAP FACE SIZE"); - } + if ( size.x == 0 && size.y == 0 ) size = image.getDimensions(); + else if ( size != image.getDimensions() ) UF_EXCEPTION("ERROR: MISMATCH CUBEMAP FACE SIZE"); auto& p = image.getPixels(); pixels.reserve( pixels.size() + p.size() ); @@ -340,9 +341,9 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { uf::stl::vector entities; entities.reserve(graph.size() / 2); - uf::graph::storage.lights.clear(); uf::graph::storage.lights.reserve(metadata.max.lights); - uf::graph::storage.shadow2Ds.clear(); uf::graph::storage.shadow2Ds.reserve(metadata.max.lights); - uf::graph::storage.shadowCubes.clear(); uf::graph::storage.shadowCubes.reserve(metadata.max.lights); + uf::graph::storage.lights.clear(); uf::graph::storage.lights.reserve(metadata.light.max); + uf::graph::storage.shadow2Ds.clear(); uf::graph::storage.shadow2Ds.reserve(metadata.light.max); + uf::graph::storage.shadowCubes.clear(); uf::graph::storage.shadowCubes.reserve(metadata.light.max); // traverse scene graph for ( auto entity : graph ) { @@ -382,7 +383,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { for ( auto& info : entities ) if ( info.shadows && shadowCount-- <= 0 ) info.shadows = false; // bind lighting and requested shadow maps - for ( uint32_t i = 0; i < entities.size() && uf::graph::storage.lights.size() < metadata.max.lights; ++i ) { + for ( uint32_t i = 0; i < entities.size() && uf::graph::storage.lights.size() < metadata.light.max; ++i ) { auto& info = entities[i]; uf::Entity* entity = info.entity; @@ -522,7 +523,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali /*this->*/max.textures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as(/*this->*/max.textures2D); /*this->*/max.texturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as(/*this->*/max.texturesCube); /*this->*/max.textures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as(/*this->*/max.textures3D); - /*this->*/max.lights = ext::config["engine"]["scenes"]["lights"]["max"].as(/*this->*/max.lights); + /*this->*/light.max = ext::config["engine"]["scenes"]["lights"]["max"].as(/*this->*/light.max); /*this->*/shadow.enabled = ext::config["engine"]["scenes"]["shadows"]["enabled"].as(true) && serializer["light"]["shadows"].as(true); /*this->*/shadow.samples = ext::config["engine"]["scenes"]["shadows"]["samples"].as(); @@ -537,8 +538,6 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali /*this->*/light.gamma = serializer["light"]["gamma"].as(2.2f); /*this->*/light.brightnessThreshold = serializer["light"]["brightnessThreshold"].as(ext::config["engine"]["scenes"]["bloom"]["brightnessThreshold"].as(1.0f)); - UF_MSG_DEBUG( serializer["bloom"] ); - /*this->*/bloom.scale = serializer["bloom"]["scale"].as(ext::config["engine"]["scenes"]["bloom"]["scale"].as(bloom.scale)); /*this->*/bloom.strength = serializer["bloom"]["strength"].as(ext::config["engine"]["scenes"]["bloom"]["strength"].as(bloom.strength)); /*this->*/bloom.sigma = serializer["bloom"]["sigma"].as(ext::config["engine"]["scenes"]["bloom"]["sigma"].as(bloom.sigma)); @@ -642,12 +641,12 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string static GLint glMaxLights = 0; if ( !glMaxLights ) glGetIntegerv(GL_MAX_LIGHTS, &glMaxLights); - metadata.max.lights = std::min( (uint32_t) glMaxLights, metadata.max.lights ); + metadata.light.max = std::min( (uint32_t) glMaxLights, metadata.light.max ); // add lighting { uint32_t i = 0; - for ( ; i < entities.size() && i < metadata.max.lights; ++i ) { + for ( ; i < entities.size() && i < metadata.light.max; ++i ) { auto& info = entities[i]; uf::Entity* entity = info.entity; GLenum target = GL_LIGHT0+i; @@ -660,7 +659,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string GL_ERROR_CHECK(glLightf(target, GL_LINEAR_ATTENUATION, 0)); GL_ERROR_CHECK(glLightf(target, GL_QUADRATIC_ATTENUATION, 1.0f / info.power)); } - for ( ; i < metadata.max.lights; ++i ) GL_ERROR_CHECK(glDisable(GL_LIGHT0+i)); + for ( ; i < metadata.light.max; ++i ) GL_ERROR_CHECK(glDisable(GL_LIGHT0+i)); } #elif UF_USE_VULKAN struct UniformDescriptor { @@ -805,7 +804,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string }; uniforms.lengths = UniformDescriptor::Lengths{ - .lights = MIN( uf::graph::storage.lights.size(), metadata.max.lights ), + .lights = MIN( uf::graph::storage.lights.size(), metadata.light.max ), .materials = MIN( uf::graph::storage.materials.keys.size(), metadata.max.textures2D ), .textures = MIN( uf::graph::storage.textures.keys.size(), metadata.max.textures2D ), .drawCommands = MIN( 0, metadata.max.textures2D ), diff --git a/ext/behaviors/scene/behavior.h b/ext/behaviors/scene/behavior.h index 7ba0609e..fb749ab1 100644 --- a/ext/behaviors/scene/behavior.h +++ b/ext/behaviors/scene/behavior.h @@ -16,10 +16,10 @@ namespace ext { uint32_t textures2D = 512; uint32_t texturesCube = 128; uint32_t textures3D = 128; - uint32_t lights = 256; } max; struct { bool enabled = true; + uint32_t max = 256; pod::Vector4f ambient = {0,0,0,1}; pod::Vector4f specular = {1,1,1,1}; float exposure = 1.0f; diff --git a/ext/behaviors/soundemitter/behavior.cpp b/ext/behaviors/soundemitter/behavior.cpp index 3120a55f..a8715518 100644 --- a/ext/behaviors/soundemitter/behavior.cpp +++ b/ext/behaviors/soundemitter/behavior.cpp @@ -17,7 +17,6 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) { auto& sounds = emitter.get(); auto& scene = uf::scene::getCurrentScene(); - auto& sMetadata = scene.getComponent(); auto& assetLoader = scene.getComponent(); if ( !metadata["audio"]["epsilon"].is() ) @@ -68,7 +67,13 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) { if ( json["volume"].is() ) volume = json["volume"].as(); else if ( json["volume"].is() ) { uf::stl::string key = json["volume"].as(); - if ( sMetadata["volumes"][key].is() ) volume = sMetadata["volumes"][key].as(); + #if UF_AUDIO_MAPPED_VOLUMES + if ( uf::audio::volumes.count(key) > 0 ) volume = uf::audio::volumes.at(key); + #else + if ( key == "bgm" ) volume = uf::audio::volumes::bgm; + else if ( key == "sfx" ) volume = uf::audio::volumes::sfx; + else if ( key == "voice" ) volume = uf::audio::volumes::voice; + #endif } audio.setVolume(volume); diff --git a/ext/main.cpp b/ext/main.cpp index aad4b0a1..28cffc34 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -244,7 +244,11 @@ void EXT_API ext::initialize() { } { uf::Mesh::defaultInterleaved = ::config["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved ); + #if 0 && UF_USE_OPENGL + uf::matrix::reverseInfiniteProjection = false; + #else uf::matrix::reverseInfiniteProjection = ::config["engine"]["scenes"]["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection ); + #endif } /* Create initial scene (kludge) */ { @@ -278,11 +282,6 @@ void EXT_API ext::initialize() { double limit = ::config["engine"]["limiters"]["deltaTime"].as(); uf::physics::time::clamp = limit != 0 ? 1.0 / limit : 0; } - // Mute audio - uf::audio::muted = ::config["engine"]["audio"]["mute"].as( uf::audio::muted ); - uf::audio::streamsByDefault = ::config["engine"]["audio"]["streams by default"].as( uf::audio::streamsByDefault ); - uf::audio::bufferSize = ::config["engine"]["audio"]["buffers"]["size"].as( uf::audio::bufferSize ); - uf::audio::buffers = ::config["engine"]["audio"]["buffers"]["count"].as( uf::audio::buffers ); // Set worker threads if ( ::config["engine"]["threads"]["workers"].as() == "auto" ) { @@ -290,6 +289,26 @@ void EXT_API ext::initialize() { ::config["engine"]["threads"]["workers"] = threads; UF_MSG_DEBUG("Using " << threads << " worker threads"); } + // Mute audio + uf::audio::muted = ::config["engine"]["audio"]["mute"].as( uf::audio::muted ); + uf::audio::streamsByDefault = ::config["engine"]["audio"]["streams by default"].as( uf::audio::streamsByDefault ); + uf::audio::bufferSize = ::config["engine"]["audio"]["buffers"]["size"].as( uf::audio::bufferSize ); + uf::audio::buffers = ::config["engine"]["audio"]["buffers"]["count"].as( uf::audio::buffers ); + #if UF_AUDIO_MAPPED_VOLUMES + ext::json::forEach( ::config["engine"]["audio"]["volumes"], []( const uf::stl::string& key, ext::json::Value& value ){ + float volume; volume = value.as(volume); + uf::audio::volumes[key] = volume; + }); + #else + uf::audio::volumes::bgm = ::config["engine"]["audio"]["volumes"]["bgm"].as(uf::audio::volumes::bgm); + uf::audio::volumes::sfx = ::config["engine"]["audio"]["volumes"]["sfx"].as(uf::audio::volumes::sfx); + uf::audio::volumes::voice = ::config["engine"]["audio"]["volumes"]["voice"].as(uf::audio::volumes::voice); + #endif + #if UF_USE_OPENAL + /* Initialize OpenAL */ { + ext::al::initialize(); + } + #endif #if UF_USE_BULLET // set bullet parameters @@ -375,11 +394,11 @@ void EXT_API ext::initialize() { #if UF_USE_LUA /* Lua */ { - ext::lua::main = ::config["engine"]["ext"]["lua"]["main"].as(); - for ( auto it = ::config["engine"]["ext"]["lua"]["modules"].begin(); it != ::config["engine"]["ext"]["lua"]["modules"].end(); ++it ) { - uf::stl::string key = it.key(); - ext::lua::modules[key] = ::config["engine"]["ext"]["lua"]["modules"][key].as(); - } + ext::lua::enabled = ::config["engine"]["ext"]["lua"]["enabled"].as(ext::lua::enabled); + ext::lua::main = ::config["engine"]["ext"]["lua"]["main"].as(ext::lua::main); + ext::json::forEach( ::config["engine"]["ext"]["lua"]["modules"], []( const uf::stl::string& key, ext::json::Value& value ){ + ext::lua::modules[key] = value.as(); + }); ext::lua::initialize(); } #endif @@ -544,18 +563,17 @@ void EXT_API ext::initialize() { payload["scene"] = ::config["engine"]["scenes"]["start"]; payload["immediate"] = true; uf::hooks.call("game:Scene.Load", payload); - } - - ext::ready = true; - UF_MSG_INFO("EXT took " << times.sys.elapsed().asDouble() << " seconds to initialize!"); - { uf::thread::add( uf::thread::fetchWorker(), [&]() -> int { auto& scene = uf::scene::getCurrentScene(); auto& assetLoader = scene.getComponent(); assetLoader.processQueue(); return 0;}, false ); } + + ext::ready = true; + UF_MSG_INFO("EXT took " << times.sys.elapsed().asDouble() << " seconds to initialize!"); + } void EXT_API ext::tick() { @@ -774,6 +792,12 @@ void EXT_API ext::terminate() { uf::renderer::destroy(); } + #if UF_USE_OPENAL + /* Initialize OpenAL */ { + ext::al::destroy(); + } + #endif + /* Print system stats */ { ::times.total.time = times.sys.elapsed().asDouble(); UF_MSG_DEBUG("System: Total Time: " << ::times.total.time << " | Total Frames: " << ::times.total.frames << " | Average FPS: " << ::times.total.frames / ::times.total.time);