Commit for 2021.07.27 22-27-21.7z
This commit is contained in:
parent
ff15e641eb
commit
60cb5bd236
17
Makefile
17
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)))
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
],
|
||||
"transform": {
|
||||
"position": [ 0, -2.0, 0 ],
|
||||
// "position": [ 12.5715, 3.53811, 7.6238 ],
|
||||
"rotation": {
|
||||
"axis": [ 0, 1, 0 ],
|
||||
"angle": 0
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
},
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
27
bin/data/shaders/common/lambert.h
Normal file
27
bin/data/shaders/common/lambert.h
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<T>({
|
||||
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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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<uf::renderer::AttributeDescriptor> 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<uf::renderer::AttributeDescriptor> descriptor;
|
||||
};
|
||||
struct Skinned {
|
||||
pod::Vector3f position;
|
||||
pod::ColorRgba color;
|
||||
pod::Vector2f uv;
|
||||
pod::Vector2f st;
|
||||
pod::Vector3f normal;
|
||||
pod::Vector3f tangent;
|
||||
pod::Vector<id_t, 4> joints;
|
||||
pod::Vector<uint16_t, 4> joints;
|
||||
pod::Vector4f weights;
|
||||
|
||||
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
|
||||
};
|
||||
}
|
||||
/*
|
||||
typedef uf::Mesh<uf::graph::mesh::Base> base_mesh_t;
|
||||
typedef uf::Mesh<uf::graph::mesh::ID> id_mesh_t;
|
||||
typedef uf::Mesh<uf::graph::mesh::Skinned> skinned_mesh_t;
|
||||
*/
|
||||
}
|
||||
}
|
||||
@ -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 );
|
||||
|
||||
@ -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<uf::stl::string, uf::stl::string> modules;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include <uf/config.h>
|
||||
#include <uf/utils/mesh/mesh.h>
|
||||
#include <uf/ext/meshopt/meshopt.h>
|
||||
|
||||
namespace ext {
|
||||
namespace meshopt {
|
||||
|
||||
@ -3,10 +3,15 @@
|
||||
#include <uf/config.h>
|
||||
#if UF_USE_OPENAL
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <AL/alut.h>
|
||||
|
||||
#if UF_ENV_DREAMCAST && UF_USE_OPENAL_ALDC
|
||||
#include <ALdc/al.h>
|
||||
#include <ALdc/alc.h>
|
||||
#include <ALdc/alut.h>
|
||||
#else
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <AL/alut.h>
|
||||
#endif
|
||||
#include <uf/utils/memory/string.h>
|
||||
#include <uf/utils/memory/vector.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 {
|
||||
|
||||
@ -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<long long> timer(false);\
|
||||
if ( !timer.running() ) {\
|
||||
timer.start(uf::Time<long long>(-x * 1000, uf::Time<long long>::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<long long> timer(false);\
|
||||
if ( !timer.running() ) timer.start(uf::Time<long long>(-x * 1000, uf::Time<long long>::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<long long> timer(false);\
|
||||
if ( !timer.running() ) timer.start(uf::Time<long long>(-x * 1000, uf::Time<long long>::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 )
|
||||
@ -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<uf::stl::string, float> 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:
|
||||
|
||||
@ -72,17 +72,17 @@ namespace uf {
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ multiplyAll( const T& matrix, typename T::type_t scalar );
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ add( const T& lhs, const T& rhs );
|
||||
// Writes to first value
|
||||
// template<typename T=pod::Matrix4> pod::Matrix<typename T::type_t, C, C>& /*UF_API*/ multiply( T& left, const T& right ); // Multiplies two matrices of same type and size together
|
||||
template<typename T, typename U> pod::Matrix<typename T::type_t, T::columns, T::columns> multiply( T& left, const U& right ); // Multiplies two matrices of same type and size together
|
||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> multiply( T& left, const T& right );
|
||||
template<typename T=pod::Matrix4> T& /*UF_API*/ invert( T& matrix ); // Flip sign of all components
|
||||
// template<typename T=pod::Matrix4> pod::Matrix<typename T::type_t, C, C>& /*UF_API*/ multiply_( T& left, const T& right ); // Multiplies two matrices of same type and size together
|
||||
template<typename T, typename U> pod::Matrix<typename T::type_t, T::columns, T::columns> multiply_( T& left, const U& right ); // Multiplies two matrices of same type and size together
|
||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> multiply_( T& left, const T& right );
|
||||
template<typename T=pod::Matrix4> T& /*UF_API*/ translate_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> T& /*UF_API*/ rotate_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> T& /*UF_API*/ scale_( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
// Complex arithmetic
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ translate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ rotate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ scale( const T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> T& /*UF_API*/ translate( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> T& /*UF_API*/ rotate( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> T& /*UF_API*/ scale( T& matrix, const pod::Vector3t<typename T::type_t>& vector );
|
||||
template<typename T=pod::Matrix4> pod::Vector3t<typename T::type_t> /*UF_API*/ eulerAngles( const T& matrix );
|
||||
|
||||
template<typename T=pod::Math::num_t> pod::Matrix4t<T> /*UF_API*/ orthographic( T, T, T, T, T, T );
|
||||
|
||||
@ -424,11 +424,6 @@ template<typename T> T uf::matrix::inverse( const T& matrix ) {
|
||||
|
||||
return inverted;
|
||||
}
|
||||
// Writes to first value
|
||||
// Multiplies two matrices of same type and size together
|
||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> uf::matrix::multiply( T& left, const T& right ) {
|
||||
return left = uf::matrix::multiply((const T&) left, right);
|
||||
}
|
||||
template<typename T> pod::Vector3t<T> uf::matrix::multiply( const pod::Matrix4t<T>& mat, const pod::Vector3t<T>& vector, T w, bool div ) {
|
||||
return uf::matrix::multiply( mat, pod::Vector4t<T>{ vector[0], vector[1], vector[2], w }, div );
|
||||
}
|
||||
@ -450,10 +445,51 @@ template<typename T> pod::Vector4t<T> 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<typename T> T& uf::matrix::invert( T& matrix ) {
|
||||
return matrix = uf::matrix::inverse((const T&) matrix);
|
||||
}
|
||||
|
||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> uf::matrix::multiply_( T& left, const T& right ) {
|
||||
return left = uf::matrix::multiply((const T&) left, right);
|
||||
}
|
||||
template<typename T> T& uf::matrix::translate_( T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
|
||||
matrix[12] = vector.x;
|
||||
matrix[13] = vector.y;
|
||||
matrix[14] = vector.z;
|
||||
return matrix;
|
||||
}
|
||||
template<typename T> T& uf::matrix::rotate_( T& matrix, const pod::Vector3t<typename T::type_t>& 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<typename T> T& uf::matrix::scale_( T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
|
||||
matrix[0] = vector.x;
|
||||
matrix[5] = vector.y;
|
||||
matrix[10] = vector.z;
|
||||
return matrix;
|
||||
}
|
||||
// Complex arithmetic
|
||||
template<typename T> T uf::matrix::translate( const T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
|
||||
alignas(16) T res = matrix;
|
||||
@ -493,41 +529,6 @@ template<typename T> T uf::matrix::scale( const T& matrix, const pod::Vector3t<t
|
||||
res[10] = vector.z;
|
||||
return res;
|
||||
}
|
||||
template<typename T> T& uf::matrix::translate( T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
|
||||
matrix[12] = vector.x;
|
||||
matrix[13] = vector.y;
|
||||
matrix[14] = vector.z;
|
||||
return matrix;
|
||||
}
|
||||
template<typename T> T& uf::matrix::rotate( T& matrix, const pod::Vector3t<typename T::type_t>& 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<typename T> T& uf::matrix::scale( T& matrix, const pod::Vector3t<typename T::type_t>& vector ) {
|
||||
matrix[0] = vector.x;
|
||||
matrix[5] = vector.y;
|
||||
matrix[10] = vector.z;
|
||||
return matrix;
|
||||
}
|
||||
template<typename T>
|
||||
pod::Matrix4t<T> /*UF_API*/ uf::matrix::orthographic( T l, T r, T b, T t, T f, T n ) {
|
||||
alignas(16) pod::Matrix4t<T> m = uf::matrix::identity();
|
||||
|
||||
@ -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<typename T> pod::Transform<T>& update( pod::Transform<T>& transform, pod::Physics& physics );
|
||||
|
||||
@ -15,18 +15,18 @@
|
||||
|
||||
namespace pod {
|
||||
// Simple vectors (designed [to store in arrays] with minimal headaches)
|
||||
template<typename T = pod::Math::num_t, std::size_t N = 3>
|
||||
template<typename T = pod::Math::num_t, size_t N = 3>
|
||||
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<T,N> operator()() const; // Negation
|
||||
Vector<T,N> operator-() const; // Negation
|
||||
@ -110,27 +110,28 @@ namespace uf {
|
||||
template<typename T> bool /*UF_API*/ equals( const T& left, const T& right ); // Equality check between two vectors (equals)
|
||||
// Basic arithmetic
|
||||
template<typename T> T /*UF_API*/ add( const T& left, const T& right ); // Adds two vectors of same type and size together
|
||||
template<typename T> T /*UF_API*/ add( const T& left, const typename T::type_t& scalar ); // Adds two vectors of same type and size together
|
||||
template<typename T> 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<typename T> T /*UF_API*/ subtract( const T& left, const T& right ); // Subtracts two vectors of same type and size together
|
||||
template<typename T> T /*UF_API*/ subtract( const T& left, const typename T::type_t& scalar ); // Subtracts two vectors of same type and size together
|
||||
template<typename T> 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<typename T> T /*UF_API*/ multiply( const T& left, const T& right ); // Multiplies two vectors of same type and size together
|
||||
template<typename T> T /*UF_API*/ multiply( const T& vector, const typename T::type_t& scalar ); // Multiplies this vector by a scalar
|
||||
template<typename T> T /*UF_API*/ multiply( const T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ); // Multiplies this vector by a scalar
|
||||
template<typename T> T /*UF_API*/ divide( const T& left, const T& right ); // Divides two vectors of same type and size together
|
||||
template<typename T> T /*UF_API*/ divide( const T& left, const typename T::type_t& scalar ); // Divides this vector by a scalar
|
||||
template<typename T> 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> typename T::type_t /*UF_API*/ sum( const T& vector ); // Compute the sum of all components
|
||||
template<typename T> typename T::type_t /*UF_API*/ product( const T& vector ); // Compute the product of all components
|
||||
template<typename T> T /*UF_API*/ negate( const T& vector ); // Flip sign of all components
|
||||
// Writes to first value
|
||||
template<typename T> T& /*UF_API*/ add( T& left, const T& right ); // Adds two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ add( T& left, const typename T::type_t& scalar ); // Adds two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ subtract( T& left, const T& right ); // Subtracts two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ subtract( T& left, const typename T::type_t& scalar ); // Subtracts two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ multiply( T& left, const T& right ); // Multiplies two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ multiply( T& vector, const typename T::type_t& scalar ); // Multiplies this vector by a scalar
|
||||
template<typename T> T& /*UF_API*/ divide( T& left, const T& right ); // Divides two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ divide( T& left, const typename T::type_t& scalar ); // Divides this vector by a scalar
|
||||
template<typename T> T& /*UF_API*/ negate( T& vector ); // Flip sign of all components
|
||||
template<typename T> T& /*UF_API*/ normalize( T& vector ); // Normalizes a vector
|
||||
template<typename T> T& /*UF_API*/ add_( T& left, const T& right ); // Adds two vectors of same type and size together
|
||||
template<typename T> 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<typename T> T& /*UF_API*/ subtract_( T& left, const T& right ); // Subtracts two vectors of same type and size together
|
||||
template<typename T> 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<typename T> T& /*UF_API*/ multiply_( T& left, const T& right ); // Multiplies two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ multiply_( T& vector, /*const typename T::type_t&*/ typename T::type_t scalar ); // Multiplies this vector by a scalar
|
||||
template<typename T> T& /*UF_API*/ divide_( T& left, const T& right ); // Divides two vectors of same type and size together
|
||||
template<typename T> T& /*UF_API*/ divide_( T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Divides this vector by a scalar
|
||||
template<typename T> T& /*UF_API*/ negate_( T& vector ); // Flip sign of all components
|
||||
template<typename T> T& /*UF_API*/ normalize_( T& vector ); // Normalizes a vector
|
||||
|
||||
template<typename T> T /*UF_API*/ min( const T& left, const T& right ); //
|
||||
template<typename T> T /*UF_API*/ max( const T& left, const T& right ); //
|
||||
template<typename T> T /*UF_API*/ ceil( const T& vector ); //
|
||||
@ -149,8 +150,8 @@ namespace uf {
|
||||
|
||||
template<typename T> 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> typename T::type_t /*UF_API*/ distance( const T& a, const T& b ); // Compute the distance between two vectors
|
||||
template<typename T> typename T::type_t /*UF_API*/ magnitude( const T& vector ); // Gets the magnitude of the vector
|
||||
template<typename T> typename T::type_t /*UF_API*/ norm( const T& vector ); // Compute the norm of the vector
|
||||
template<typename T> typename T::type_t /*UF_API*/ magnitude( const T& vector ); // Gets the magnitude of the vector
|
||||
template<typename T> T /*UF_API*/ normalize( const T& vector ); // Normalizes a vector
|
||||
template<typename T> void /*UF_API*/ orthonormalize( T& x, T& y ); // Normalizes a vector
|
||||
template<typename T> 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<typename T = pod::Math::num_t, std::size_t N = 3>
|
||||
template<typename T = pod::Math::num_t, size_t N = 3>
|
||||
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<T,N>::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<T,N> operator-() const; // Negation
|
||||
inline Vector<T,N> operator+( const Vector<T,N>& 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<T,1> operator()() const; // Creation
|
||||
inline Vector<T,1> 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<T,2> operator()() const; // Creation
|
||||
inline Vector<T,2> 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<T,3> operator()() const; // Creation
|
||||
inline Vector<T,3> 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<T,4> operator()() const; // Creation
|
||||
inline Vector<T,4> operator-() const; // Negation
|
||||
|
||||
@ -22,7 +22,7 @@ template<typename T, size_t N, typename U>
|
||||
pod::Vector<T, N> /*UF_API*/ uf::vector::cast( const U& from ) {
|
||||
alignas(16) pod::Vector<T, N> 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> // 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<typename T> //
|
||||
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<typename T> //
|
||||
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<typename T> //
|
||||
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<typename T> //
|
||||
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<typename T> //
|
||||
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<typename T::type_t> 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<typename T> // 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<T,N>& 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<typename T, size_t N>
|
||||
pod::Vector<T,N>& /*UF_API*/ uf::vector::decode( const ext::json::Value& json, pod::Vector<T,N>& 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<T>(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<T>(v[i]) );
|
||||
@ -497,10 +504,10 @@ pod::Vector<T,N> /*UF_API*/ uf::vector::decode( const ext::json::Value& json, co
|
||||
pod::Vector<T,N> 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<T>(_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<T>(_v[i]);
|
||||
|
||||
@ -47,35 +47,35 @@ inline pod::Vector<T,N> pod::Vector<T,N>::operator/( T scalar ) const {
|
||||
}
|
||||
template<typename T, std::size_t N> // Addition set between two vectors
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator +=( const pod::Vector<T,N>& vector ) {
|
||||
return uf::vector::add( *this, vector );
|
||||
return uf::vector::add_( *this, vector );
|
||||
}
|
||||
template<typename T, std::size_t N> // Subtraction set between two vectors
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator -=( const pod::Vector<T,N>& vector ) {
|
||||
return uf::vector::subtract( *this, vector );
|
||||
return uf::vector::subtract_( *this, vector );
|
||||
}
|
||||
template<typename T, std::size_t N> // Multiplication set between two vectors
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator *=( const pod::Vector<T,N>& vector ) {
|
||||
return uf::vector::multiply( *this, vector );
|
||||
return uf::vector::multiply_( *this, vector );
|
||||
}
|
||||
template<typename T, std::size_t N> // Division set between two vectors
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator /=( const pod::Vector<T,N>& vector ) {
|
||||
return uf::vector::divide( *this, vector );
|
||||
return uf::vector::divide_( *this, vector );
|
||||
}
|
||||
template<typename T, std::size_t N> // Multiplication set with scalar
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator +=( T scalar ) {
|
||||
return uf::vector::add( *this, scalar );
|
||||
return uf::vector::add_( *this, scalar );
|
||||
}
|
||||
template<typename T, std::size_t N> // Multiplication set with scalar
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator -=( T scalar ) {
|
||||
return uf::vector::subtract( *this, scalar );
|
||||
return uf::vector::subtract_( *this, scalar );
|
||||
}
|
||||
template<typename T, std::size_t N> // Multiplication set with scalar
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator *=( T scalar ) {
|
||||
return uf::vector::multiply( *this, scalar );
|
||||
return uf::vector::multiply_( *this, scalar );
|
||||
}
|
||||
template<typename T, std::size_t N> // Division set with scalar
|
||||
inline pod::Vector<T,N>& pod::Vector<T,N>::operator /=( T scalar ) {
|
||||
return uf::vector::divide( *this, scalar );
|
||||
return uf::vector::divide_( *this, scalar );
|
||||
}
|
||||
template<typename T, std::size_t N> // Equality check between two vectors (equals)
|
||||
inline bool pod::Vector<T,N>::operator==( const pod::Vector<T,N>& vector ) const {
|
||||
@ -170,35 +170,35 @@ inline pod::Vector<T,1> pod::Vector<T,1>::operator/( T scalar ) const {
|
||||
}
|
||||
template<typename T> // Addition set between two vectors
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator +=( const pod::Vector<T,1>& vector ) {
|
||||
return uf::vector::add( *this, vector );
|
||||
return uf::vector::add_( *this, vector );
|
||||
}
|
||||
template<typename T> // Subtraction set between two vectors
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator -=( const pod::Vector<T,1>& vector ) {
|
||||
return uf::vector::subtract( *this, vector );
|
||||
return uf::vector::subtract_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication set between two vectors
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator *=( const pod::Vector<T,1>& vector ) {
|
||||
return uf::vector::multiply( *this, vector );
|
||||
return uf::vector::multiply_( *this, vector );
|
||||
}
|
||||
template<typename T> // Division set between two vectors
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator /=( const pod::Vector<T,1>& vector ) {
|
||||
return uf::vector::divide( *this, vector );
|
||||
return uf::vector::divide_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator +=( T scalar ) {
|
||||
return uf::vector::add( *this, scalar );
|
||||
return uf::vector::add_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator -=( T scalar ) {
|
||||
return uf::vector::subtract( *this, scalar );
|
||||
return uf::vector::subtract_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication set with scalar
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator *=( T scalar ) {
|
||||
return uf::vector::multiply( *this, scalar );
|
||||
return uf::vector::multiply_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Division set with scalar
|
||||
inline pod::Vector<T,1>& pod::Vector<T,1>::operator /=( T scalar ) {
|
||||
return uf::vector::divide( *this, scalar );
|
||||
return uf::vector::divide_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Equality check between two vectors (equals)
|
||||
inline bool pod::Vector<T,1>::operator==( const pod::Vector<T,1>& vector ) const {
|
||||
@ -292,35 +292,35 @@ inline pod::Vector<T,2> pod::Vector<T,2>::operator/( T scalar ) const {
|
||||
}
|
||||
template<typename T> // Addition set between two vectors
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator +=( const pod::Vector<T,2>& vector ) {
|
||||
return uf::vector::add( *this, vector );
|
||||
return uf::vector::add_( *this, vector );
|
||||
}
|
||||
template<typename T> // Subtraction set between two vectors
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator -=( const pod::Vector<T,2>& vector ) {
|
||||
return uf::vector::subtract( *this, vector );
|
||||
return uf::vector::subtract_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication set between two vectors
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator *=( const pod::Vector<T,2>& vector ) {
|
||||
return uf::vector::multiply( *this, vector );
|
||||
return uf::vector::multiply_( *this, vector );
|
||||
}
|
||||
template<typename T> // Division set between two vectors
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator /=( const pod::Vector<T,2>& vector ) {
|
||||
return uf::vector::divide( *this, vector );
|
||||
return uf::vector::divide_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator+=( T scalar ) {
|
||||
return uf::vector::add( *this, scalar );
|
||||
return uf::vector::add_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator-=( T scalar ) {
|
||||
return uf::vector::subtract( *this, scalar );
|
||||
return uf::vector::subtract_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication set with scalar
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator *=( T scalar ) {
|
||||
return uf::vector::multiply( *this, scalar );
|
||||
return uf::vector::multiply_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Division set with scalar
|
||||
inline pod::Vector<T,2>& pod::Vector<T,2>::operator /=( T scalar ) {
|
||||
return uf::vector::divide( *this, scalar );
|
||||
return uf::vector::divide_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Equality check between two vectors (equals)
|
||||
inline bool pod::Vector<T,2>::operator==( const pod::Vector<T,2>& vector ) const {
|
||||
@ -414,35 +414,35 @@ inline pod::Vector<T,3> pod::Vector<T,3>::operator/( T scalar ) const {
|
||||
}
|
||||
template<typename T> // Addition set between two vectors
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator +=( const pod::Vector<T,3>& vector ) {
|
||||
return uf::vector::add( *this, vector );
|
||||
return uf::vector::add_( *this, vector );
|
||||
}
|
||||
template<typename T> // Subtraction set between two vectors
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator -=( const pod::Vector<T,3>& vector ) {
|
||||
return uf::vector::subtract( *this, vector );
|
||||
return uf::vector::subtract_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication set between two vectors
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator *=( const pod::Vector<T,3>& vector ) {
|
||||
return uf::vector::multiply( *this, vector );
|
||||
return uf::vector::multiply_( *this, vector );
|
||||
}
|
||||
template<typename T> // Division set between two vectors
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator /=( const pod::Vector<T,3>& vector ) {
|
||||
return uf::vector::divide( *this, vector );
|
||||
return uf::vector::divide_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator +=( T scalar ) {
|
||||
return uf::vector::add( *this, scalar );
|
||||
return uf::vector::add_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator -=( T scalar ) {
|
||||
return uf::vector::subtract( *this, scalar );
|
||||
return uf::vector::subtract_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication set with scalar
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator *=( T scalar ) {
|
||||
return uf::vector::multiply( *this, scalar );
|
||||
return uf::vector::multiply_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Division set with scalar
|
||||
inline pod::Vector<T,3>& pod::Vector<T,3>::operator /=( T scalar ) {
|
||||
return uf::vector::divide( *this, scalar );
|
||||
return uf::vector::divide_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Equality check between two vectors (equals)
|
||||
inline bool pod::Vector<T,3>::operator==( const pod::Vector<T,3>& vector ) const {
|
||||
@ -549,35 +549,35 @@ inline pod::Vector<T,4> pod::Vector<T,4>::operator/( T scalar ) const {
|
||||
}
|
||||
template<typename T> // Addition set between two vectors
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator +=( const pod::Vector<T,4>& vector ) {
|
||||
return uf::vector::add( *this, vector );
|
||||
return uf::vector::add_( *this, vector );
|
||||
}
|
||||
template<typename T> // Subtraction set between two vectors
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator -=( const pod::Vector<T,4>& vector ) {
|
||||
return uf::vector::subtract( *this, vector );
|
||||
return uf::vector::subtract_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication set between two vectors
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator *=( const pod::Vector<T,4>& vector ) {
|
||||
return uf::vector::multiply( *this, vector );
|
||||
return uf::vector::multiply_( *this, vector );
|
||||
}
|
||||
template<typename T> // Division set between two vectors
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator /=( const pod::Vector<T,4>& vector ) {
|
||||
return uf::vector::divide( *this, vector );
|
||||
return uf::vector::divide_( *this, vector );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator+=( T scalar ) {
|
||||
return uf::vector::add( *this, scalar );
|
||||
return uf::vector::add_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication with scalar
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator-=( T scalar ) {
|
||||
return uf::vector::subtract( *this, scalar );
|
||||
return uf::vector::subtract_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Multiplication set with scalar
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator *=( T scalar ) {
|
||||
return uf::vector::multiply( *this, scalar );
|
||||
return uf::vector::multiply_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Division set with scalar
|
||||
inline pod::Vector<T,4>& pod::Vector<T,4>::operator /=( T scalar ) {
|
||||
return uf::vector::divide( *this, scalar );
|
||||
return uf::vector::divide_( *this, scalar );
|
||||
}
|
||||
template<typename T> // Equality check between two vectors (equals)
|
||||
inline bool pod::Vector<T,4>::operator==( const pod::Vector<T,4>& vector ) const {
|
||||
|
||||
@ -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<uf::renderer::AttributeDescriptor> descriptor;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#include <uf/ext/meshopt/meshopt.h>
|
||||
#include "mesh.inl"
|
||||
}
|
||||
@ -1,163 +0,0 @@
|
||||
#if 0
|
||||
template<typename T, typename U>
|
||||
void uf::Mesh<T, U>::initialize( size_t o ) {
|
||||
this->optimize(o);
|
||||
if ( this->indices.empty() ) this->generateIndices();
|
||||
this->updateDescriptor();
|
||||
}
|
||||
template<typename T, typename U>
|
||||
void uf::Mesh<T, U>::expand( bool check ) {
|
||||
if ( this->indices.empty() ) return;
|
||||
uf::stl::vector<vertex_t> _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<vertex_t> 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<typename T, typename U>
|
||||
void uf::Mesh<T, U>::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<typename T, typename U>
|
||||
void uf::Mesh<T, U>::destroy() {
|
||||
this->indices.clear();
|
||||
this->vertices.clear();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
uf::Mesh<T,U> uf::Mesh<T,U>::simplify( float threshold ) {
|
||||
size_t target = size_t(this->indices.size() * threshold);
|
||||
float error = 1e-2f;
|
||||
uf::Mesh<T,U> 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<typename T, typename U>
|
||||
void uf::Mesh<T,U>::optimize( size_t o ) {
|
||||
#if UF_USE_MESHOPTIMIZER
|
||||
ext::meshopt::optimize( *this, o );
|
||||
#endif
|
||||
this->updateDescriptor();
|
||||
}
|
||||
template<typename T, typename U>
|
||||
void uf::Mesh<T,U>::insert( const uf::Mesh<T,U>& 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<typename T, typename U>
|
||||
void uf::Mesh<T,U>::resizeVertices( size_t n ) {
|
||||
this->vertices.resize(n);
|
||||
this->updateDescriptor();
|
||||
}
|
||||
template<typename T, typename U>
|
||||
void uf::Mesh<T,U>::resizeIndices( size_t n ) {
|
||||
this->indices.resize(n);
|
||||
this->updateDescriptor();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
template<typename T, typename U>
|
||||
bool pod::VaryingMesh::is() const {
|
||||
#if 0
|
||||
return uf::pointeredUserdata::is<uf::Mesh<T,U>>();
|
||||
#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<typename T, typename U>
|
||||
uf::Mesh<T,U>& pod::VaryingMesh::get() {
|
||||
if ( !userdata.data ) set<T,U>();
|
||||
return uf::pointeredUserdata::get<uf::Mesh<T,U>>( userdata );
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
const uf::Mesh<T,U>& pod::VaryingMesh::get() const {
|
||||
UF_ASSERT( userdata.data );
|
||||
return uf::pointeredUserdata::get<uf::Mesh<T,U>>( userdata );
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
void pod::VaryingMesh::set( const uf::Mesh<T, U>& mesh ) {
|
||||
if ( userdata.data ) uf::pointeredUserdata::destroy( userdata );
|
||||
userdata = uf::pointeredUserdata::create( mesh );
|
||||
attributes = mesh.attributes;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
void pod::VaryingMesh::insert( const pod::VaryingMesh& mesh ) {
|
||||
get<T,U>().insert( mesh.get<T,U>() );
|
||||
updateDescriptor();
|
||||
}
|
||||
template<typename T, typename U>
|
||||
void pod::VaryingMesh::insert( const uf::Mesh<T, U>& mesh ) {
|
||||
get<T,U>().insert( mesh );
|
||||
updateDescriptor();
|
||||
}
|
||||
#endif
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
namespace uf {
|
||||
template<typename T = spec::Time::time_t>
|
||||
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<T>::exp_t microseconds = -6;
|
||||
static const uf::Time<T>::exp_t nanoseconds = -9;
|
||||
|
||||
UF_API_CALL Time(uf::Time<T>::time_t t = 0, uf::Time<T>::exp_t b = spec::Time::unit );
|
||||
Time(uf::Time<T>::time_t t = 0, uf::Time<T>::exp_t b = spec::Time::unit );
|
||||
|
||||
void UF_API_CALL set(uf::Time<T>::time_t t);
|
||||
void UF_API_CALL set(uf::Time<T>::time_t t, uf::Time<T>::exp_t b);
|
||||
inline void UF_API_CALL fromSeconds(uf::Time<T>::time_t t);
|
||||
inline void UF_API_CALL fromMilliseconds(uf::Time<T>::time_t t);
|
||||
inline void UF_API_CALL fromMicroseconds(uf::Time<T>::time_t t);
|
||||
inline void UF_API_CALL fromNanoseconds(uf::Time<T>::time_t t);
|
||||
void set(uf::Time<T>::time_t t);
|
||||
void set(uf::Time<T>::time_t t, uf::Time<T>::exp_t b);
|
||||
inline void fromSeconds(uf::Time<T>::time_t t);
|
||||
inline void fromMilliseconds(uf::Time<T>::time_t t);
|
||||
inline void fromMicroseconds(uf::Time<T>::time_t t);
|
||||
inline void fromNanoseconds(uf::Time<T>::time_t t);
|
||||
|
||||
uf::Time<T>::time_t UF_API_CALL get() const;
|
||||
uf::Time<T>::exp_t UF_API_CALL getBase() const;
|
||||
uf::Time<T>::time_t get() const;
|
||||
uf::Time<T>::exp_t getBase() const;
|
||||
|
||||
uf::Time<T>::time_t UF_API_CALL asBase(uf::Time<T>::exp_t base = spec::Time::unit );
|
||||
inline uf::Time<T>::time_t UF_API_CALL asSeconds();
|
||||
inline uf::Time<T>::time_t UF_API_CALL asMilliseconds();
|
||||
inline uf::Time<T>::time_t UF_API_CALL asMicroseconds();
|
||||
inline uf::Time<T>::time_t UF_API_CALL asNanoseconds();
|
||||
double UF_API_CALL asDouble();
|
||||
uf::Time<T>::time_t asBase(uf::Time<T>::exp_t base = spec::Time::unit );
|
||||
inline uf::Time<T>::time_t asSeconds();
|
||||
inline uf::Time<T>::time_t asMilliseconds();
|
||||
inline uf::Time<T>::time_t asMicroseconds();
|
||||
inline uf::Time<T>::time_t asNanoseconds();
|
||||
float asFloat();
|
||||
double asDouble();
|
||||
|
||||
uf::Time<T>& UF_API_CALL operator=( const uf::Time<T>::time_t& t );
|
||||
UF_API_CALL operator double();
|
||||
bool UF_API_CALL operator>( const uf::Time<T>::time_t& t );
|
||||
bool UF_API_CALL operator>=( const uf::Time<T>::time_t& t );
|
||||
bool UF_API_CALL operator<( const uf::Time<T>::time_t& t );
|
||||
bool UF_API_CALL operator<=( const uf::Time<T>::time_t& t );
|
||||
bool UF_API_CALL operator==( const uf::Time<T>::time_t& t );
|
||||
bool UF_API_CALL operator>( const uf::Time<T>& t );
|
||||
bool UF_API_CALL operator>=( const uf::Time<T>& t );
|
||||
bool UF_API_CALL operator<( const uf::Time<T>& t );
|
||||
bool UF_API_CALL operator<=( const uf::Time<T>& t );
|
||||
bool UF_API_CALL operator==( const uf::Time<T>& t );
|
||||
uf::Time<T> UF_API_CALL operator-( const uf::Time<T>& t );
|
||||
uf::Time<T> UF_API_CALL operator+( const uf::Time<T>& t );
|
||||
uf::Time<T>& operator=( const uf::Time<T>::time_t& t );
|
||||
operator float();
|
||||
operator double();
|
||||
bool operator>( const uf::Time<T>::time_t& t );
|
||||
bool operator>=( const uf::Time<T>::time_t& t );
|
||||
bool operator<( const uf::Time<T>::time_t& t );
|
||||
bool operator<=( const uf::Time<T>::time_t& t );
|
||||
bool operator==( const uf::Time<T>::time_t& t );
|
||||
bool operator>( const uf::Time<T>& t );
|
||||
bool operator>=( const uf::Time<T>& t );
|
||||
bool operator<( const uf::Time<T>& t );
|
||||
bool operator<=( const uf::Time<T>& t );
|
||||
bool operator==( const uf::Time<T>& t );
|
||||
uf::Time<T> operator-( const uf::Time<T>& t );
|
||||
uf::Time<T> operator+( const uf::Time<T>& t );
|
||||
};
|
||||
template<typename T = spec::Time::time_t>
|
||||
class /*UF_API*/ Timer {
|
||||
|
||||
@ -61,6 +61,10 @@ inline typename uf::Time<T>::time_t uf::Time<T>::asNanoseconds() {
|
||||
return this->asBase( uf::Time<T>::nanoseconds );
|
||||
}
|
||||
template<typename T>
|
||||
float uf::Time<T>::asFloat() {
|
||||
return this->m_time * pow(10.0f, this->m_exp);
|
||||
}
|
||||
template<typename T>
|
||||
double uf::Time<T>::asDouble() {
|
||||
return this->m_time * pow(10.0, this->m_exp);
|
||||
}
|
||||
@ -75,6 +79,10 @@ uf::Time<T>::operator double() {
|
||||
return this->asDouble();
|
||||
}
|
||||
template<typename T>
|
||||
uf::Time<T>::operator float() {
|
||||
return this->asFloat();
|
||||
}
|
||||
template<typename T>
|
||||
bool uf::Time<T>::operator>( const uf::Time<T>::time_t& t ) {
|
||||
return this->m_time > t;
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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<uf::stl::string>() == "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<bool>() ) if ( graph.lights.count(node.name) > 0 ) return;
|
||||
// if ( graph.metadata["lightmapped"].as<bool>() )
|
||||
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<bool>()) ) 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<bool>()) ) 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<float>::max() << std::endl;
|
||||
// UF_MSG_DEBUG("OVERRIDED: " << graph.settings.animations.override.a << "\t" << -std::numeric_limits<float>::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) );
|
||||
|
||||
@ -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>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<pod::DrawCommand>();
|
||||
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
|
||||
/*
|
||||
size_t primitiveID = 0;
|
||||
*/
|
||||
uf::stl::vector<uf::graph::mesh::Skinned> vertices;
|
||||
uf::stl::vector<uint32_t> 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<bool>();
|
||||
#endif
|
||||
if ( full ) {
|
||||
mesh.bind<uf::graph::mesh::Skinned, uint32_t>();
|
||||
uf::stl::vector<uf::graph::mesh::Skinned> vertices;
|
||||
uf::stl::vector<uint32_t> 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<float> floats;
|
||||
uf::stl::vector<uint16_t> ints;
|
||||
};
|
||||
struct Attribute {
|
||||
uf::stl::string name = "";
|
||||
size_t components = 1;
|
||||
uf::stl::vector<float> floats;
|
||||
uf::stl::vector<uint16_t> ints;
|
||||
};
|
||||
|
||||
uf::stl::unordered_map<uf::stl::string, Attribute> attributes = {
|
||||
{"POSITION", {}},
|
||||
{"TEXCOORD_0", {}},
|
||||
{"NORMAL", {}},
|
||||
{"TANGENT", {}},
|
||||
{"JOINTS_0", {}},
|
||||
{"WEIGHTS_0", {}},
|
||||
};
|
||||
uf::stl::unordered_map<uf::stl::string, Attribute> 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<bool>()) ){
|
||||
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<const uint16_t*>(&(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<const float*>(&(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<bool>()) ){
|
||||
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<const uint16_t*>(&(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<const float*>(&(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<uint32_t>(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<const uint32_t*>( pointer );
|
||||
COPY_INDICES()
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
|
||||
auto* buf = static_cast<const uint16_t*>( pointer );
|
||||
COPY_INDICES()
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
|
||||
auto* buf = static_cast<const uint8_t*>( 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::graph::mesh::Base, uint32_t>();
|
||||
uf::stl::vector<uf::graph::mesh::Base> vertices;
|
||||
uf::stl::vector<uint32_t> 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<float> floats;
|
||||
uf::stl::vector<uint16_t> ints;
|
||||
};
|
||||
|
||||
uf::stl::unordered_map<uf::stl::string, Attribute> 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<bool>()) ){
|
||||
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<bool>()) ){
|
||||
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<uint32_t>(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<const uint32_t*>( pointer );
|
||||
COPY_INDICES()
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
|
||||
auto* buf = static_cast<const uint16_t*>( pointer );
|
||||
COPY_INDICES()
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
|
||||
auto* buf = static_cast<const uint8_t*>( pointer );
|
||||
COPY_INDICES()
|
||||
break;
|
||||
if ( attribute.name == "JOINTS_0" ) {
|
||||
auto* buffer = reinterpret_cast<const uint16_t*>(&(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<const float*>(&(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<bool>()) ){
|
||||
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<uint32_t>(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<const uint32_t*>( pointer );
|
||||
COPY_INDICES()
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
|
||||
auto* buf = static_cast<const uint16_t*>( pointer );
|
||||
COPY_INDICES()
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
|
||||
auto* buf = static_cast<const uint8_t*>( 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();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include <uf/ext/lua/lua.h>
|
||||
#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<uf::stl::string, uf::stl::string> 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;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include <uf/utils/mesh/mesh.h>
|
||||
#include <uf/ext/meshopt/meshopt.h>
|
||||
#if UF_USE_MESHOPTIMIZER
|
||||
#include <meshoptimizer.h>
|
||||
#endif
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <uf/utils/memory/pool.h>
|
||||
#include <uf/utils/string/io.h>
|
||||
#include <uf/ext/vorbis/vorbis.h>
|
||||
#include <uf/utils/audio/audio.h>
|
||||
#include <iostream>
|
||||
|
||||
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<uf::audio::Metadata>() : 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 );
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -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<uf::stl::string>(), " ").back();
|
||||
member[key] = ext::opengl::definitionToJson(value);
|
||||
});
|
||||
// is primitive
|
||||
} else if ( !ext::json::isNull(definition["value"]) ) {
|
||||
// is array of structs
|
||||
if ( definition["struct"].as<bool>() ) {
|
||||
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<size_t>();
|
||||
|
||||
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<uf::stl::string> variableName;
|
||||
#endif
|
||||
std::function<void(const ext::json::Value&)> 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<int>(true) ) {
|
||||
size_t size = sizeof(int32_t);
|
||||
auto get = value.as<int32_t>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
// is strictly an unsigned int
|
||||
} else if ( value.is<size_t>(true) ) {
|
||||
size_t size = sizeof(uint32_t);
|
||||
auto get = value.as<uint32_t>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
// is strictly a float
|
||||
} else if ( value.is<float>(true) ) {
|
||||
size_t size = sizeof(float);
|
||||
auto get = value.as<float>();
|
||||
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<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
auto get = input.as<bool>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "int8_t" ) {
|
||||
size_t size = sizeof(int8_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
|
||||
// auto get = input.as<int8_t>();
|
||||
// memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "uint8_t" ) {
|
||||
size_t size = sizeof(uint8_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
// auto get = input.as<uint8_t>();
|
||||
// memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "int16_t" ) {
|
||||
size_t size = sizeof(int16_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
// auto get = input.as<int16_t>();
|
||||
// memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "uint16_t" ) {
|
||||
size_t size = sizeof(uint16_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
// auto get = input.as<uint16_t>();
|
||||
// memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "int32_t" ) {
|
||||
size_t size = sizeof(int32_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
auto get = input.as<int32_t>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "uint32_t" ) {
|
||||
size_t size = sizeof(uint32_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
auto get = input.as<int32_t>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "int64_t" ) {
|
||||
size_t size = sizeof(int64_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
auto get = input.as<uint64_t>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "uint64_t" ) {
|
||||
size_t size = sizeof(uint64_t); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
auto get = input.as<uint64_t>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "half" ) {
|
||||
size_t size = sizeof(float); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
// auto get = input.as<float>();
|
||||
// memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "float" ) {
|
||||
size_t size = sizeof(float); // v["size"].as<size_t>();
|
||||
if ( byteBufferEnd < byteBuffer + size ) return false; // overflow
|
||||
auto get = input.as<float>();
|
||||
memcpy( byteBuffer, &get, size );
|
||||
byteBuffer += size;
|
||||
} else if ( primitive == "double" ) {
|
||||
auto get = input.as<double>();
|
||||
size_t size = sizeof(double); // v["size"].as<size_t>();
|
||||
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<uf::stl::string> variableName;
|
||||
#endif
|
||||
std::function<void(const ext::json::Value&, const ext::json::Value&)> 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>(), " ");
|
||||
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<uf::stl::string>(), " ").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>(), " ");
|
||||
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<uf::stl::string>() << 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<size_t>() / 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
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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<ext::json::Value(spirv_cross::TypeID)> 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("["<<filename<<"] Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding));\
|
||||
@ -570,6 +578,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
const uf::stl::string name = resource.name;
|
||||
size_t size = 0; // comp.get_declared_struct_size(type);
|
||||
// generate definition to JSON
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
{
|
||||
metadata.json["definitions"]["inputs"][name]["name"] = name;
|
||||
metadata.json["definitions"]["inputs"][name]["index"] = i;
|
||||
@ -577,6 +586,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
metadata.json["definitions"]["inputs"][name]["size"] = size;
|
||||
metadata.json["definitions"]["inputs"][name]["members"] = parseMembers(resource.type_id);
|
||||
}
|
||||
#endif
|
||||
// generate definition to unordered_map
|
||||
{
|
||||
metadata.definitions.inputs[name] = Shader::Metadata::Definition::InOut{
|
||||
@ -595,6 +605,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
const uf::stl::string name = resource.name;
|
||||
size_t size = 0; // comp.get_declared_struct_size(type);
|
||||
// generate definition to JSON
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
{
|
||||
metadata.json["definitions"]["outputs"][name]["name"] = name;
|
||||
metadata.json["definitions"]["outputs"][name]["index"] = i;
|
||||
@ -602,6 +613,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
metadata.json["definitions"]["outputs"][name]["size"] = size;
|
||||
metadata.json["definitions"]["outputs"][name]["members"] = parseMembers(resource.type_id);
|
||||
}
|
||||
#endif
|
||||
// generate definition to unordered_map
|
||||
{
|
||||
metadata.definitions.outputs[name] = Shader::Metadata::Definition::InOut{
|
||||
@ -636,6 +648,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
pushConstant.create( size );
|
||||
}
|
||||
// generate definition to JSON
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
{
|
||||
metadata.json["definitions"]["pushConstants"][name]["name"] = name;
|
||||
metadata.json["definitions"]["pushConstants"][name]["index"] = pushConstants.size() - 1;
|
||||
@ -643,6 +656,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
metadata.json["definitions"]["pushConstants"][name]["size"] = size;
|
||||
metadata.json["definitions"]["pushConstants"][name]["members"] = parseMembers(resource.type_id);
|
||||
}
|
||||
#endif
|
||||
// generate definition to unordered_map
|
||||
{
|
||||
metadata.definitions.pushConstants[name] = Shader::Metadata::Definition::PushConstant{
|
||||
@ -680,26 +694,31 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
|
||||
uint8_t* s = (uint8_t*) (void*) specializationConstants;
|
||||
size_t offset = 0;
|
||||
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
metadata.json["specializationConstants"] = ext::json::array();
|
||||
#endif
|
||||
for ( const auto& constant : comp.get_specialization_constants() ) {
|
||||
const auto& value = comp.get_constant(constant.id);
|
||||
const auto& type = comp.get_type(value.constant_type);
|
||||
uf::stl::string name = comp.get_name (constant.id);
|
||||
|
||||
ext::json::Value member;
|
||||
|
||||
size_t size = 4;
|
||||
uint8_t buffer[size];
|
||||
auto& definition = metadata.definitions.specializationConstants[name];
|
||||
definition.name = name;
|
||||
definition.index = offset / size;
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
ext::json::Value member;
|
||||
#endif
|
||||
switch ( type.basetype ) {
|
||||
case spirv_cross::SPIRType::UInt: {
|
||||
auto v = value.scalar();
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
member["type"] = "uint32_t";
|
||||
member["value"] = v;
|
||||
member["validate"] = true;
|
||||
#endif
|
||||
memcpy( &buffer[0], &v, sizeof(v) );
|
||||
|
||||
definition.type = "uint32_t";
|
||||
@ -708,8 +727,10 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
} break;
|
||||
case spirv_cross::SPIRType::Int: {
|
||||
auto v = value.scalar_i32();
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
member["type"] = "int32_t";
|
||||
member["value"] = v;
|
||||
#endif
|
||||
memcpy( &buffer[0], &v, sizeof(v) );
|
||||
|
||||
definition.type = "int32_t";
|
||||
@ -718,8 +739,10 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
} break;
|
||||
case spirv_cross::SPIRType::Float: {
|
||||
auto v = value.scalar_f32();
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
member["type"] = "float";
|
||||
member["value"] = v;
|
||||
#endif
|
||||
memcpy( &buffer[0], &v, sizeof(v) );
|
||||
|
||||
definition.type = "float";
|
||||
@ -728,8 +751,10 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
} break;
|
||||
case spirv_cross::SPIRType::Boolean: {
|
||||
auto v = value.scalar()!=0;
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
member["type"] = "bool";
|
||||
member["value"] = v;
|
||||
#endif
|
||||
memcpy( &buffer[0], &v, sizeof(v) );
|
||||
|
||||
definition.type = "bool";
|
||||
@ -740,11 +765,13 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
|
||||
VK_DEBUG_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename );
|
||||
} break;
|
||||
}
|
||||
#if UF_SHADER_PARSE_AS_JSON
|
||||
member["name"] = name;
|
||||
member["size"] = size;
|
||||
member["default"] = member["value"];
|
||||
VK_DEBUG_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<uf::stl::string>() << " " << 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<uf::stl::string>() << " " << 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
|
||||
@ -2,6 +2,7 @@
|
||||
#if UF_USE_XATLAS
|
||||
#include <xatlas/xatlas.h>
|
||||
#endif
|
||||
#if 0
|
||||
pod::Vector2ui UF_API ext::xatlas::unwrap( uf::stl::vector<uf::graph::mesh::Skinned>& vertices, uf::stl::vector<uint32_t>& indices ) {
|
||||
#if UF_USE_XATLAS
|
||||
uf::stl::vector<uf::graph::mesh::Skinned> source = std::move(vertices);
|
||||
@ -41,6 +42,7 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( uf::stl::vector<uf::graph::mesh::Skin
|
||||
return size;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
#if UF_USE_XATLAS
|
||||
struct Pair {
|
||||
@ -135,11 +137,11 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
// chartOptions.useInputMeshUvs = true;
|
||||
|
||||
::xatlas::PackOptions packOptions{};
|
||||
// packOptions.bruteForce = true;
|
||||
packOptions.bruteForce = true;
|
||||
// packOptions.resolution = resolution;
|
||||
// packOptions.texelsPerUnit = 64.0f;
|
||||
// packOptions.blockAlign = true;
|
||||
// packOptions.bilinear = true;
|
||||
packOptions.blockAlign = true;
|
||||
packOptions.bilinear = true;
|
||||
|
||||
::xatlas::Generate(atlas, chartOptions, packOptions);
|
||||
|
||||
|
||||
@ -16,6 +16,14 @@ uint8_t uf::audio::buffers = 4;
|
||||
size_t uf::audio::bufferSize = 1024 * 16;
|
||||
uf::Audio uf::audio::null;
|
||||
|
||||
#if UF_AUDIO_MAPPED_VOLUMES
|
||||
uf::stl::unordered_map<uf::stl::string, float> 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 ) {
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
#include <uf/utils/math/physics.h>
|
||||
|
||||
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 <iostream>
|
||||
|
||||
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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -35,15 +35,16 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
if ( metadataJson["baking"]["resolution"].is<size_t>() )
|
||||
metadata.size = { metadataJson["baking"]["resolution"].as<size_t>(), metadataJson["baking"]["resolution"].as<size_t>() };
|
||||
|
||||
metadata.max.lights = metadataJson["baking"]["lights"].as<size_t>(metadata.max.lights);
|
||||
metadata.max.shadows = metadataJson["baking"]["shadows"].as<size_t>(metadata.max.shadows);
|
||||
|
||||
metadata.cull = metadataJson["baking"]["cull"].as<bool>();
|
||||
|
||||
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<uf::renderer::RenderTargetRenderMode>();
|
||||
@ -172,7 +173,8 @@ SAVE: {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadata = scene.getComponent<ext::ExtSceneBehavior::Metadata>();
|
||||
|
||||
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");
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<pod::Bullet>();
|
||||
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<pod::Bullet>();
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -44,7 +44,7 @@ void ext::PlayerModelBehavior::tick( uf::Object& self ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
||||
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<pod::Transform<>>();
|
||||
|
||||
/*this->*/track = serializer["track"].as<bool>();
|
||||
/*this->*/hide = serializer["hide"].as<bool>();
|
||||
/*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
|
||||
@ -57,7 +57,11 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
audio = std::move(asset);
|
||||
assetLoader.remove<uf::Audio>(filename);
|
||||
|
||||
audio.setVolume(metadataJson["volumes"]["bgm"].as<float>());
|
||||
#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<LightInfo> 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<uint32_t>(/*this->*/max.textures2D);
|
||||
/*this->*/max.texturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as<uint32_t>(/*this->*/max.texturesCube);
|
||||
/*this->*/max.textures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as<uint32_t>(/*this->*/max.textures3D);
|
||||
/*this->*/max.lights = ext::config["engine"]["scenes"]["lights"]["max"].as<uint32_t>(/*this->*/max.lights);
|
||||
/*this->*/light.max = ext::config["engine"]["scenes"]["lights"]["max"].as<uint32_t>(/*this->*/light.max);
|
||||
|
||||
/*this->*/shadow.enabled = ext::config["engine"]["scenes"]["shadows"]["enabled"].as<bool>(true) && serializer["light"]["shadows"].as<bool>(true);
|
||||
/*this->*/shadow.samples = ext::config["engine"]["scenes"]["shadows"]["samples"].as<uint32_t>();
|
||||
@ -537,8 +538,6 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
|
||||
/*this->*/light.gamma = serializer["light"]["gamma"].as<float>(2.2f);
|
||||
/*this->*/light.brightnessThreshold = serializer["light"]["brightnessThreshold"].as<float>(ext::config["engine"]["scenes"]["bloom"]["brightnessThreshold"].as<float>(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 ),
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -17,7 +17,6 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) {
|
||||
auto& sounds = emitter.get();
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sMetadata = scene.getComponent<uf::Serializer>();
|
||||
auto& assetLoader = scene.getComponent<uf::Asset>();
|
||||
|
||||
if ( !metadata["audio"]["epsilon"].is<float>() )
|
||||
@ -68,7 +67,13 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) {
|
||||
if ( json["volume"].is<double>() ) volume = json["volume"].as<float>();
|
||||
else if ( json["volume"].is<uf::stl::string>() ) {
|
||||
uf::stl::string key = json["volume"].as<uf::stl::string>();
|
||||
if ( sMetadata["volumes"][key].is<double>() ) volume = sMetadata["volumes"][key].as<float>();
|
||||
#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);
|
||||
|
||||
|
||||
54
ext/main.cpp
54
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<double>();
|
||||
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<uf::stl::string>() == "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<uf::stl::string>();
|
||||
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<uf::stl::string>();
|
||||
}
|
||||
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<uf::stl::string>();
|
||||
});
|
||||
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<uf::Asset>();
|
||||
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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user