Commit for 2020.09.07.7z
This commit is contained in:
parent
1313677a56
commit
1acffac153
2
Makefile
2
Makefile
@ -15,7 +15,7 @@ UF_LIBS =
|
||||
# EXT_LIBS = -lpng16 -lz -lassimp -lsfml-main -lsfml-system -lsfml-window -lsfml-graphics -llua52
|
||||
# EXT_LIBS = -lpng16 -lz -lassimp -ljsoncpp -lopenal32 -lalut -lvorbis -lvorbisfile -logg -lfreetype
|
||||
EXT_LIBS =
|
||||
#FLAGS = -std=c++0x -Wall -g -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENGL -DUF_USE_GLEW
|
||||
#FLAGS = -Og -DUF_DISABLE_ALIGNAS -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW
|
||||
FLAGS = -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW
|
||||
#-march=native
|
||||
LIB_NAME = uf
|
||||
|
||||
@ -3,19 +3,20 @@
|
||||
layout (binding = 1) uniform sampler2D samplerColor;
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in vec3 inPosition;
|
||||
layout (location = 1) in vec4 inColor;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inColor;
|
||||
layout (location = 3) in vec3 inPosition;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedoSpecular;
|
||||
layout (location = 1) out vec4 outPosition;
|
||||
layout (location = 2) out vec4 outNormal;
|
||||
layout (location = 1) out vec4 outNormal;
|
||||
layout (location = 2) out vec4 outPosition;
|
||||
|
||||
void main() {
|
||||
outAlbedoSpecular = texture(samplerColor, inUv);
|
||||
if ( outAlbedoSpecular.a < 0.001 ) discard;
|
||||
outAlbedoSpecular.rgb *= inColor.rgb;
|
||||
outAlbedoSpecular.a = 1;
|
||||
// outPosition = vec4(inPosition, 1.0);
|
||||
// outNormal = vec4(normalize(inNormal), 1.0);
|
||||
|
||||
outNormal = vec4(inNormal,1);
|
||||
outPosition = vec4(inPosition,1);
|
||||
}
|
||||
@ -20,9 +20,9 @@ layout (binding = 0) uniform UBO {
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec3 outPosition;
|
||||
layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out vec4 outColor;
|
||||
layout (location = 3) out vec3 outPosition;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
@ -35,9 +35,7 @@ void main() {
|
||||
|
||||
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
|
||||
// outPosition = vec3(ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
// outNormal = vec3(ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
mat4 model;
|
||||
mat4 view[2];
|
||||
mat4 projection[2];
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
Matrices matrices;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec3 outPositionEye;
|
||||
layout (location = 2) out vec3 outNormalEye;
|
||||
layout (location = 3) out vec4 outColor;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outPositionEye = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
outNormalEye = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
outColor = ubo.color;
|
||||
|
||||
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
#version 450
|
||||
|
||||
layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerOutput;
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 0) out vec4 outFragColor;
|
||||
|
||||
void main() {
|
||||
outFragColor = subpassLoad(samplerOutput);
|
||||
}
|
||||
@ -3,8 +3,7 @@
|
||||
|
||||
layout (binding = 1) uniform sampler samp;
|
||||
layout (binding = 2) uniform texture2D albedoTexture;
|
||||
layout (binding = 3) uniform texture2D positionTexture;
|
||||
layout (binding = 4) uniform texture2D normalTexture;
|
||||
layout (binding = 3) uniform texture2D normalTexture;
|
||||
|
||||
struct Cursor {
|
||||
vec2 position;
|
||||
@ -17,8 +16,7 @@ layout (location = 1) in float inAlpha;
|
||||
layout (location = 2) in Cursor inCursor;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedoSpecular;
|
||||
layout (location = 1) out vec4 outPosition;
|
||||
layout (location = 2) out vec4 outNormal;
|
||||
layout (location = 1) out vec4 outNormal;
|
||||
|
||||
void main() {
|
||||
outAlbedoSpecular = texture(sampler2D(albedoTexture, samp), inUv);
|
||||
@ -26,7 +24,6 @@ void main() {
|
||||
vec2 uv = gl_FragCoord.xy / textureSize(albedoTexture, 0);
|
||||
// uv.x = 1-uv.x;
|
||||
outAlbedoSpecular = texture(sampler2D(albedoTexture, samp), uv);
|
||||
outPosition = texture(sampler2D(positionTexture, samp), uv);
|
||||
outNormal = texture(sampler2D(normalTexture, samp), uv);
|
||||
if ( outAlbedoSpecular.a < 0.01f ) outAlbedoSpecular = vec4(0,0,0,1);
|
||||
return;
|
||||
|
||||
@ -27,7 +27,7 @@ struct Matrices {
|
||||
layout (binding = 0) uniform UBO {
|
||||
Matrices matrices;
|
||||
Cursor cursor;
|
||||
float alpha;
|
||||
vec2 alpha;
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
|
||||
@ -1,22 +1,29 @@
|
||||
#version 450
|
||||
|
||||
#define BASE_LIGHTS_SIZE 16
|
||||
layout (constant_id = 0) const uint LIGHTS = BASE_LIGHTS_SIZE;
|
||||
|
||||
layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedo;
|
||||
layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerPosition;
|
||||
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerNormal;
|
||||
layout (input_attachment_index = 0, binding = 4) uniform subpassInput samplerDepth;
|
||||
layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormal;
|
||||
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerPosition;
|
||||
// layout (input_attachment_index = 0, binding = 4) uniform subpassInput samplerDepth;
|
||||
layout (binding = 5) uniform sampler2D samplerShadows[BASE_LIGHTS_SIZE];
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in flat uint inPushConstantPass;
|
||||
|
||||
layout (location = 0) out vec4 outFragColor;
|
||||
|
||||
layout (constant_id = 0) const uint LIGHTS = 32;
|
||||
|
||||
struct Light {
|
||||
vec3 position;
|
||||
float power;
|
||||
vec3 color;
|
||||
float radius;
|
||||
int type;
|
||||
int shadowed;
|
||||
mat4 view;
|
||||
mat4 projection;
|
||||
};
|
||||
|
||||
struct Matrices {
|
||||
@ -78,31 +85,117 @@ void phong( Light light, vec4 albedoSpecular, inout vec3 i ) {
|
||||
i += Id * light.power;
|
||||
}
|
||||
|
||||
bool debugShadow( Light light, uint i ) {
|
||||
return false;
|
||||
|
||||
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
|
||||
positionClip.xyz /= positionClip.w;
|
||||
float lightDepth = texture(samplerShadows[i], positionClip.xy * 0.5 + 0.5).r;
|
||||
|
||||
float eyeDepth = positionClip.z;
|
||||
eyeDepth = lightDepth;
|
||||
float bias = 0.0005;
|
||||
|
||||
if ( positionClip.x < -1 || positionClip.x >= 1 ) eyeDepth = 1;
|
||||
else if ( positionClip.y < -1 || positionClip.y >= 1 ) eyeDepth = 1;
|
||||
else if ( positionClip.z < 0 || positionClip.z >= 1 ) eyeDepth = 1;
|
||||
// else eyeDepth /= 0.00526;
|
||||
|
||||
outFragColor.rgb = vec3( 1 - eyeDepth );
|
||||
outFragColor.a = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float shadowFactor( Light light, uint i ) {
|
||||
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
|
||||
positionClip.xyz /= positionClip.w;
|
||||
float lightDepth = texture(samplerShadows[i], positionClip.xy * 0.5 + 0.5).r;
|
||||
float eyeDepth = positionClip.z;
|
||||
float bias = 0.0005;
|
||||
// bias = max(0.05 * (1.0 - dot(normal.eye, light.position.xyz - position.eye)), bias);
|
||||
|
||||
// eyeDepth /= 0.00526;
|
||||
// lightDepth /= 0.00526;
|
||||
|
||||
eyeDepth = 1 - eyeDepth;
|
||||
lightDepth = 1 - lightDepth;
|
||||
|
||||
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
|
||||
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
|
||||
if ( positionClip.z < 0 || positionClip.z >= 1 ) return 0.0;
|
||||
|
||||
return eyeDepth - bias < lightDepth ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 albedoSpecular = subpassLoad(samplerAlbedo);
|
||||
position.eye = subpassLoad(samplerPosition).rgb;
|
||||
normal.eye = subpassLoad(samplerNormal).rgb;
|
||||
position.eye = subpassLoad(samplerPosition).rgb;
|
||||
|
||||
{
|
||||
float depth = subpassLoad(samplerDepth).r;
|
||||
mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] );
|
||||
vec4 positionWorld = iView * vec4(position.eye, 1);
|
||||
position.world = positionWorld.xyz;
|
||||
}
|
||||
/*
|
||||
{
|
||||
mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] );
|
||||
mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] );
|
||||
|
||||
float depth = subpassLoad(samplerDepth).r;
|
||||
|
||||
if ( false ) {
|
||||
depth /= 0.00526;
|
||||
outFragColor.rgb = vec3( 1 - depth );
|
||||
outFragColor.a = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0);
|
||||
positionClip.y *= -1;
|
||||
vec4 positionEye = iProj * positionClip;
|
||||
positionEye /= positionEye.w;
|
||||
position.eye = positionEye.xyz;
|
||||
|
||||
vec4 positionWorld = iView * positionEye;
|
||||
position.world = positionWorld.xyz;
|
||||
}
|
||||
*/
|
||||
|
||||
vec3 fragColor = albedoSpecular.rgb * ubo.ambient.rgb;
|
||||
bool lit = false;
|
||||
for ( uint i = 0; i < LIGHTS; ++i ) {
|
||||
Light light = ubo.lights[i];
|
||||
|
||||
if ( light.power <= 0.001 ) continue;
|
||||
lit = true;
|
||||
|
||||
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
|
||||
|
||||
if ( light.shadowed > 0 ) {
|
||||
float shadowFactor = shadowFactor( light, i );
|
||||
if ( shadowFactor <= 0.0001 ) continue;
|
||||
}
|
||||
phong( light, albedoSpecular, fragColor );
|
||||
}
|
||||
|
||||
if ( !lit ) fragColor = albedoSpecular.rgb;
|
||||
|
||||
fog(fragColor);
|
||||
|
||||
outFragColor = vec4(fragColor,1);
|
||||
/*
|
||||
if ( !false ) {
|
||||
float depth = texture(samplerShadows[0], inUv).r;
|
||||
depth /= 0.00526;
|
||||
outFragColor = vec4( vec3(1 - depth), 1 );
|
||||
return;
|
||||
} else if ( !false ) {
|
||||
outFragColor = vec4( texture(samplerShadows[0], inUv).rgb, 1 );
|
||||
return;
|
||||
} else {
|
||||
outFragColor = vec4( inUv.x, 0, inUv.y, 1 );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@ -3,19 +3,17 @@
|
||||
layout (binding = 1) uniform sampler2D samplerColor;
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in vec3 inPosition;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inColor;
|
||||
layout (location = 1) in vec3 inNormal;
|
||||
layout (location = 2) in vec4 inColor;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedoSpecular;
|
||||
layout (location = 1) out vec4 outPosition;
|
||||
layout (location = 2) out vec4 outNormal;
|
||||
layout (location = 1) out vec4 outNormal;
|
||||
|
||||
void main() {
|
||||
outAlbedoSpecular = texture(samplerColor, inUv);
|
||||
outAlbedoSpecular = vec4(1,1,1,1);
|
||||
outAlbedoSpecular.rgb *= inColor.rgb;
|
||||
outAlbedoSpecular.a = 1;
|
||||
outPosition = vec4(inPosition, 1.0);
|
||||
// outPosition = vec4(inPosition, 1.0);
|
||||
outNormal = vec4(normalize(inNormal), 1.0);
|
||||
}
|
||||
@ -21,9 +21,8 @@ layout (binding = 0) uniform UBO {
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec3 outPosition;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out vec4 outColor;
|
||||
layout (location = 1) out vec3 outNormal;
|
||||
layout (location = 2) out vec4 outColor;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
@ -34,7 +33,7 @@ void main() {
|
||||
outUv = inUv;
|
||||
// outColor = ubo.color;
|
||||
|
||||
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
// outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
|
||||
// outPosition = vec3(ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 inPosition;
|
||||
layout (location = 1) in vec3 inColor;
|
||||
layout (location = 0) in vec3 inColor;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedoSpecular;
|
||||
|
||||
|
||||
@ -17,8 +17,7 @@ layout (binding = 0) uniform UBO {
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec3 outPosition;
|
||||
layout (location = 1) out vec4 outColor;
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
@ -28,7 +27,7 @@ out gl_PerVertex {
|
||||
void main() {
|
||||
outColor = ubo.color;
|
||||
|
||||
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
// outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
|
||||
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
|
||||
}
|
||||
@ -3,18 +3,18 @@
|
||||
layout (binding = 1) uniform sampler2D samplerColor;
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in vec3 inPosition;
|
||||
layout (location = 1) in vec4 inColor;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inColor;
|
||||
layout (location = 3) in vec3 inPosition;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedoSpecular;
|
||||
layout (location = 1) out vec4 outPosition;
|
||||
layout (location = 2) out vec4 outNormal;
|
||||
layout (location = 1) out vec4 outNormal;
|
||||
layout (location = 2) out vec4 outPosition;
|
||||
|
||||
void main() {
|
||||
outAlbedoSpecular = texture(samplerColor, inUv);
|
||||
outAlbedoSpecular.rgb *= inColor.rgb;
|
||||
// outAlbedoSpecular.rgb *= inColor.rgb;
|
||||
outAlbedoSpecular.a = 1;
|
||||
outPosition = vec4(inPosition, 1.0);
|
||||
outNormal = vec4(normalize(inNormal), 1.0);
|
||||
outNormal = vec4(inNormal,1);
|
||||
outPosition = vec4(inPosition,1);
|
||||
}
|
||||
@ -21,9 +21,9 @@ layout (binding = 0) uniform UBO {
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec3 outPosition;
|
||||
layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out vec4 outColor;
|
||||
layout (location = 3) out vec3 outPosition;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
@ -36,9 +36,7 @@ void main() {
|
||||
|
||||
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
|
||||
// outPosition = vec3(ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
// outNormal = vec3(ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
outColor.a = (inColor >> 24u) & 0xFF;
|
||||
outColor.b = (inColor >> 16u) & 0xFF;
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in uint inColor;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
mat4 model;
|
||||
mat4 view[2];
|
||||
mat4 projection[2];
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
Matrices matrices;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec3 outPositionEye;
|
||||
layout (location = 2) out vec3 outNormalEye;
|
||||
layout (location = 3) out vec4 outColor;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outPositionEye = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
outNormalEye = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
// outColor = ubo.color;
|
||||
|
||||
outColor.a = (inColor >> 24u) & 0xFF;
|
||||
outColor.b = (inColor >> 16u) & 0xFF;
|
||||
outColor.g = (inColor >> 8u) & 0xFF;
|
||||
outColor.r = (inColor ) & 0xFF;
|
||||
outColor.rgb /= 256.0;
|
||||
outColor.a = 0.5;
|
||||
|
||||
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
|
||||
}
|
||||
20406
engine/inc/gltf/json.hpp
Normal file
20406
engine/inc/gltf/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
7530
engine/inc/gltf/stb_image.h
Normal file
7530
engine/inc/gltf/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
1621
engine/inc/gltf/stb_image_write.h
Normal file
1621
engine/inc/gltf/stb_image_write.h
Normal file
File diff suppressed because it is too large
Load Diff
7639
engine/inc/gltf/tiny_gltf.h
Normal file
7639
engine/inc/gltf/tiny_gltf.h
Normal file
File diff suppressed because it is too large
Load Diff
17
engine/inc/uf/ext/gltf/gltf.h
Normal file
17
engine/inc/uf/ext/gltf/gltf.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/engine/object/object.h>
|
||||
|
||||
namespace ext {
|
||||
namespace gltf {
|
||||
enum LoadMode {
|
||||
GENERATE_NORMALS = 0x1 << 0,
|
||||
APPLY_TRANSFORMS = 0x1 << 1,
|
||||
SEPARATE_MESHES = 0x1 << 2,
|
||||
RENDER = 0x1 << 3,
|
||||
COLLISION = 0x1 << 4,
|
||||
AABB = 0x1 << 5,
|
||||
};
|
||||
bool UF_API load( uf::Object&, const std::string&, uint8_t = LoadMode::GENERATE_NORMALS | LoadMode::RENDER );
|
||||
}
|
||||
}
|
||||
@ -35,6 +35,7 @@ namespace ext {
|
||||
extern UF_API float width, height;
|
||||
extern UF_API bool enabled;
|
||||
extern UF_API bool swapEyes;
|
||||
extern UF_API uint8_t dominantEye;
|
||||
|
||||
bool UF_API initialize( int stage = 0 );
|
||||
void UF_API tick();
|
||||
|
||||
@ -16,6 +16,7 @@ namespace ext {
|
||||
VkImageView view;
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocationInfo;
|
||||
VkPipelineColorBlendAttachmentState blendState;
|
||||
} Attachment;
|
||||
std::vector<Attachment> attachments;
|
||||
|
||||
@ -38,7 +39,7 @@ namespace ext {
|
||||
void initialize( Device& device );
|
||||
void destroy();
|
||||
void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector<size_t>&, const std::vector<size_t>&, size_t );
|
||||
size_t attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, Attachment* attachment = NULL );
|
||||
size_t attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, bool blend = false, Attachment* attachment = NULL );
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -11,10 +11,29 @@ namespace ext {
|
||||
Device* device = NULL;
|
||||
|
||||
VkSampler sampler;
|
||||
VkDescriptorImageInfo descriptor;
|
||||
VkFilter filter = VK_FILTER_LINEAR;
|
||||
struct {
|
||||
struct {
|
||||
VkFilter min = VK_FILTER_LINEAR;
|
||||
VkFilter mag = VK_FILTER_LINEAR;
|
||||
} filter;
|
||||
struct {
|
||||
VkSamplerAddressMode u = VK_SAMPLER_ADDRESS_MODE_REPEAT, v = VK_SAMPLER_ADDRESS_MODE_REPEAT, w = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
} addressMode;
|
||||
struct {
|
||||
VkSamplerMipmapMode mode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
float lodBias = 0.0f;
|
||||
} mip;
|
||||
VkCompareOp compareOp = VK_COMPARE_OP_NEVER;
|
||||
struct {
|
||||
float min = 0.0f;
|
||||
float max = 0.0f;
|
||||
} lod;
|
||||
float maxAnisotropy;
|
||||
|
||||
void initialize( Device& device, VkFilter filter = VK_FILTER_LINEAR );
|
||||
VkDescriptorImageInfo info;
|
||||
} descriptor;
|
||||
|
||||
void initialize( Device& device );
|
||||
void destroy();
|
||||
};
|
||||
struct UF_API Texture {
|
||||
@ -59,6 +78,7 @@ namespace ext {
|
||||
);
|
||||
};
|
||||
struct UF_API Texture2D : public Texture {
|
||||
static Texture2D empty;
|
||||
void loadFromFile(
|
||||
std::string filename,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
@ -99,7 +119,6 @@ namespace ext {
|
||||
uint32_t texHeight,
|
||||
Device& device,
|
||||
VkQueue copyQueue,
|
||||
VkFilter filter = VK_FILTER_LINEAR,
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
|
||||
@ -43,6 +43,8 @@ namespace ext {
|
||||
extern UF_API uint32_t height;
|
||||
|
||||
extern UF_API bool validation;
|
||||
extern UF_API std::vector<std::string> validationFilters;
|
||||
extern UF_API std::vector<std::string> requestedDeviceFeatures;
|
||||
extern UF_API Device device;
|
||||
typedef VmaAllocator Allocator;
|
||||
extern UF_API Allocator allocator;
|
||||
|
||||
@ -22,6 +22,7 @@ namespace uf {
|
||||
} perspective;
|
||||
int mode;
|
||||
pod::Vector3 offset;
|
||||
bool stereoscopic = false;
|
||||
} m_settings;
|
||||
struct {
|
||||
struct {
|
||||
@ -38,6 +39,7 @@ namespace uf {
|
||||
Camera( const Camera& copy );
|
||||
*/
|
||||
bool modified() const;
|
||||
void setStereoscopic( bool );
|
||||
pod::Transform<>& getTransform();
|
||||
const pod::Transform<>& getTransform() const;
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ namespace uf {
|
||||
~Image();
|
||||
void clear(); // empties pixel container
|
||||
// Getters
|
||||
void loadFromBuffer( const Image::pixel_t::type_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels );
|
||||
void loadFromBuffer( const Image::pixel_t::type_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip = false );
|
||||
void loadFromBuffer( const Image::container_t& container, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip = false );
|
||||
std::string getFilename() const;
|
||||
Image::container_t& getPixels();
|
||||
|
||||
@ -2,157 +2,29 @@
|
||||
|
||||
#include <uf/config.h>
|
||||
|
||||
#include <uf/utils/math/vector.h>
|
||||
#include <functional>
|
||||
#include "./collision/gjk.h"
|
||||
#include "./collision/boundingbox.h"
|
||||
#include "./collision/sphere.h"
|
||||
#include "./collision/mesh.h"
|
||||
#include <vector>
|
||||
|
||||
// #include <uf/gl/mesh/mesh.h>
|
||||
namespace pod {
|
||||
struct UF_API Simplex {
|
||||
public:
|
||||
struct UF_API SupportPoint {
|
||||
pod::Vector3 a, b, v;
|
||||
bool operator==( const pod::Simplex::SupportPoint& r ) const {
|
||||
return v == r.v;
|
||||
}
|
||||
pod::Vector3 operator-( const pod::Simplex::SupportPoint& r ) const {
|
||||
return v - r.v;
|
||||
}
|
||||
pod::Vector3 operator*( float r ) const {
|
||||
return v * r;
|
||||
}
|
||||
pod::Vector3 operator-( const pod::Vector3& r ) const {
|
||||
return v - r;
|
||||
}
|
||||
float dot( const pod::Vector3& r ) const {
|
||||
return uf::vector::dot(v, r);
|
||||
}
|
||||
pod::Vector3 cross( const pod::Simplex::SupportPoint& r ) const {
|
||||
return uf::vector::cross(v, r.v);
|
||||
}
|
||||
pod::Vector3 cross( const pod::Vector3& r ) const {
|
||||
return uf::vector::cross(v, r);
|
||||
}
|
||||
};
|
||||
int size = 0;
|
||||
pod::Simplex::SupportPoint b, c, d;
|
||||
/* pod::Vector3 b, c, d;
|
||||
Simplex( const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3() );
|
||||
void add( const pod::Vector3& );
|
||||
void set( const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3() );
|
||||
*/
|
||||
};
|
||||
}
|
||||
namespace uf {
|
||||
class UF_API Collider {
|
||||
public:
|
||||
typedef std::vector<pod::Collider*> container_t;
|
||||
protected:
|
||||
uf::Collider::container_t m_container;
|
||||
public:
|
||||
struct UF_API Manifold {
|
||||
const uf::Collider* a;
|
||||
const uf::Collider* b;
|
||||
pod::Vector3 normal;
|
||||
float depth;
|
||||
bool colliding;
|
||||
|
||||
Manifold() {
|
||||
this->normal = pod::Vector3{0.0f, 0.0f, 0.0f};
|
||||
this->depth = -0.1f;
|
||||
this->colliding = false;
|
||||
}
|
||||
Manifold( const uf::Collider& a, const uf::Collider& b ) {
|
||||
this->a = &a;
|
||||
this->b = &b;
|
||||
this->normal = pod::Vector3{0.0f, 0.0f, 0.0f};
|
||||
this->depth = -0.1f;
|
||||
this->colliding = false;
|
||||
}
|
||||
Manifold( const uf::Collider& a, const uf::Collider& b, const pod::Vector3& normal, float depth, bool colliding ) {
|
||||
this->a = &a;
|
||||
this->b = &b;
|
||||
this->normal = normal;
|
||||
this->depth = depth;
|
||||
this->colliding = colliding;
|
||||
}
|
||||
};
|
||||
virtual ~Collider();
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const = 0;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const = 0;
|
||||
virtual uf::Collider::Manifold intersects( const uf::Collider& ) const;
|
||||
};
|
||||
|
||||
class UF_API AABBox : public uf::Collider {
|
||||
protected:
|
||||
pod::Vector3 m_origin;
|
||||
pod::Vector3 m_corner;
|
||||
public:
|
||||
AABBox( const pod::Vector3&, const pod::Vector3& );
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const;
|
||||
virtual uf::Collider::Manifold intersects( const uf::AABBox& ) const;
|
||||
};
|
||||
class UF_API SphereCollider : public uf::Collider {
|
||||
protected:
|
||||
float m_radius;
|
||||
pod::Vector3 m_origin;
|
||||
public:
|
||||
SphereCollider( float = 1.0f, const pod::Vector3& = pod::Vector3{} );
|
||||
|
||||
float getRadius() const;
|
||||
const pod::Vector3& getOrigin() const;
|
||||
|
||||
void setRadius( float = 1.0f );
|
||||
void setOrigin( const pod::Vector3& );
|
||||
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const;
|
||||
virtual uf::Collider::Manifold intersects( const uf::SphereCollider& ) const;
|
||||
};
|
||||
|
||||
class UF_API ModularCollider : public uf::Collider {
|
||||
public:
|
||||
typedef std::function<pod::Vector3*()> function_expand_t;
|
||||
typedef std::function<pod::Vector3(const pod::Vector3&)> function_support_t;
|
||||
protected:
|
||||
uint m_len;
|
||||
pod::Vector3* m_container;
|
||||
|
||||
bool m_should_free;
|
||||
|
||||
uf::ModularCollider::function_expand_t m_function_expand;
|
||||
uf::ModularCollider::function_support_t m_function_support;
|
||||
public:
|
||||
ModularCollider( uint len = 0, pod::Vector3* = NULL, bool = false, const uf::ModularCollider::function_expand_t& = NULL, const uf::ModularCollider::function_support_t& = NULL );
|
||||
~ModularCollider();
|
||||
|
||||
void setExpand( const uf::ModularCollider::function_expand_t& = NULL );
|
||||
void setSupport( const uf::ModularCollider::function_support_t& = NULL );
|
||||
|
||||
pod::Vector3* getContainer();
|
||||
uint getSize() const;
|
||||
void setContainer( pod::Vector3*, uint );
|
||||
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const;
|
||||
};
|
||||
class UF_API CollisionBody {
|
||||
public:
|
||||
typedef std::vector<uf::Collider*> container_t;
|
||||
protected:
|
||||
uf::CollisionBody::container_t m_container;
|
||||
public:
|
||||
~CollisionBody();
|
||||
~Collider();
|
||||
void clear();
|
||||
|
||||
void add( uf::Collider* );
|
||||
uf::CollisionBody::container_t& getContainer();
|
||||
const uf::CollisionBody::container_t& getContainer() const;
|
||||
void add( pod::Collider* );
|
||||
uf::Collider::container_t& getContainer();
|
||||
const uf::Collider::container_t& getContainer() const;
|
||||
|
||||
std::size_t getSize() const;
|
||||
|
||||
std::vector<uf::Collider::Manifold> intersects( const uf::CollisionBody& ) const;
|
||||
std::vector<uf::Collider::Manifold> intersects( const uf::Collider& ) const;
|
||||
std::vector<pod::Collider::Manifold> intersects( const uf::Collider&, bool = false ) const;
|
||||
std::vector<pod::Collider::Manifold> intersects( const pod::Collider&, bool = false ) const;
|
||||
};
|
||||
}
|
||||
27
engine/inc/uf/utils/math/collision/boundingbox.h
Normal file
27
engine/inc/uf/utils/math/collision/boundingbox.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "gjk.h"
|
||||
|
||||
namespace uf {
|
||||
class UF_API BoundingBox : public pod::Collider {
|
||||
protected:
|
||||
pod::Vector3 m_origin;
|
||||
pod::Vector3 m_corner;
|
||||
public:
|
||||
BoundingBox( const pod::Vector3& = {}, const pod::Vector3& = {} );
|
||||
|
||||
const pod::Vector3& getOrigin() const;
|
||||
const pod::Vector3& getCorner() const;
|
||||
void setOrigin( const pod::Vector3& );
|
||||
void setCorner( const pod::Vector3& );
|
||||
|
||||
pod::Vector3 min() const;
|
||||
pod::Vector3 max() const;
|
||||
pod::Vector3 closest( const pod::Vector3f& ) const;
|
||||
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const;
|
||||
virtual pod::Collider::Manifold intersects( const uf::BoundingBox& ) const;
|
||||
};
|
||||
}
|
||||
88
engine/inc/uf/utils/math/collision/gjk.h
Normal file
88
engine/inc/uf/utils/math/collision/gjk.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/config.h>
|
||||
|
||||
#include <uf/utils/math/vector.h>
|
||||
#include <uf/utils/math/transform.h>
|
||||
|
||||
namespace pod {
|
||||
struct UF_API Simplex {
|
||||
public:
|
||||
struct UF_API SupportPoint {
|
||||
pod::Vector3 a, b, v;
|
||||
bool operator==( const pod::Simplex::SupportPoint& r ) const {
|
||||
return v == r.v;
|
||||
}
|
||||
pod::Vector3 operator-( const pod::Simplex::SupportPoint& r ) const {
|
||||
return v - r.v;
|
||||
}
|
||||
pod::Vector3 operator*( float r ) const {
|
||||
return v * r;
|
||||
}
|
||||
pod::Vector3 operator-( const pod::Vector3& r ) const {
|
||||
return v - r;
|
||||
}
|
||||
float dot( const pod::Vector3& r ) const {
|
||||
return uf::vector::dot(v, r);
|
||||
}
|
||||
pod::Vector3 cross( const pod::Simplex::SupportPoint& r ) const {
|
||||
return uf::vector::cross(v, r.v);
|
||||
}
|
||||
pod::Vector3 cross( const pod::Vector3& r ) const {
|
||||
return uf::vector::cross(v, r);
|
||||
}
|
||||
};
|
||||
int size = 0;
|
||||
pod::Simplex::SupportPoint b, c, d;
|
||||
/*
|
||||
pod::Vector3 b, c, d;
|
||||
Simplex( const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3() );
|
||||
void add( const pod::Vector3& );
|
||||
void set( const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3(), const pod::Vector3& = pod::Vector3() );
|
||||
*/
|
||||
};
|
||||
}
|
||||
namespace pod {
|
||||
class UF_API Collider {
|
||||
protected:
|
||||
pod::Transform<> m_transform;
|
||||
public:
|
||||
struct UF_API Manifold {
|
||||
const pod::Collider* a;
|
||||
const pod::Collider* b;
|
||||
pod::Vector3 normal;
|
||||
float depth;
|
||||
bool colliding;
|
||||
|
||||
Manifold() {
|
||||
this->normal = pod::Vector3{0.0f, 0.0f, 0.0f};
|
||||
this->depth = -0.1f;
|
||||
this->colliding = false;
|
||||
}
|
||||
Manifold( const pod::Collider& a, const pod::Collider& b ) {
|
||||
this->a = &a;
|
||||
this->b = &b;
|
||||
this->normal = pod::Vector3{0.0f, 0.0f, 0.0f};
|
||||
this->depth = -0.1f;
|
||||
this->colliding = false;
|
||||
}
|
||||
Manifold( const pod::Collider& a, const pod::Collider& b, const pod::Vector3& normal, float depth, bool colliding ) {
|
||||
this->a = &a;
|
||||
this->b = &b;
|
||||
this->normal = normal;
|
||||
this->depth = depth;
|
||||
this->colliding = colliding;
|
||||
}
|
||||
};
|
||||
virtual ~Collider();
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const = 0;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const = 0;
|
||||
virtual pod::Collider::Manifold intersects( const pod::Collider& ) const;
|
||||
|
||||
pod::Vector3f getPosition() const;
|
||||
pod::Transform<>& getTransform();
|
||||
const pod::Transform<>& getTransform() const;
|
||||
void setTransform( const pod::Transform<>& );
|
||||
};
|
||||
}
|
||||
33
engine/inc/uf/utils/math/collision/mesh.h
Normal file
33
engine/inc/uf/utils/math/collision/mesh.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "gjk.h"
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
|
||||
namespace uf {
|
||||
class UF_API MeshCollider : public pod::Collider {
|
||||
protected:
|
||||
std::vector<pod::Vector3> m_positions;
|
||||
public:
|
||||
MeshCollider( const pod::Transform<>& = {}, const std::vector<pod::Vector3>& = {} );
|
||||
|
||||
std::vector<pod::Vector3>& getPositions();
|
||||
const std::vector<pod::Vector3>& getPositions() const;
|
||||
|
||||
void setPositions( const std::vector<pod::Vector3>& );
|
||||
|
||||
template<typename T, typename U>
|
||||
void setPositions( const uf::BaseMesh<T, U>& mesh ) {
|
||||
this->m_positions.clear();
|
||||
this->m_positions.reserve( std::max( mesh.vertices.size(), mesh.indices.size() ) );
|
||||
if ( !mesh.indices.empty() ) {
|
||||
for ( auto& index : mesh.indices ) this->m_positions.push_back( mesh.vertices[index].position );
|
||||
} else {
|
||||
for ( auto& vertex : mesh.vertices ) this->m_positions.push_back( vertex.position );
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const;
|
||||
};
|
||||
}
|
||||
34
engine/inc/uf/utils/math/collision/modular.h
Normal file
34
engine/inc/uf/utils/math/collision/modular.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "gjk.h"
|
||||
#include <functional>
|
||||
|
||||
namespace uf {
|
||||
class UF_API ModularCollider : public pod::Collider {
|
||||
public:
|
||||
typedef std::function<pod::Vector3*()> function_expand_t;
|
||||
typedef std::function<pod::Vector3(const pod::Vector3&)> function_support_t;
|
||||
protected:
|
||||
uint m_len;
|
||||
pod::Vector3* m_container;
|
||||
|
||||
bool m_should_free;
|
||||
|
||||
uf::ModularCollider::function_expand_t m_function_expand;
|
||||
uf::ModularCollider::function_support_t m_function_support;
|
||||
public:
|
||||
ModularCollider( uint len = 0, pod::Vector3* = NULL, bool = false, const uf::ModularCollider::function_expand_t& = NULL, const uf::ModularCollider::function_support_t& = NULL );
|
||||
~ModularCollider();
|
||||
|
||||
void setExpand( const uf::ModularCollider::function_expand_t& = NULL );
|
||||
void setSupport( const uf::ModularCollider::function_support_t& = NULL );
|
||||
|
||||
pod::Vector3* getContainer();
|
||||
uint getSize() const;
|
||||
void setContainer( pod::Vector3*, uint );
|
||||
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const;
|
||||
};
|
||||
}
|
||||
24
engine/inc/uf/utils/math/collision/sphere.h
Normal file
24
engine/inc/uf/utils/math/collision/sphere.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "gjk.h"
|
||||
|
||||
namespace uf {
|
||||
class UF_API SphereCollider : public pod::Collider {
|
||||
protected:
|
||||
float m_radius;
|
||||
pod::Vector3 m_origin;
|
||||
public:
|
||||
SphereCollider( float = 1.0f, const pod::Vector3& = pod::Vector3{} );
|
||||
|
||||
float getRadius() const;
|
||||
const pod::Vector3& getOrigin() const;
|
||||
|
||||
void setRadius( float = 1.0f );
|
||||
void setOrigin( const pod::Vector3& );
|
||||
|
||||
virtual std::string type() const;
|
||||
virtual pod::Vector3* expand() const;
|
||||
virtual pod::Vector3 support( const pod::Vector3& ) const;
|
||||
virtual pod::Collider::Manifold intersects( const uf::SphereCollider& ) const;
|
||||
};
|
||||
}
|
||||
@ -21,8 +21,11 @@ namespace pod {
|
||||
namespace uf {
|
||||
namespace physics {
|
||||
namespace time {
|
||||
UF_API uf::Timer<> timer;
|
||||
UF_API double current, previous, delta, clamp;
|
||||
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;
|
||||
}
|
||||
void UF_API tick();
|
||||
template<typename T> pod::Transform<T>& update( pod::Transform<T>& transform, pod::Physics& physics );
|
||||
|
||||
@ -214,8 +214,7 @@ std::string uf::Asset::load( const std::string& uri ) {
|
||||
uf::Serializer& json = container.emplace_back();
|
||||
json.readFromFile(filename);
|
||||
} else {
|
||||
uf::iostream << "Failed to load `" + filename + "`: Unimplemented extension: " + extension << "\n";
|
||||
return "";
|
||||
uf::iostream << "Failed to parse `" + filename + "`: Unimplemented extension: " + extension << "\n";
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
@ -3,6 +3,11 @@
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/utils/time/time.h>
|
||||
#include <uf/utils/math/transform.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
|
||||
namespace {
|
||||
uf::Timer<long long> timer(false);
|
||||
@ -14,6 +19,7 @@ namespace {
|
||||
if ( filename.substr(0,9) == "/smtsamo/" ) root = "./data/";
|
||||
else if ( extension == "json" ) root = "./data/entities/";
|
||||
else if ( extension == "png" ) root = "./data/textures/";
|
||||
else if ( extension == "glb" ) root = "./data/models/";
|
||||
else if ( extension == "ogg" ) root = "./data/audio/";
|
||||
}
|
||||
return uf::string::sanitize(filename, root);
|
||||
@ -23,6 +29,33 @@ namespace {
|
||||
UF_OBJECT_REGISTER_CPP(Object)
|
||||
void uf::Object::initialize() {
|
||||
uf::Entity::initialize();
|
||||
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
if ( metadata["system"]["type"].isNull() || metadata["system"]["defaults"]["asset load"].asBool() ) {
|
||||
// Default load: GLTF model
|
||||
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
std::string filename = json["filename"].asString();
|
||||
|
||||
if ( uf::string::extension(filename) != "glb" ) return "false";
|
||||
int8_t LOAD_FLAGS = 0;
|
||||
if ( metadata["model"]["flags"]["GENERATE_NORMALS"].asBool() )
|
||||
LOAD_FLAGS |= ext::gltf::LoadMode::GENERATE_NORMALS; // 0x1 << 0;
|
||||
if ( metadata["model"]["flags"]["APPLY_TRANSFORMS"].asBool() )
|
||||
LOAD_FLAGS |= ext::gltf::LoadMode::APPLY_TRANSFORMS; // 0x1 << 1;
|
||||
if ( metadata["model"]["flags"]["SEPARATE_MESHES"].asBool() )
|
||||
LOAD_FLAGS |= ext::gltf::LoadMode::SEPARATE_MESHES; // 0x1 << 2;
|
||||
if ( metadata["model"]["flags"]["RENDER"].asBool() )
|
||||
LOAD_FLAGS |= ext::gltf::LoadMode::RENDER; // 0x1 << 3;
|
||||
if ( metadata["model"]["flags"]["COLLISION"].asBool() )
|
||||
LOAD_FLAGS |= ext::gltf::LoadMode::COLLISION; // 0x1 << 4;
|
||||
if ( metadata["model"]["flags"]["AABB"].asBool() )
|
||||
LOAD_FLAGS |= ext::gltf::LoadMode::AABB; // 0x1 << 5;
|
||||
|
||||
ext::gltf::load( *this, filename, LOAD_FLAGS );
|
||||
return "true";
|
||||
});
|
||||
}
|
||||
}
|
||||
void uf::Object::destroy() {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
@ -41,10 +74,14 @@ void uf::Object::tick() {
|
||||
// listen for metadata file changes
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
if ( metadata["system"]["hot reload"]["enabled"].asBool() ) {
|
||||
/*
|
||||
std::string filename = "./entities/"+metadata["system"]["source"].asString();
|
||||
std::string root = "./data/" + uf::string::directory(filename);
|
||||
size_t mtime = uf::string::mtime( root + uf::string::filename(filename) );
|
||||
*/
|
||||
size_t mtime = uf::string::mtime( metadata["system"]["source"].asString() );
|
||||
if ( metadata["system"]["hot reload"]["mtime"].asUInt64() < mtime ) {
|
||||
std::cout << metadata["system"]["hot reload"]["mtime"] << ": " << mtime << std::endl;
|
||||
metadata["system"]["hot reload"]["mtime"] = mtime;
|
||||
this->reload();
|
||||
//this->queueHook("metadata:Reload.%UID%");
|
||||
@ -71,6 +108,32 @@ void uf::Object::tick() {
|
||||
}
|
||||
void uf::Object::render() {
|
||||
uf::Entity::render();
|
||||
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
if ( metadata["system"]["type"].isNull() || metadata["system"]["defaults"]["render"].asBool() ) {
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& transform = this->getComponent<pod::Transform<>>();
|
||||
auto& camera = scene.getController()->getComponent<uf::Camera>();
|
||||
|
||||
if ( !graphic.initialized ) return;
|
||||
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
uniforms.matrices.model = uf::transform::model( transform );
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
uniforms.matrices.view[i] = camera.getView( i );
|
||||
uniforms.matrices.projection[i] = camera.getProjection( i );
|
||||
}
|
||||
|
||||
uniforms.color[0] = 1;
|
||||
uniforms.color[1] = 1;
|
||||
uniforms.color[2] = 1;
|
||||
uniforms.color[3] = 1;
|
||||
|
||||
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void uf::Object::queueHook( const std::string& name, const std::string& payload, double timeout ) {
|
||||
@ -105,11 +168,11 @@ bool uf::Object::load( const std::string& f, bool inheritRoot ) {
|
||||
}
|
||||
std::string filename = grabURI( f, root );
|
||||
if ( !json.readFromFile( filename ) ) {
|
||||
uf::iostream << "Error: failed to open `" + filename + "`" << "\n";
|
||||
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << ": failed to open `" + filename + "`" << "\n";
|
||||
return false;
|
||||
}
|
||||
json["root"] = uf::string::directory(filename);
|
||||
json["source"] = uf::string::filename(filename);
|
||||
json["source"] = filename; // uf::string::filename(filename);
|
||||
json["hot reload"]["mtime"] = uf::string::mtime(filename);
|
||||
return this->load(json);
|
||||
}
|
||||
@ -118,9 +181,10 @@ bool uf::Object::reload( bool hard ) {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
if ( !metadata["system"]["source"].isString() ) return false;
|
||||
uf::Serializer json;
|
||||
std::string filename = grabURI( metadata["system"]["source"].asString(), metadata["system"]["root"].asString() ); // uf::string::sanitize(metadata["system"]["source"].asString(), metadata["system"]["root"].asString());
|
||||
std::string filename = metadata["system"]["source"].asString(); //grabURI( metadata["system"]["source"].asString(), metadata["system"]["root"].asString() ); // uf::string::sanitize(metadata["system"]["source"].asString(), metadata["system"]["root"].asString());
|
||||
if ( !json.readFromFile( filename ) ) {
|
||||
uf::iostream << "Error: failed to open `" + filename + "`" << "\n";
|
||||
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << ": failed to open `" + filename + "`" << "\n";
|
||||
uf::iostream << this << ": " << this->getName() << ": " << this->getUid() << ": " << metadata << "\n";
|
||||
return false;
|
||||
}
|
||||
if ( hard ) return this->load(filename);
|
||||
@ -136,11 +200,11 @@ std::size_t uf::Object::loadChild( const std::string& f, bool initialize ) {
|
||||
uf::Serializer json;
|
||||
std::string filename = grabURI( f, metadata["system"]["root"].asString() );
|
||||
if ( !json.readFromFile(filename) ) {
|
||||
uf::iostream << "Error: failed to open `" + filename + "`" << "\n";
|
||||
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << ": failed to open `" + filename + "`" << "\n";
|
||||
return -1;
|
||||
}
|
||||
json["root"] = uf::string::directory(filename);
|
||||
json["source"] = uf::string::filename(filename);
|
||||
json["source"] = metadata["system"]["source"].asString(); //uf::string::filename(filename);
|
||||
json["hot reload"]["mtime"] = uf::string::mtime( filename );
|
||||
return this->loadChild(json, initialize);
|
||||
}
|
||||
@ -150,7 +214,9 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
{
|
||||
// Set name
|
||||
this->m_name = json["name"].isString() ? json["name"].asString() : json["type"].asString();
|
||||
// Set transform
|
||||
}
|
||||
// Set transform
|
||||
{
|
||||
bool load = json["transform"].isObject();
|
||||
if ( this->hasComponent<pod::Transform<>>() ) load = false;
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
@ -182,6 +248,25 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
transform = uf::transform::reorient( transform );
|
||||
}
|
||||
}
|
||||
// Set movement
|
||||
{
|
||||
if ( json["physics"].isObject() && !this->hasComponent<pod::Physics>() ) {
|
||||
auto& physics = this->getComponent<pod::Physics>();
|
||||
if ( json["physics"]["linear"]["velocity"].isArray() )
|
||||
for ( uint j = 0; j < 3; ++j )
|
||||
physics.linear.velocity[j] = json["physics"]["linear"]["velocity"][j].asFloat();
|
||||
if ( json["physics"]["linear"]["acceleration"].isArray() )
|
||||
for ( uint j = 0; j < 3; ++j )
|
||||
physics.linear.acceleration[j] = json["physics"]["linear"]["acceleration"][j].asFloat();
|
||||
|
||||
if ( json["physics"]["rotational"]["velocity"].isArray() )
|
||||
for ( uint j = 0; j < 4; ++j )
|
||||
physics.rotational.velocity[j] = json["physics"]["rotational"]["velocity"][j].asFloat();
|
||||
if ( json["physics"]["rotational"]["acceleration"].isArray() )
|
||||
for ( uint j = 0; j < 4; ++j )
|
||||
physics.rotational.acceleration[j] = json["physics"]["rotational"]["acceleration"][j].asFloat();
|
||||
}
|
||||
}
|
||||
|
||||
uf::Scene& scene = this->getRootParent<uf::Scene>();
|
||||
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
||||
@ -204,12 +289,6 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
std::string filename = grabURI( target[i].asString(), json["root"].asString() );
|
||||
if ( uf::string::extension(filename) != "ogg" ) continue;
|
||||
if ( (canonical = assetLoader.load( filename )) != "" ) {
|
||||
/*
|
||||
uf::Serializer queue;
|
||||
queue["name"] = "asset:Load.%UID%";
|
||||
queue["payload"]["filename"] = canonical;
|
||||
metadata["system"]["hooks"]["queue"].append(queue);
|
||||
*/
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = canonical;
|
||||
this->queueHook( "asset:Load.%UID%", payload );
|
||||
@ -234,12 +313,6 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
std::string filename = grabURI( target[i].asString(), json["root"].asString() );
|
||||
if ( uf::string::extension(filename) != "png" ) continue;
|
||||
if ( (canonical = assetLoader.load( filename )) != "" ) {
|
||||
/*
|
||||
uf::Serializer queue;
|
||||
queue["name"] = "asset:Load.%UID%";
|
||||
queue["payload"]["filename"] = canonical;
|
||||
metadata["system"]["hooks"]["queue"].append(queue);
|
||||
*/
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = canonical;
|
||||
this->queueHook( "asset:Load.%UID%", payload );
|
||||
@ -247,7 +320,31 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
}
|
||||
}
|
||||
|
||||
uf::Serializer queue = metadata["system"]["hooks"]["queue"];
|
||||
// gltf (singular)
|
||||
{
|
||||
// find first valid texture in asset list
|
||||
uf::Serializer target;
|
||||
if ( metadata["system"]["assets"].isArray() ) {
|
||||
target = metadata["system"]["assets"];
|
||||
} else if ( json["assets"].isArray() ) {
|
||||
target = json["assets"];
|
||||
} else if ( json["assets"].isObject() && !json["assets"]["models"].isNull() ) {
|
||||
target = json["assets"]["models"];
|
||||
}
|
||||
for ( uint i = 0; i < target.size(); ++i ) {
|
||||
std::string canonical = "";
|
||||
std::string f = target[i].asString();
|
||||
std::string filename = grabURI( target[i].asString(), json["root"].asString() );
|
||||
if ( uf::string::extension(filename) != "glb" ) continue;
|
||||
if ( (canonical = assetLoader.load( filename )) != "" ) {
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = canonical;
|
||||
this->queueHook( "asset:Load.%UID%", payload );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uf::Serializer hooks = metadata["system"]["hooks"];
|
||||
// Metadata
|
||||
if ( json["metadata"] != Json::nullValue ) {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
@ -255,7 +352,7 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
std::string f = json["metadata"].asString();
|
||||
std::string filename = grabURI( json["metadata"].asString(), json["root"].asString() );
|
||||
if ( !metadata.readFromFile(filename) ) {
|
||||
uf::iostream << "Error: failed to open `" + filename + "`" << "\n";
|
||||
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << ": failed to open `" + filename + "`" << "\n";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -264,7 +361,11 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
}
|
||||
metadata["system"] = json;
|
||||
metadata["system"].removeMember("metadata");
|
||||
metadata["system"]["hooks"]["queue"] = queue;
|
||||
metadata["system"]["hooks"] = hooks;
|
||||
for ( auto it = json["system"].begin(); it != json["system"].end(); ++it ) {
|
||||
if ( metadata["system"][it.key().asString()].isNull() )
|
||||
metadata["system"][it.key().asString()] = json["system"][it.key().asString()];
|
||||
}
|
||||
|
||||
// check for children
|
||||
{
|
||||
@ -284,15 +385,39 @@ bool uf::Object::load( const uf::Serializer& json ) {
|
||||
if ( uf::string::extension(filename) != "json" ) continue;
|
||||
if ( (filename = assetLoader.load(filename) ) == "" ) continue;
|
||||
if ( !json.readFromFile(filename) ) {
|
||||
uf::iostream << "Error: failed to open `" + filename + "`" << "\n";
|
||||
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << ": failed to open `" + filename + "`" << "\n";
|
||||
continue;
|
||||
}
|
||||
json["root"] = uf::string::directory(filename);
|
||||
json["source"] = uf::string::filename(filename);
|
||||
json["source"] = filename; // uf::string::filename(filename)
|
||||
json["hot reload"]["mtime"] = uf::string::mtime( filename );
|
||||
if ( this->loadChild(json) == -1 ) continue;
|
||||
}
|
||||
}
|
||||
// Add lights
|
||||
if ( metadata["system"]["lights"].isArray() ) {
|
||||
uf::Serializer target = metadata["system"]["lights"];
|
||||
for ( uint i = 0; i < target.size(); ++i ) {
|
||||
uf::Serializer json = target[i];
|
||||
auto* light = this->findByUid(this->loadChild("/light.json", false));
|
||||
if ( !light ) continue;
|
||||
auto& metadata = light->getComponent<uf::Serializer>();
|
||||
auto& transform = light->getComponent<pod::Transform<>>();
|
||||
if ( json["position"].isArray() )
|
||||
for ( uint j = 0; j < 3; ++j ) transform.position[j] = json["position"][j].asFloat();
|
||||
if ( json["orientation"].isArray() )
|
||||
for ( uint j = 0; j < 4; ++j ) transform.orientation[j] = json["orientation"][j].asFloat();
|
||||
|
||||
if ( !json["color"].isNull() ) metadata["light"]["color"] = json["color"];
|
||||
if ( !json["radius"].isNull() ) metadata["light"]["radius"] = json["radius"];
|
||||
if ( !json["power"].isNull() ) metadata["light"]["power"] = json["power"];
|
||||
if ( !json["shadows"].isNull() ) metadata["light"]["shadows"] = json["shadows"];
|
||||
|
||||
light->initialize();
|
||||
|
||||
// std::cout << json << "\t" << metadata["light"] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -303,7 +428,7 @@ std::size_t uf::Object::loadChild( const uf::Serializer& json, bool initialize )
|
||||
entity = uf::instantiator::instantiate(type);
|
||||
|
||||
if ( !((uf::Object*) entity)->load(json) ) {
|
||||
uf::iostream << "Error loading `" << json << "!" << "\n";
|
||||
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << " loading `" << json << "!" << "\n";
|
||||
delete entity;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1,22 +1,174 @@
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/ext/vulkan/vulkan.h>
|
||||
#include <uf/utils/string/ext.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
|
||||
#include <uf/ext/vulkan/rendermodes/deferred.h>
|
||||
#include <uf/ext/vulkan/rendermodes/rendertarget.h>
|
||||
#include <uf/ext/vulkan/rendermodes/stereoscopic_deferred.h>
|
||||
|
||||
UF_OBJECT_REGISTER_CPP(Scene)
|
||||
void uf::Scene::initialize() {
|
||||
// this->m_graphics = new std::vector<ext::vulkan::Graphic*>();
|
||||
// ext::vulkan::graphics = (std::vector<ext::vulkan::Graphic*>*) this->m_graphics;
|
||||
ext::vulkan::scenes.push_back(this);
|
||||
ext::vulkan::rebuild = true;
|
||||
uf::Object::initialize();
|
||||
}
|
||||
void uf::Scene::tick() {
|
||||
// ext::vulkan::graphics = (std::vector<ext::vulkan::Graphic*>*) this->m_graphics;
|
||||
uf::Object::tick();
|
||||
|
||||
if ( uf::scene::getCurrentScene().getUid() == this->getUid() ) {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
/* Update lights */ if ( metadata["light"]["should"].asBool() ) {
|
||||
// if ( !ext::vulkan::currentRenderMode || ext::vulkan::currentRenderMode->name != "" ) return;
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
|
||||
std::vector<ext::vulkan::Graphic*> blitters;
|
||||
auto& renderMode = ext::vulkan::getRenderMode("", true);
|
||||
if ( renderMode.getType() == "Deferred (Stereoscopic)" ) {
|
||||
auto* renderModePointer = (ext::vulkan::StereoscopicDeferredRenderMode*) &renderMode;
|
||||
blitters.push_back(&renderModePointer->blitters.left);
|
||||
blitters.push_back(&renderModePointer->blitters.right);
|
||||
} else if ( renderMode.getType() == "Deferred" ) {
|
||||
auto* renderModePointer = (ext::vulkan::DeferredRenderMode*) &renderMode;
|
||||
blitters.push_back(&renderModePointer->blitter);
|
||||
}
|
||||
auto& controller = *scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
|
||||
// auto& uniforms = blitter.uniforms;
|
||||
struct UniformDescriptor {
|
||||
struct Matrices {
|
||||
alignas(16) pod::Matrix4f view[2];
|
||||
alignas(16) pod::Matrix4f projection[2];
|
||||
} matrices;
|
||||
alignas(16) pod::Vector4f ambient;
|
||||
struct Light {
|
||||
alignas(16) pod::Vector4f position;
|
||||
alignas(16) pod::Vector4f color;
|
||||
alignas(8) pod::Vector2i type;
|
||||
alignas(16) pod::Matrix4f view;
|
||||
alignas(16) pod::Matrix4f projection;
|
||||
} lights;
|
||||
};
|
||||
|
||||
struct SpecializationConstant {
|
||||
int32_t maxLights = 16;
|
||||
} specializationConstants;
|
||||
|
||||
for ( size_t _ = 0; _ < blitters.size(); ++_ ) {
|
||||
auto& blitter = *blitters[_];
|
||||
|
||||
uint8_t* buffer;
|
||||
size_t len;
|
||||
auto* shader = &blitter.material.shaders.front();
|
||||
|
||||
for ( auto& _ : blitter.material.shaders ) {
|
||||
if ( _.uniforms.empty() ) continue;
|
||||
auto& userdata = _.uniforms.front();
|
||||
buffer = (uint8_t*) (void*) userdata;
|
||||
len = userdata.data().len;
|
||||
shader = &_;
|
||||
specializationConstants = _.specializationConstants.get<SpecializationConstant>();
|
||||
}
|
||||
|
||||
if ( !buffer ) continue;
|
||||
|
||||
UniformDescriptor* uniforms = (UniformDescriptor*) buffer;
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
uniforms->matrices.view[i] = camera.getView( i );
|
||||
uniforms->matrices.projection[i] = camera.getProjection( i );
|
||||
}
|
||||
{
|
||||
uniforms->ambient.x = metadata["light"]["ambient"][0].asFloat();
|
||||
uniforms->ambient.y = metadata["light"]["ambient"][1].asFloat();
|
||||
uniforms->ambient.z = metadata["light"]["ambient"][2].asFloat();
|
||||
uniforms->ambient.w = metadata["light"]["kexp"].asFloat();
|
||||
}
|
||||
{
|
||||
std::vector<uf::Entity*> entities;
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
if ( !entity || entity->getName() != "Light" ) return;
|
||||
entities.push_back(entity);
|
||||
};
|
||||
for ( uf::Scene* scene : ext::vulkan::scenes ) { if ( !scene ) continue;
|
||||
scene->process(filter);
|
||||
}
|
||||
{
|
||||
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
|
||||
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
|
||||
if ( !l ) return false; if ( !r ) return true;
|
||||
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
|
||||
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
|
||||
} );
|
||||
}
|
||||
|
||||
{
|
||||
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
|
||||
if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller);
|
||||
}
|
||||
UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)];
|
||||
for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) {
|
||||
UniformDescriptor::Light& light = lights[i];
|
||||
light.position = { 0, 0, 0, 0 };
|
||||
light.color = { 0, 0, 0, 0 };
|
||||
light.type = { 0, 0 };
|
||||
}
|
||||
|
||||
blitter.material.textures.clear();
|
||||
|
||||
for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) {
|
||||
UniformDescriptor::Light& light = lights[i];
|
||||
uf::Entity* entity = entities[i];
|
||||
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();
|
||||
uf::Serializer& metadata = entity->getComponent<uf::Serializer>();
|
||||
uf::Camera& camera = entity->getComponent<uf::Camera>();
|
||||
|
||||
light.position.x = transform.position.x;
|
||||
light.position.y = transform.position.y;
|
||||
light.position.z = transform.position.z;
|
||||
|
||||
light.view = camera.getView();
|
||||
light.projection = camera.getProjection();
|
||||
|
||||
if ( entity == &controller ) light.position.y += 2;
|
||||
|
||||
light.position.w = metadata["light"]["power"].asFloat();
|
||||
|
||||
light.color.x = metadata["light"]["color"][0].asFloat();
|
||||
light.color.y = metadata["light"]["color"][1].asFloat();
|
||||
light.color.z = metadata["light"]["color"][2].asFloat();
|
||||
|
||||
light.color.w = metadata["light"]["radius"].asFloat();
|
||||
|
||||
light.type.x = metadata["light"]["type"].asUInt64();
|
||||
light.type.y = metadata["light"]["shadows"]["enabled"].asBool();
|
||||
|
||||
if ( entity->hasComponent<ext::vulkan::RenderTargetRenderMode>() ) {
|
||||
auto& renderMode = entity->getComponent<ext::vulkan::RenderTargetRenderMode>();
|
||||
auto& renderTarget = renderMode.renderTarget;
|
||||
for ( auto& attachment : renderTarget.attachments ) {
|
||||
if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
auto& texture = blitter.material.textures.emplace_back();
|
||||
texture.aliasAttachment(attachment);
|
||||
light.type.y = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
light.type.y = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
blitter.getPipeline().update( blitter );
|
||||
shader->updateBuffer( (void*) buffer, len, 0, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void uf::Scene::render() {
|
||||
// ext::vulkan::graphics = (std::vector<ext::vulkan::Graphic*>*) this->m_graphics;
|
||||
uf::Object::render();
|
||||
|
||||
}
|
||||
void uf::Scene::destroy() {
|
||||
uf::Object::destroy();
|
||||
@ -27,29 +179,45 @@ void uf::Scene::destroy() {
|
||||
ext::vulkan::scenes.erase(it);
|
||||
}
|
||||
}
|
||||
/*
|
||||
ext::vulkan::scenes.erase(
|
||||
std::remove(ext::vulkan::scenes.begin(), ext::vulkan::scenes.end(), this),
|
||||
ext::vulkan::scenes.end()
|
||||
);
|
||||
*/
|
||||
ext::vulkan::rebuild = true;
|
||||
/*
|
||||
std::vector<ext::vulkan::Graphic*>* graphics = (std::vector<ext::vulkan::Graphic*>*) this->m_graphics;
|
||||
for ( auto* graphic : *graphics ) {
|
||||
graphic->destroy();
|
||||
}
|
||||
delete graphics;
|
||||
ext::vulkan::graphics = NULL;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
uf::Entity* uf::Scene::getController() {
|
||||
return this->findByName("Player");
|
||||
}
|
||||
const uf::Entity* uf::Scene::getController() const {
|
||||
return this->findByName("Player");
|
||||
}
|
||||
*/
|
||||
uf::Entity* uf::Scene::getController() {
|
||||
if ( ext::vulkan::currentRenderMode ) {
|
||||
auto& renderMode = *ext::vulkan::currentRenderMode;
|
||||
std::string name = renderMode.name;
|
||||
auto split = uf::string::split( name, ": " );
|
||||
if ( split.front() == "Render Target" ) {
|
||||
uint64_t uid = std::stoi( split.back() );
|
||||
uf::Entity* ent = this->findByUid( uid );
|
||||
if ( ent ) return ent;
|
||||
}
|
||||
}
|
||||
return this->findByName("Player");
|
||||
}
|
||||
const uf::Entity* uf::Scene::getController() const {
|
||||
if ( ext::vulkan::currentRenderMode ) {
|
||||
auto& renderMode = *ext::vulkan::currentRenderMode;
|
||||
std::string name = renderMode.name;
|
||||
auto split = uf::string::split( name, ": " );
|
||||
if ( split.front() == "Render Target" ) {
|
||||
uint64_t uid = std::stoi( split.back() );
|
||||
const uf::Entity* ent = this->findByUid( uid );
|
||||
if ( ent ) return ent;
|
||||
}
|
||||
}
|
||||
return this->findByName("Player");
|
||||
}
|
||||
|
||||
std::vector<uf::Scene*> uf::scene::scenes;
|
||||
uf::Scene& uf::scene::loadScene( const std::string& name, const std::string& filename ) {
|
||||
|
||||
334
engine/src/ext/gltf/gltf.cpp
Normal file
334
engine/src/ext/gltf/gltf.cpp
Normal file
@ -0,0 +1,334 @@
|
||||
#define TINYGLTF_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#include <gltf/tiny_gltf.h>
|
||||
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
#include <uf/utils/string/ext.h>
|
||||
#include <uf/utils/math/transform.h>
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/math/collision.h>
|
||||
|
||||
namespace {
|
||||
|
||||
VkSamplerAddressMode getVkWrapMode(int32_t wrapMode) {
|
||||
switch (wrapMode) {
|
||||
case 10497: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case 33071: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case 33648: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
default: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
VkFilter getVkFilterMode(int32_t filterMode) {
|
||||
switch (filterMode) {
|
||||
case 9728: return VK_FILTER_NEAREST;
|
||||
case 9729: return VK_FILTER_LINEAR;
|
||||
case 9984: return VK_FILTER_NEAREST;
|
||||
case 9985: return VK_FILTER_NEAREST;
|
||||
case 9986: return VK_FILTER_LINEAR;
|
||||
case 9987: return VK_FILTER_LINEAR;
|
||||
default: return VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
void loadNode( uf::Object& entity, const tinygltf::Model& model, const tinygltf::Node& node, uint8_t mode ) {
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
|
||||
if ( node.translation.size() == 3 ) {
|
||||
transform.position.x = node.translation[0];
|
||||
transform.position.y = node.translation[1];
|
||||
transform.position.z = node.translation[2];
|
||||
}
|
||||
if ( node.rotation.size() == 4 ) {
|
||||
transform.orientation.x = node.rotation[0];
|
||||
transform.orientation.y = node.rotation[1];
|
||||
transform.orientation.z = node.rotation[2];
|
||||
transform.orientation.w = node.rotation[3];
|
||||
}
|
||||
if ( node.scale.size() == 3 ) {
|
||||
transform.scale.x = node.scale[0];
|
||||
transform.scale.y = node.scale[1];
|
||||
transform.scale.z = node.scale[2];
|
||||
}
|
||||
// if ( node.matrix.size() == 16 ) {}
|
||||
|
||||
auto fillMesh = [&]( uf::BaseMesh<pod::Vertex_3F2F3F, uint32_t>& mesh, const tinygltf::Primitive& primitive, uf::Collider& collider ) {
|
||||
size_t verticesStart = mesh.vertices.size();
|
||||
size_t indicesStart = mesh.indices.size();
|
||||
|
||||
size_t vertices = 0;
|
||||
struct Attribute {
|
||||
std::string name = "";
|
||||
size_t components = 1;
|
||||
std::vector<float> buffer;
|
||||
};
|
||||
std::unordered_map<std::string, Attribute> attributes = {
|
||||
{"POSITION", {}},
|
||||
{"TEXCOORD_0", {}},
|
||||
{"NORMAL", {}},
|
||||
};
|
||||
|
||||
for ( auto& kv : attributes ) {
|
||||
auto& attribute = kv.second;
|
||||
attribute.name = kv.first;
|
||||
auto it = primitive.attributes.find(attribute.name);
|
||||
if ( it == primitive.attributes.end() ) continue;
|
||||
|
||||
auto& accessor = model.accessors[it->second];
|
||||
auto& view = model.bufferViews[accessor.bufferView];
|
||||
auto* buffer = reinterpret_cast<const float*>(&(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]));
|
||||
|
||||
if ( attribute.name == "POSITION" ) {
|
||||
vertices = accessor.count;
|
||||
pod::Vector3f minCorner = { accessor.minValues[0], accessor.minValues[1], accessor.minValues[2] };
|
||||
pod::Vector3f maxCorner = { accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2] };
|
||||
|
||||
pod::Vector3f origin = (maxCorner + minCorner) * 0.5f;
|
||||
pod::Vector3f size = (maxCorner - minCorner) * 0.5f;
|
||||
|
||||
if ( (mode & ext::gltf::LoadMode::COLLISION) && (mode & ext::gltf::LoadMode::AABB) ) {
|
||||
auto* box = new uf::BoundingBox( origin, size );
|
||||
collider.add(box);
|
||||
}
|
||||
}
|
||||
|
||||
attribute.components = accessor.ByteStride(view) / sizeof(float);
|
||||
attribute.buffer.reserve( accessor.count * attribute.components );
|
||||
attribute.buffer.insert( attribute.buffer.end(), &buffer[0], &buffer[accessor.count * attribute.components] );
|
||||
}
|
||||
|
||||
mesh.vertices.reserve( vertices + verticesStart );
|
||||
|
||||
for ( size_t i = 0; i < vertices; ++i ) {
|
||||
auto& vertex = mesh.vertices.emplace_back();
|
||||
|
||||
#define ITERATE_ATTRIBUTE( name, member )\
|
||||
if ( !attributes[name].buffer.empty() ) { \
|
||||
for ( size_t j = 0; j < attributes[name].components; ++j )\
|
||||
vertex.member[j] = attributes[name].buffer[i * attributes[name].components + j];\
|
||||
}
|
||||
|
||||
ITERATE_ATTRIBUTE("POSITION", position);
|
||||
ITERATE_ATTRIBUTE("TEXCOORD_0", uv);
|
||||
ITERATE_ATTRIBUTE("NORMAL", normal);
|
||||
|
||||
#undef ITERATE_ATTRIBUTE
|
||||
}
|
||||
|
||||
|
||||
if ( primitive.indices > -1 ) {
|
||||
auto& accessor = model.accessors[primitive.indices];
|
||||
auto& view = model.bufferViews[accessor.bufferView];
|
||||
auto& buffer = model.buffers[view.buffer];
|
||||
|
||||
mesh.indices.reserve( accessor.count + indicesStart );
|
||||
|
||||
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 );
|
||||
for (size_t index = 0; index < accessor.count; index++) mesh.indices.push_back(buf[index] + verticesStart );
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT: {
|
||||
auto* buf = static_cast<const uint16_t*>( pointer );
|
||||
for (size_t index = 0; index < accessor.count; index++) mesh.indices.push_back(buf[index] + verticesStart );
|
||||
break;
|
||||
}
|
||||
case TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE: {
|
||||
auto* buf = static_cast<const uint8_t*>( pointer );
|
||||
for (size_t index = 0; index < accessor.count; index++) mesh.indices.push_back(buf[index] + verticesStart );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mode & ext::gltf::LoadMode::GENERATE_NORMALS ) {
|
||||
for ( size_t i = 0; i < mesh.indices.size(); i+=3 ) {
|
||||
auto& A = mesh.vertices[mesh.indices[i+0]];
|
||||
auto& B = mesh.vertices[mesh.indices[i+1]];
|
||||
auto& C = mesh.vertices[mesh.indices[i+2]];
|
||||
|
||||
auto& a = A.position;
|
||||
auto& b = B.position;
|
||||
auto& c = C.position;
|
||||
|
||||
pod::Vector3f normal = uf::vector::normalize( uf::vector::cross( b - a, c - a ) );
|
||||
|
||||
A.normal = normal;
|
||||
B.normal = normal;
|
||||
C.normal = normal;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// recalc normals
|
||||
if ( mode & ext::gltf::LoadMode::GENERATE_NORMALS ) {
|
||||
// bool invert = false;
|
||||
for ( size_t i = 0; i < mesh.vertices.size(); i+=3 ) {
|
||||
// auto& b = mesh.vertices[i+(invert ? 2 : 1)].position;
|
||||
// auto& c = mesh.vertices[i+(invert ? 1 : 2)].position;
|
||||
auto& a = mesh.vertices[i+0].position;
|
||||
auto& b = mesh.vertices[i+1].position;
|
||||
auto& c = mesh.vertices[i+2].position;
|
||||
|
||||
pod::Vector3f normal = uf::vector::normalize( uf::vector::cross( b - a, c - a ) );
|
||||
mesh.vertices[i+0].normal = normal;
|
||||
mesh.vertices[i+1].normal = normal;
|
||||
mesh.vertices[i+2].normal = normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( mode & ext::gltf::LoadMode::APPLY_TRANSFORMS ) {
|
||||
pod::Matrix4f model = uf::transform::model( transform );
|
||||
for ( auto& vertex : mesh.vertices ) {
|
||||
vertex.position = uf::matrix::multiply<float>( model, vertex.position );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if ( node.mesh > -1 ) {
|
||||
auto& m = model.meshes[node.mesh];
|
||||
std::vector<ext::vulkan::Sampler> samplers;
|
||||
std::vector<uf::Image> images;
|
||||
/*
|
||||
std::vector<uf::Object> lights;
|
||||
for ( auto& l : model.lights ) {
|
||||
auto& light = lights.emplace_back();
|
||||
auto& metadata = light.getComponent<uf::Serializer>();
|
||||
metadata["light"]["color"][0] = l.color[0];
|
||||
metadata["light"]["color"][1] = l.color[1];
|
||||
metadata["light"]["color"][2] = l.color[2];
|
||||
|
||||
metadata["light"]["radius"] = l.range;
|
||||
metadata["light"]["power"] = l.intensity;
|
||||
|
||||
std::cout << metadata << std::endl;
|
||||
}
|
||||
*/
|
||||
for ( auto& s : model.samplers ) {
|
||||
auto& sampler = samplers.emplace_back();
|
||||
sampler.descriptor.filter.min = getVkFilterMode( s.minFilter );
|
||||
sampler.descriptor.filter.mag = getVkFilterMode( s.magFilter );
|
||||
sampler.descriptor.addressMode.u = getVkWrapMode( s.wrapS );
|
||||
sampler.descriptor.addressMode.v = getVkWrapMode( s.wrapT );
|
||||
sampler.descriptor.addressMode.w = sampler.descriptor.addressMode.v;
|
||||
}
|
||||
for ( auto& t : model.textures ) {
|
||||
auto& im = model.images[t.source];
|
||||
uf::Image& image = images.emplace_back();
|
||||
// std::cout << "Loading image: " << im.width << ", " << im.height << std::endl;
|
||||
image.loadFromBuffer( &im.image[0], {im.width, im.height}, 8, im.component, true );
|
||||
}
|
||||
// if ( model.textures.size() > 1 && m.primitives.size() == model.textures.size() ) {
|
||||
if ( mode & ext::gltf::LoadMode::SEPARATE_MESHES ) {
|
||||
auto sampler = samplers.begin();
|
||||
auto image = images.begin();
|
||||
for ( auto& primitive : m.primitives ) {
|
||||
uf::Object* child = new uf::Object;
|
||||
|
||||
uf::BaseMesh<pod::Vertex_3F2F3F, uint32_t> mesh;
|
||||
auto& cTransform = child->getComponent<pod::Transform<>>();
|
||||
cTransform = transform;
|
||||
|
||||
auto& collider = child->getComponent<uf::Collider>();
|
||||
fillMesh( mesh, primitive, collider );
|
||||
|
||||
if ( (mode & ext::gltf::LoadMode::COLLISION) && !(mode & ext::gltf::LoadMode::AABB) ) {
|
||||
auto* box = new uf::MeshCollider( cTransform );
|
||||
box->setPositions( mesh );
|
||||
collider.add(box);
|
||||
}
|
||||
if ( mode & ext::gltf::LoadMode::RENDER ) {
|
||||
auto& graphic = child->getComponent<uf::Graphic>();
|
||||
// graphic.descriptor.cullMode = VK_CULL_MODE_NONE;
|
||||
graphic.initialize();
|
||||
graphic.initializeGeometry( mesh );
|
||||
|
||||
graphic.material.attachShader("./data/shaders/base.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
if ( image != images.end() ) graphic.material.textures.emplace_back().loadFromImage( *(image++) );
|
||||
if ( sampler != samplers.end() ) graphic.material.samplers.push_back( *(sampler++) );
|
||||
}
|
||||
for ( auto* collider : collider.getContainer() ) collider->getTransform().reference = &cTransform;
|
||||
|
||||
entity.addChild( *child );
|
||||
child->initialize();
|
||||
|
||||
if ( mode & ext::gltf::LoadMode::APPLY_TRANSFORMS ) cTransform = {};
|
||||
}
|
||||
} else {
|
||||
uf::BaseMesh<pod::Vertex_3F2F3F, uint32_t> mesh;
|
||||
auto& collider = entity.getComponent<uf::Collider>();
|
||||
|
||||
for ( auto& primitive : m.primitives ) fillMesh( mesh, primitive, collider );
|
||||
|
||||
if ( (mode & ext::gltf::LoadMode::COLLISION) && !(mode & ext::gltf::LoadMode::AABB) ) {
|
||||
auto* c = new uf::MeshCollider( transform );
|
||||
c->setPositions( mesh );
|
||||
collider.add(c);
|
||||
}
|
||||
|
||||
for ( auto* collider : collider.getContainer() ) collider->getTransform().reference = &transform;
|
||||
|
||||
if ( mode & ext::gltf::LoadMode::RENDER ) {
|
||||
auto& graphic = entity.getComponent<uf::Graphic>();
|
||||
|
||||
graphic.initialize();
|
||||
graphic.initializeGeometry( mesh );
|
||||
|
||||
graphic.material.attachShader("./data/shaders/base.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
for ( auto& image : images ) graphic.material.textures.emplace_back().loadFromImage( image );
|
||||
for ( auto& sampler : samplers ) graphic.material.samplers.push_back(sampler);
|
||||
}
|
||||
if ( mode & ext::gltf::LoadMode::APPLY_TRANSFORMS ) transform = {};
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto i : node.children ) {
|
||||
uf::Object* child = new uf::Object;
|
||||
entity.addChild( *child );
|
||||
loadNode( *child, model, model.nodes[i], mode );
|
||||
child->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ext::gltf::load( uf::Object& entity, const std::string& filename, uint8_t mode ) {
|
||||
tinygltf::Model model;
|
||||
tinygltf::TinyGLTF loader;
|
||||
|
||||
std::string warn, err;
|
||||
std::string extension = uf::string::extension( filename );
|
||||
bool ret;
|
||||
if ( extension == "glb" )
|
||||
ret = loader.LoadBinaryFromFile(&model, &err, &warn, filename); // for binary glTF(.glb)
|
||||
else
|
||||
ret = loader.LoadASCIIFromFile(&model, &err, &warn, filename);
|
||||
|
||||
if ( !warn.empty() ) std::cout << "glTF warning: " << warn << std::endl;
|
||||
if ( !err.empty() ) std::cout << "glTF error: " << err << std::endl;
|
||||
if ( !ret ) { std::cout << "glTF error: failed to parse file: " << filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& scene = model.scenes[model.defaultScene > -1 ? model.defaultScene : 0];
|
||||
for ( auto i : scene.nodes ) {
|
||||
loadNode( entity, model, model.nodes[i], mode );
|
||||
}
|
||||
|
||||
// parent transform
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* child ) {
|
||||
if ( child == &entity ) return;
|
||||
if ( !child->hasComponent<pod::Transform<>>() ) return;
|
||||
child->getComponent<pod::Transform<>>().reference = &transform;
|
||||
};
|
||||
entity.process(filter);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -14,6 +14,7 @@ float ext::openvr::width = 0;
|
||||
float ext::openvr::height = 0;
|
||||
bool ext::openvr::enabled = false;
|
||||
bool ext::openvr::swapEyes = false;
|
||||
uint8_t ext::openvr::dominantEye = 0;
|
||||
|
||||
#define VR_CHECK_INPUT_RESULT(f)\
|
||||
if ( f != vr::VRInputError_None ) {\
|
||||
@ -556,7 +557,7 @@ pod::Matrix4t<> ext::openvr::hmdProjectionMatrix( vr::Hmd_Eye eye, float zNear,
|
||||
frustum.bottom = abs( frustum.bottom );
|
||||
} else {
|
||||
}
|
||||
std::cout << frustum.left << "\t" << frustum.right << "\t" << frustum.top << "\t" << frustum.bottom << std::endl;
|
||||
// std::cout << frustum.left << "\t" << frustum.right << "\t" << frustum.top << "\t" << frustum.bottom << std::endl;
|
||||
|
||||
/*
|
||||
float fov = this->m_settings.perspective.fov * (3.14159265358f / 180.0f);
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
|
||||
namespace {
|
||||
void VRExtensions( std::vector<std::string>& requested ) {
|
||||
if ( !vr::VRCompositor() ) return;
|
||||
@ -18,34 +20,142 @@ namespace {
|
||||
vr::VRCompositor()->GetVulkanInstanceExtensionsRequired( pExtensionStr, nBufferSize );
|
||||
std::vector<std::string> extensions = uf::string::split( pExtensionStr, " " );
|
||||
requested.insert( requested.end(), extensions.begin(), extensions.end() );
|
||||
/*
|
||||
// Allocate enough ExtensionProperties to support all extensions being enabled
|
||||
uint32_t extensionsCount = 0;
|
||||
uint32_t enabledExtensionsCount = 0;
|
||||
|
||||
VK_CHECK_RESULT(vkEnumerateInstanceExtensionProperties( NULL, &extensionsCount, NULL ));
|
||||
std::vector<VkExtensionProperties> extensionProperties(extensionsCount);
|
||||
VK_CHECK_RESULT( vkEnumerateInstanceExtensionProperties( NULL, &extensionsCount, &extensionProperties[0] ) );
|
||||
for ( size_t i = 0; i < extensions.size(); ++i ) {
|
||||
bool found = false;
|
||||
uint32_t index = 0;
|
||||
for ( index = 0; index < extensionsCount; index++ ) {
|
||||
if ( strcmp( extensions[i].c_str(), extensionProperties[index].extensionName ) == 0 ) {
|
||||
for ( auto alreadyAdded : supportedExtensions ) {
|
||||
if ( strcmp( extensions[i].c_str(), alreadyAdded ) == 0 ) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( found ) break;
|
||||
found = true;
|
||||
supportedExtensions.push_back(extensionProperties[index].extensionName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found ) std::cout << "Vulkan missing requested extension " << extensions[index] << std::endl;
|
||||
}
|
||||
void enableRequestedDeviceFeatures( ext::vulkan::Device& device ) {
|
||||
uf::Serializer json;
|
||||
|
||||
#define CHECK_FEATURE( NAME )\
|
||||
if ( feature == #NAME ) {\
|
||||
if ( device.features.NAME == VK_TRUE ) {\
|
||||
device.enabledFeatures.NAME = true;\
|
||||
if ( ext::vulkan::validation ) std::cout << "Enabled feature: " << feature << std::endl;\
|
||||
} else if ( ext::vulkan::validation ) std::cout << "Failed to enable feature: " << feature << std::endl;\
|
||||
}
|
||||
*/
|
||||
|
||||
for ( auto& feature : ext::vulkan::requestedDeviceFeatures ) {
|
||||
CHECK_FEATURE(robustBufferAccess);
|
||||
CHECK_FEATURE(fullDrawIndexUint32);
|
||||
CHECK_FEATURE(imageCubeArray);
|
||||
CHECK_FEATURE(independentBlend);
|
||||
CHECK_FEATURE(geometryShader);
|
||||
CHECK_FEATURE(tessellationShader);
|
||||
CHECK_FEATURE(sampleRateShading);
|
||||
CHECK_FEATURE(dualSrcBlend);
|
||||
CHECK_FEATURE(logicOp);
|
||||
CHECK_FEATURE(multiDrawIndirect);
|
||||
CHECK_FEATURE(drawIndirectFirstInstance);
|
||||
CHECK_FEATURE(depthClamp);
|
||||
CHECK_FEATURE(depthBiasClamp);
|
||||
CHECK_FEATURE(fillModeNonSolid);
|
||||
CHECK_FEATURE(depthBounds);
|
||||
CHECK_FEATURE(wideLines);
|
||||
CHECK_FEATURE(largePoints);
|
||||
CHECK_FEATURE(alphaToOne);
|
||||
CHECK_FEATURE(multiViewport);
|
||||
CHECK_FEATURE(samplerAnisotropy);
|
||||
CHECK_FEATURE(textureCompressionETC2);
|
||||
CHECK_FEATURE(textureCompressionASTC_LDR);
|
||||
CHECK_FEATURE(textureCompressionBC);
|
||||
CHECK_FEATURE(occlusionQueryPrecise);
|
||||
CHECK_FEATURE(pipelineStatisticsQuery);
|
||||
CHECK_FEATURE(vertexPipelineStoresAndAtomics);
|
||||
CHECK_FEATURE(fragmentStoresAndAtomics);
|
||||
CHECK_FEATURE(shaderTessellationAndGeometryPointSize);
|
||||
CHECK_FEATURE(shaderImageGatherExtended);
|
||||
CHECK_FEATURE(shaderStorageImageExtendedFormats);
|
||||
CHECK_FEATURE(shaderStorageImageMultisample);
|
||||
CHECK_FEATURE(shaderStorageImageReadWithoutFormat);
|
||||
CHECK_FEATURE(shaderStorageImageWriteWithoutFormat);
|
||||
CHECK_FEATURE(shaderUniformBufferArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderSampledImageArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderStorageBufferArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderStorageImageArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderClipDistance);
|
||||
CHECK_FEATURE(shaderCullDistance);
|
||||
CHECK_FEATURE(shaderFloat64);
|
||||
CHECK_FEATURE(shaderInt64);
|
||||
CHECK_FEATURE(shaderInt16);
|
||||
CHECK_FEATURE(shaderResourceResidency);
|
||||
CHECK_FEATURE(shaderResourceMinLod);
|
||||
CHECK_FEATURE(sparseBinding);
|
||||
CHECK_FEATURE(sparseResidencyBuffer);
|
||||
CHECK_FEATURE(sparseResidencyImage2D);
|
||||
CHECK_FEATURE(sparseResidencyImage3D);
|
||||
CHECK_FEATURE(sparseResidency2Samples);
|
||||
CHECK_FEATURE(sparseResidency4Samples);
|
||||
CHECK_FEATURE(sparseResidency8Samples);
|
||||
CHECK_FEATURE(sparseResidency16Samples);
|
||||
CHECK_FEATURE(sparseResidencyAliased);
|
||||
CHECK_FEATURE(variableMultisampleRate);
|
||||
CHECK_FEATURE(inheritedQueries);
|
||||
}
|
||||
#undef CHECK_FEATURE
|
||||
}
|
||||
uf::Serializer retrieveDeviceFeatures( ext::vulkan::Device& device ) {
|
||||
uf::Serializer json;
|
||||
|
||||
#define CHECK_FEATURE( NAME )\
|
||||
json[#NAME]["supported"] = device.features.NAME;\
|
||||
json[#NAME]["enabled"] = device.enabledFeatures.NAME;
|
||||
|
||||
CHECK_FEATURE(robustBufferAccess);
|
||||
CHECK_FEATURE(fullDrawIndexUint32);
|
||||
CHECK_FEATURE(imageCubeArray);
|
||||
CHECK_FEATURE(independentBlend);
|
||||
CHECK_FEATURE(geometryShader);
|
||||
CHECK_FEATURE(tessellationShader);
|
||||
CHECK_FEATURE(sampleRateShading);
|
||||
CHECK_FEATURE(dualSrcBlend);
|
||||
CHECK_FEATURE(logicOp);
|
||||
CHECK_FEATURE(multiDrawIndirect);
|
||||
CHECK_FEATURE(drawIndirectFirstInstance);
|
||||
CHECK_FEATURE(depthClamp);
|
||||
CHECK_FEATURE(depthBiasClamp);
|
||||
CHECK_FEATURE(fillModeNonSolid);
|
||||
CHECK_FEATURE(depthBounds);
|
||||
CHECK_FEATURE(wideLines);
|
||||
CHECK_FEATURE(largePoints);
|
||||
CHECK_FEATURE(alphaToOne);
|
||||
CHECK_FEATURE(multiViewport);
|
||||
CHECK_FEATURE(samplerAnisotropy);
|
||||
CHECK_FEATURE(textureCompressionETC2);
|
||||
CHECK_FEATURE(textureCompressionASTC_LDR);
|
||||
CHECK_FEATURE(textureCompressionBC);
|
||||
CHECK_FEATURE(occlusionQueryPrecise);
|
||||
CHECK_FEATURE(pipelineStatisticsQuery);
|
||||
CHECK_FEATURE(vertexPipelineStoresAndAtomics);
|
||||
CHECK_FEATURE(fragmentStoresAndAtomics);
|
||||
CHECK_FEATURE(shaderTessellationAndGeometryPointSize);
|
||||
CHECK_FEATURE(shaderImageGatherExtended);
|
||||
CHECK_FEATURE(shaderStorageImageExtendedFormats);
|
||||
CHECK_FEATURE(shaderStorageImageMultisample);
|
||||
CHECK_FEATURE(shaderStorageImageReadWithoutFormat);
|
||||
CHECK_FEATURE(shaderStorageImageWriteWithoutFormat);
|
||||
CHECK_FEATURE(shaderUniformBufferArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderSampledImageArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderStorageBufferArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderStorageImageArrayDynamicIndexing);
|
||||
CHECK_FEATURE(shaderClipDistance);
|
||||
CHECK_FEATURE(shaderCullDistance);
|
||||
CHECK_FEATURE(shaderFloat64);
|
||||
CHECK_FEATURE(shaderInt64);
|
||||
CHECK_FEATURE(shaderInt16);
|
||||
CHECK_FEATURE(shaderResourceResidency);
|
||||
CHECK_FEATURE(shaderResourceMinLod);
|
||||
CHECK_FEATURE(sparseBinding);
|
||||
CHECK_FEATURE(sparseResidencyBuffer);
|
||||
CHECK_FEATURE(sparseResidencyImage2D);
|
||||
CHECK_FEATURE(sparseResidencyImage3D);
|
||||
CHECK_FEATURE(sparseResidency2Samples);
|
||||
CHECK_FEATURE(sparseResidency4Samples);
|
||||
CHECK_FEATURE(sparseResidency8Samples);
|
||||
CHECK_FEATURE(sparseResidency16Samples);
|
||||
CHECK_FEATURE(sparseResidencyAliased);
|
||||
CHECK_FEATURE(variableMultisampleRate);
|
||||
CHECK_FEATURE(inheritedQueries);
|
||||
#undef CHECK_FEATURE
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
@ -512,6 +622,8 @@ void ext::vulkan::Device::initialize() {
|
||||
deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
enableRequestedDeviceFeatures( *this );
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());;
|
||||
@ -525,6 +637,9 @@ void ext::vulkan::Device::initialize() {
|
||||
|
||||
if ( vkCreateDevice( this->physicalDevice, &deviceCreateInfo, nullptr, &this->logicalDevice) != VK_SUCCESS )
|
||||
throw std::runtime_error("failed to create logical device!");
|
||||
|
||||
if ( ext::vulkan::validation )
|
||||
std::cout << retrieveDeviceFeatures( *this ) << std::endl;
|
||||
}
|
||||
// Create command pool
|
||||
{
|
||||
|
||||
@ -58,24 +58,23 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
||||
spirv_cross::Compiler comp( (uint32_t*) &spirv[0], spirv.size() / 4 );
|
||||
spirv_cross::ShaderResources res = comp.get_shader_resources();
|
||||
|
||||
auto parseResource = [&]( const spirv_cross::Resource& resource, VkDescriptorType type ) {
|
||||
// comp.get_decoration(resource.id, spv::DecorationDescriptorSet);
|
||||
|
||||
switch ( type ) {
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
||||
} break;
|
||||
auto parseResource = [&]( const spirv_cross::Resource& resource, VkDescriptorType descriptorType ) {
|
||||
switch ( descriptorType ) {
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
|
||||
const auto& type = comp.get_type(resource.base_type_id);
|
||||
size_t size = comp.get_declared_struct_size(type);
|
||||
const auto& base_type = comp.get_type(resource.base_type_id);
|
||||
auto& uniform = uniforms.emplace_back();
|
||||
uniform.create( size );
|
||||
uniform.create( comp.get_declared_struct_size(base_type) );
|
||||
} break;
|
||||
}
|
||||
descriptorSetLayoutBindings.push_back(ext::vulkan::initializers::descriptorSetLayoutBinding( type, stage, comp.get_decoration(resource.id, spv::DecorationBinding) ) );
|
||||
|
||||
|
||||
const auto& type = comp.get_type(resource.type_id);
|
||||
size_t size = 1;
|
||||
if ( !type.array.empty() ) size = type.array[0];
|
||||
|
||||
descriptorSetLayoutBindings.push_back( ext::vulkan::initializers::descriptorSetLayoutBinding( descriptorType, stage, comp.get_decoration(resource.id, spv::DecorationBinding), size ) );
|
||||
};
|
||||
// std::cout << "Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding) << std::endl;\
|
||||
|
||||
// std::cout << "Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding) << std::endl;
|
||||
#define LOOP_RESOURCES( key, type ) for ( const auto& resource : res.key ) {\
|
||||
parseResource( resource, type );\
|
||||
}
|
||||
@ -86,8 +85,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
||||
LOOP_RESOURCES( uniform_buffers, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER );
|
||||
LOOP_RESOURCES( subpass_inputs, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT );
|
||||
LOOP_RESOURCES( storage_buffers, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER );
|
||||
#undef LOOP_RESOURCES
|
||||
|
||||
#undef LOOP_RESOURCES
|
||||
|
||||
for ( const auto& resource : res.push_constant_buffers ) {
|
||||
auto& pushConstant = pushConstants.emplace_back();
|
||||
@ -196,6 +194,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) {
|
||||
this->device = graphic.device;
|
||||
Device& device = *graphic.device;
|
||||
|
||||
// std::cout << &graphic << ": Shaders: " << graphic.material.shaders.size() << " Textures: " << graphic.material.textures.size() << std::endl;
|
||||
assert( graphic.material.shaders.size() > 0 );
|
||||
|
||||
RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true);
|
||||
@ -274,6 +273,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) {
|
||||
|
||||
std::vector<VkPipelineColorBlendAttachmentState> blendAttachmentStates;
|
||||
auto& subpass = renderTarget.passes[graphic.descriptor.subpass];
|
||||
/*
|
||||
for ( auto& color : subpass.colors ) {
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
|
||||
0xf,
|
||||
@ -285,16 +285,19 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) {
|
||||
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
/*
|
||||
if ( !blendAttachmentStates.empty() ) {
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
|
||||
0xf,
|
||||
VK_FALSE
|
||||
);
|
||||
}
|
||||
*/
|
||||
blendAttachmentStates.push_back(blendAttachmentState);
|
||||
}
|
||||
*/
|
||||
for ( auto& color : subpass.colors ) {
|
||||
blendAttachmentStates.push_back(renderTarget.attachments[color.attachment].blendState);
|
||||
}
|
||||
// require blending if independentBlend is not an enabled feature
|
||||
if ( !device.enabledFeatures.independentBlend ) {
|
||||
for ( size_t i = 1; i < blendAttachmentStates.size(); ++i ) {
|
||||
blendAttachmentStates[i] = blendAttachmentStates[0];
|
||||
}
|
||||
}
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo colorBlendState = ext::vulkan::initializers::pipelineColorBlendStateCreateInfo(
|
||||
blendAttachmentStates.size(),
|
||||
blendAttachmentStates.data()
|
||||
@ -398,9 +401,13 @@ void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuf
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
}
|
||||
void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
// generate fallback empty texture
|
||||
auto& emptyTexture = Texture2D::empty;
|
||||
|
||||
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
||||
std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
|
||||
std::vector<VkDescriptorImageInfo> inputDescriptors;
|
||||
std::vector<VkDescriptorImageInfo> imageInfos;
|
||||
|
||||
for ( auto& shader : graphic.material.shaders ) {
|
||||
descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() );
|
||||
@ -414,6 +421,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
inputDescriptors.push_back(ext::vulkan::initializers::descriptorImageInfo(
|
||||
renderTarget.attachments[input.attachment].view,
|
||||
input.layout
|
||||
// input.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : input.layout
|
||||
));
|
||||
}
|
||||
{
|
||||
@ -424,42 +432,88 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
auto attachments = inputDescriptors.begin();
|
||||
|
||||
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
|
||||
VkDescriptorBufferInfo* bufferInfo = NULL;
|
||||
|
||||
if ( layout.descriptorCount > 1 ) {
|
||||
switch ( layout.descriptorType ) {
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
|
||||
size_t imageInfosStart = imageInfos.size();
|
||||
// assume we have a texture, and fill it in the slots as defaults
|
||||
for ( size_t i = 0; i < layout.descriptorCount; ++i ) {
|
||||
VkDescriptorImageInfo d = emptyTexture.descriptor;
|
||||
if ( textures != graphic.material.textures.end() ) {
|
||||
d = (textures++)->descriptor;
|
||||
if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && !d.sampler )
|
||||
d.sampler = emptyTexture.sampler.sampler;
|
||||
|
||||
// if ( d.imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL )
|
||||
// d.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
imageInfos.push_back( d );
|
||||
}
|
||||
|
||||
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
layout.binding,
|
||||
&imageInfos[imageInfosStart],
|
||||
imageInfos.size() - imageInfosStart
|
||||
));
|
||||
} break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo* imageInfo = NULL;
|
||||
switch ( layout.descriptorType ) {
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
|
||||
if ( textures == graphic.material.textures.end() ) {
|
||||
imageInfo = &emptyTexture.descriptor;
|
||||
break;
|
||||
}
|
||||
imageInfo = &((textures++)->descriptor);
|
||||
} break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER: {
|
||||
imageInfo = &((samplers++)->descriptor);
|
||||
if ( samplers == graphic.material.samplers.end() ) {
|
||||
std::cout << "samplers == graphic.material.samplers.end()" << std::endl;
|
||||
break;
|
||||
}
|
||||
imageInfo = &((samplers++)->descriptor.info);
|
||||
} break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
|
||||
bufferInfo = &((buffers++)->descriptor);
|
||||
if ( buffers == shader.buffers.end() ) {
|
||||
std::cout << "buffers == shader.buffers.end()" << std::endl;
|
||||
break;
|
||||
}
|
||||
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
layout.binding,
|
||||
&((buffers++)->descriptor)
|
||||
));
|
||||
} break;
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
||||
if ( attachments == inputDescriptors.end() ) {
|
||||
std::cout << "attachments == inputDescriptors.end()" << std::endl;
|
||||
break;
|
||||
}
|
||||
imageInfo = &(*(attachments++));
|
||||
} break;
|
||||
}
|
||||
if ( !bufferInfo && !imageInfo ) continue;
|
||||
if ( bufferInfo )
|
||||
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
layout.binding,
|
||||
bufferInfo
|
||||
));
|
||||
else if ( imageInfo )
|
||||
|
||||
if ( imageInfo ) {
|
||||
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
layout.binding,
|
||||
imageInfo
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vkUpdateDescriptorSets(
|
||||
*device,
|
||||
writeDescriptorSets.size(),
|
||||
|
||||
@ -91,6 +91,10 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
|
||||
|
||||
// this->width = 0; //ext::vulkan::width;
|
||||
// this->height = 0; //ext::vulkan::height;
|
||||
{
|
||||
if ( this->width > 0 ) renderTarget.width = this->width;
|
||||
if ( this->height > 0 ) renderTarget.height = this->height;
|
||||
}
|
||||
|
||||
// Create command buffers
|
||||
{
|
||||
|
||||
@ -21,13 +21,15 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
renderTarget.device = &device;
|
||||
// attach targets
|
||||
struct {
|
||||
size_t albedo, position, normals, depth, output;
|
||||
size_t albedo, normals, position, depth, output, ping, pong;
|
||||
} attachments;
|
||||
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
attachments.position = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // position
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // normals
|
||||
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // normals
|
||||
attachments.position = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // position
|
||||
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true ); // depth
|
||||
// attachments.ping = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
// attachments.pong = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
// Attach swapchain's image as output
|
||||
{
|
||||
attachments.output = renderTarget.attachments.size();
|
||||
@ -36,6 +38,23 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
swapchainAttachment.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
swapchainAttachment.aliased = true;
|
||||
{
|
||||
VkBool32 blendEnabled = VK_TRUE;
|
||||
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
|
||||
writeMask,
|
||||
blendEnabled
|
||||
);
|
||||
if ( blendEnabled == VK_TRUE ) {
|
||||
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
}
|
||||
swapchainAttachment.blendState = blendAttachmentState;
|
||||
}
|
||||
renderTarget.attachments.push_back(swapchainAttachment);
|
||||
}
|
||||
|
||||
@ -43,7 +62,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.albedo, attachments.position, attachments.normals },
|
||||
{ attachments.albedo, attachments.normals, attachments.position },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
@ -53,7 +72,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.albedo, attachments.position, attachments.normals, attachments.depth },
|
||||
{ attachments.albedo, attachments.normals, attachments.position/*, attachments.depth*/ },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
@ -63,10 +82,10 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
{
|
||||
uf::BaseMesh<pod::Vertex_2F2F, uint16_t> mesh;
|
||||
mesh.vertices = {
|
||||
{ {-1.0f, 1.0f}, {0.0f, 0.0f}, },
|
||||
{ {-1.0f, -1.0f}, {0.0f, 1.0f}, },
|
||||
{ {1.0f, -1.0f}, {1.0f, 1.0f}, },
|
||||
{ {1.0f, 1.0f}, {1.0f, 0.0f}, }
|
||||
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
|
||||
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
|
||||
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
|
||||
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
|
||||
};
|
||||
mesh.indices = {
|
||||
0, 1, 2, 0, 2, 3
|
||||
@ -169,6 +188,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
|
||||
RenderTarget& renderTarget = layer->renderTarget;
|
||||
for ( auto& attachment : renderTarget.attachments ) {
|
||||
if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
|
||||
if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
imageMemoryBarrier.image = attachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
@ -218,11 +238,12 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
|
||||
RenderTarget& renderTarget = layer->renderTarget;
|
||||
for ( auto& attachment : renderTarget.attachments ) {
|
||||
if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
|
||||
if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
imageMemoryBarrier.image = attachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = attachment.layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
imageMemoryBarrier.newLayout = attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
attachment.layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
|
||||
@ -17,16 +17,16 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
{
|
||||
renderTarget.device = &device;
|
||||
struct {
|
||||
size_t albedo, position, normals, depth, output;
|
||||
size_t albedo, normals, position, depth, output;
|
||||
} attachments;
|
||||
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
attachments.position = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // position
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // normals
|
||||
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // normals
|
||||
attachments.position = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // position
|
||||
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true ); // depth
|
||||
// Attach swapchain's image as output
|
||||
if ( !false ) {
|
||||
attachments.output = renderTarget.attach( device.formats.color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ); // depth
|
||||
attachments.output = renderTarget.attach( device.formats.color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, true ); // output
|
||||
} else {
|
||||
attachments.output = renderTarget.attachments.size();
|
||||
RenderTarget::Attachment swapchainAttachment;
|
||||
@ -34,13 +34,31 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
swapchainAttachment.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
swapchainAttachment.aliased = true;
|
||||
{
|
||||
VkBool32 blendEnabled = VK_TRUE;
|
||||
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
|
||||
writeMask,
|
||||
blendEnabled
|
||||
);
|
||||
if ( blendEnabled == VK_TRUE ) {
|
||||
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
}
|
||||
swapchainAttachment.blendState = blendAttachmentState;
|
||||
}
|
||||
renderTarget.attachments.push_back(swapchainAttachment);
|
||||
}
|
||||
|
||||
// First pass: write to target
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.albedo, attachments.position, attachments.normals },
|
||||
{ attachments.albedo, attachments.normals, attachments.position },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
@ -50,7 +68,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.albedo, attachments.position, attachments.normals },
|
||||
{ attachments.albedo, attachments.normals, attachments.position/*, attachments.depth*/ },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
|
||||
@ -11,11 +11,6 @@
|
||||
#include <uf/utils/math/transform.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
namespace {
|
||||
// 0 left 1 right
|
||||
uint8_t DOMINANT_EYE = 0;
|
||||
}
|
||||
|
||||
// ext::vulkan::StereoscopicDeferredRenderMode::StereoscopicDeferredRenderMode() : renderTargets({ renderTarget }), blitters({ blitter }) {
|
||||
ext::vulkan::StereoscopicDeferredRenderMode::StereoscopicDeferredRenderMode() : renderTargets({ renderTarget }) {
|
||||
}
|
||||
@ -58,16 +53,18 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) {
|
||||
renderTarget.height = this->height;
|
||||
// attach targets
|
||||
struct {
|
||||
size_t albedo, position, normals, depth, output;
|
||||
size_t albedo, normals, position, depth, output;
|
||||
} attachments;
|
||||
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
attachments.position = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // position
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // normals
|
||||
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ); // depth
|
||||
attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
// Attach swapchain's image as output
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
attachments.position = renderTarget.attach( VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // position
|
||||
attachments.depth = renderTarget.attach( device.formats.depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
|
||||
// attachments.ping = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
// attachments.pong = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
/*
|
||||
// Attach swapchain's image as output
|
||||
if ( !true ) {
|
||||
attachments.swapchain = renderTarget.attachments.size();
|
||||
RenderTarget::Attachment swapchainAttachment;
|
||||
@ -81,8 +78,8 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) {
|
||||
// First pass: fill the G-Buffer
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.albedo, attachments.position, attachments.normals },
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.albedo, attachments.normals, attachments.position },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
@ -90,9 +87,9 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) {
|
||||
// Second pass: write to output
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.albedo, attachments.position, attachments.normals },
|
||||
{ attachments.albedo, attachments.normals, attachments.position/*, attachments.depth*/ },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
@ -100,10 +97,10 @@ void ext::vulkan::StereoscopicDeferredRenderMode::initialize( Device& device ) {
|
||||
{
|
||||
uf::BaseMesh<pod::Vertex_2F2F, uint16_t> mesh;
|
||||
mesh.vertices = {
|
||||
{ {-1.0f, 1.0f}, {0.0f, 0.0f}, },
|
||||
{ {-1.0f, -1.0f}, {0.0f, 1.0f}, },
|
||||
{ {1.0f, -1.0f}, {1.0f, 1.0f}, },
|
||||
{ {1.0f, 1.0f}, {1.0f, 0.0f}, }
|
||||
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
|
||||
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
|
||||
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
|
||||
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
|
||||
};
|
||||
mesh.indices = {
|
||||
0, 1, 2, 0, 2, 3
|
||||
@ -230,13 +227,17 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
|
||||
for ( auto layer : layers ) {
|
||||
if ( layer->getName() == "" ) continue;
|
||||
RenderTarget& renderTarget = layer->renderTarget;
|
||||
imageMemoryBarrier.image = renderTarget.attachments[0].image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
imageMemoryBarrier.oldLayout = renderTarget.attachments[0].layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
renderTarget.attachments[0].layout = imageMemoryBarrier.newLayout;
|
||||
for ( auto& attachment : renderTarget.attachments ) {
|
||||
if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
|
||||
if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
imageMemoryBarrier.image = attachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
imageMemoryBarrier.oldLayout = attachment.layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
attachment.layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
}
|
||||
|
||||
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
@ -258,7 +259,9 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
|
||||
}
|
||||
}
|
||||
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
|
||||
blitter.record(commands[i]);
|
||||
{
|
||||
blitter.record(commands[i]);
|
||||
}
|
||||
// render gui layer
|
||||
{
|
||||
for ( auto _ : layers ) {
|
||||
@ -269,149 +272,117 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
|
||||
blitter.record(commands[i]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
|
||||
if ( ext::openvr::renderPass == DOMINANT_EYE ) {
|
||||
viewport.width = (float) ::ext::vulkan::width;
|
||||
viewport.height = (float) ::ext::vulkan::height;
|
||||
scissor.extent.width = ::ext::vulkan::width;
|
||||
scissor.extent.height = ::ext::vulkan::height;
|
||||
|
||||
vkCmdSetViewport(commands[i], 0, 1, &viewport);
|
||||
vkCmdSetScissor(commands[i], 0, 1, &scissor);
|
||||
this->blitter.createCommandBuffer(commands[i]);
|
||||
// render gui layer
|
||||
{
|
||||
for ( auto layer : layers ) {
|
||||
if ( layer->getName() == "Gui" ) {
|
||||
RenderTargetRenderMode* guiLayer = (RenderTargetRenderMode*) layer;
|
||||
if ( guiLayer->blitter.subpass == 2 ) guiLayer->blitter.createCommandBuffer(commands[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
vkCmdEndRenderPass(commands[i]);
|
||||
|
||||
for ( auto layer : layers ) {
|
||||
if ( layer->getName() == "" ) continue;
|
||||
RenderTarget& renderTarget = layer->renderTarget;
|
||||
imageMemoryBarrier.image = renderTarget.attachments[0].image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = renderTarget.attachments[0].layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
renderTarget.attachments[0].layout = imageMemoryBarrier.newLayout;
|
||||
for ( auto& attachment : renderTarget.attachments ) {
|
||||
if ( !(attachment.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
|
||||
if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
|
||||
imageMemoryBarrier.image = attachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = attachment.layout;
|
||||
imageMemoryBarrier.newLayout = attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
attachment.layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Blit eye to swapchain
|
||||
{
|
||||
// if ( false ) {
|
||||
auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain");
|
||||
{
|
||||
auto& renderTarget = swapchainRender.renderTarget;
|
||||
float width = renderTarget.width;
|
||||
float height = renderTarget.height;
|
||||
|
||||
std::vector<VkClearValue> clearValues; clearValues.resize(2);
|
||||
clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } };
|
||||
clearValues[1].depthStencil = { 1.0f, 0 };
|
||||
|
||||
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
||||
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassBeginInfo.pNext = nullptr;
|
||||
renderPassBeginInfo.renderArea.offset.x = 0;
|
||||
renderPassBeginInfo.renderArea.offset.y = 0;
|
||||
renderPassBeginInfo.renderArea.extent.width = width;
|
||||
renderPassBeginInfo.renderArea.extent.height = height;
|
||||
renderPassBeginInfo.clearValueCount = clearValues.size();
|
||||
renderPassBeginInfo.pClearValues = &clearValues[0];
|
||||
renderPassBeginInfo.renderPass = renderTarget.renderPass;
|
||||
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];
|
||||
|
||||
// Update dynamic viewport state
|
||||
VkViewport viewport = {};
|
||||
viewport.width = (float) width;
|
||||
viewport.height = (float) height;
|
||||
viewport.minDepth = (float) 0.0f;
|
||||
viewport.maxDepth = (float) 1.0f;
|
||||
|
||||
// Update dynamic scissor state
|
||||
VkRect2D scissor = {};
|
||||
scissor.extent.width = width;
|
||||
scissor.extent.height = height;
|
||||
scissor.offset.x = 0;
|
||||
scissor.offset.y = 0;
|
||||
|
||||
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdEndRenderPass(commands[i]);
|
||||
|
||||
}
|
||||
{
|
||||
auto& renderTarget = DOMINANT_EYE == 0 ? renderTargets.left : renderTargets.right;
|
||||
VkImageBlit imageBlitRegion{};
|
||||
imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlitRegion.srcSubresource.layerCount = 1;
|
||||
imageBlitRegion.srcOffsets[1] = { width, height, 1 };
|
||||
imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlitRegion.dstSubresource.layerCount = 1;
|
||||
imageBlitRegion.dstOffsets[1] = {
|
||||
swapchainRender.width > 0 ? swapchainRender.width : ext::vulkan::width,
|
||||
swapchainRender.height > 0 ? swapchainRender.height : ext::vulkan::height,
|
||||
1
|
||||
};
|
||||
|
||||
auto& outputAttachment = renderTarget.attachments[renderTarget.attachments.size()-1];
|
||||
// Transition to KHR
|
||||
// Blit eye to swapchain
|
||||
if ( ext::openvr::dominantEye == ext::openvr::renderPass ) {
|
||||
// if ( false ) {
|
||||
// transition swapchain to proper layout
|
||||
auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain");
|
||||
{
|
||||
imageMemoryBarrier.image = outputAttachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = outputAttachment.layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
outputAttachment.layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
{
|
||||
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
|
||||
auto& renderTarget = swapchainRender.renderTarget;
|
||||
float width = renderTarget.width;
|
||||
float height = renderTarget.height;
|
||||
|
||||
std::vector<VkClearValue> clearValues; clearValues.resize(2);
|
||||
clearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } };
|
||||
clearValues[1].depthStencil = { 1.0f, 0 };
|
||||
|
||||
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
||||
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassBeginInfo.pNext = nullptr;
|
||||
renderPassBeginInfo.renderArea.offset.x = 0;
|
||||
renderPassBeginInfo.renderArea.offset.y = 0;
|
||||
renderPassBeginInfo.renderArea.extent.width = width;
|
||||
renderPassBeginInfo.renderArea.extent.height = height;
|
||||
renderPassBeginInfo.clearValueCount = clearValues.size();
|
||||
renderPassBeginInfo.pClearValues = &clearValues[0];
|
||||
renderPassBeginInfo.renderPass = renderTarget.renderPass;
|
||||
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];
|
||||
|
||||
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdEndRenderPass(commands[i]);
|
||||
}
|
||||
|
||||
vkCmdBlitImage(
|
||||
commands[i],
|
||||
outputAttachment.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
swapchainRender.renderTarget.attachments[i].image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
&imageBlitRegion,
|
||||
VK_FILTER_LINEAR
|
||||
);
|
||||
{
|
||||
VkImageBlit imageBlitRegion{};
|
||||
imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlitRegion.srcSubresource.layerCount = 1;
|
||||
imageBlitRegion.srcOffsets[1] = { width, height, 1 };
|
||||
imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageBlitRegion.dstSubresource.layerCount = 1;
|
||||
imageBlitRegion.dstOffsets[1] = {
|
||||
swapchainRender.width > 0 ? swapchainRender.width : ext::vulkan::width,
|
||||
swapchainRender.height > 0 ? swapchainRender.height : ext::vulkan::height,
|
||||
1
|
||||
};
|
||||
|
||||
{
|
||||
imageMemoryBarrier.image = outputAttachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = outputAttachment.layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
outputAttachment.layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
{
|
||||
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
|
||||
auto& outputAttachment = renderTarget.attachments[renderTarget.attachments.size()-1];
|
||||
// Transition to KHR
|
||||
{
|
||||
imageMemoryBarrier.image = outputAttachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = outputAttachment.layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
outputAttachment.layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
{
|
||||
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
|
||||
vkCmdBlitImage(
|
||||
commands[i],
|
||||
outputAttachment.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
swapchainRender.renderTarget.attachments[i].image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
&imageBlitRegion,
|
||||
VK_FILTER_LINEAR
|
||||
);
|
||||
|
||||
{
|
||||
imageMemoryBarrier.image = outputAttachment.image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = outputAttachment.layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
outputAttachment.layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
{
|
||||
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imageMemoryBarrier.oldLayout = swapchainRender.renderTarget.attachments[i].layout;
|
||||
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
|
||||
swapchainRender.renderTarget.attachments[i].layout = imageMemoryBarrier.newLayout;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,11 @@ void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFla
|
||||
pass.access = access;
|
||||
for ( auto& i : colors ) pass.colors.push_back( { (uint32_t) i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } );
|
||||
for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
|
||||
// for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
|
||||
if ( depth < attachments.size() ) pass.depth = { (uint32_t) depth, attachments[depth].layout };
|
||||
passes.push_back(pass);
|
||||
}
|
||||
size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, Attachment* attachment ) {
|
||||
size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usage, VkImageLayout layout, bool blend, Attachment* attachment ) {
|
||||
uint32_t width = this->width > 0 ? this->width : ext::vulkan::width;
|
||||
uint32_t height = this->height > 0 ? this->height : ext::vulkan::height;
|
||||
|
||||
@ -98,6 +99,30 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
|
||||
|
||||
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->view));
|
||||
|
||||
{
|
||||
VkBool32 blendEnabled = VK_FALSE;
|
||||
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT;
|
||||
|
||||
if ( blend ) {
|
||||
blendEnabled = VK_TRUE;
|
||||
writeMask |= VK_COLOR_COMPONENT_A_BIT;
|
||||
}
|
||||
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
|
||||
writeMask,
|
||||
blendEnabled
|
||||
);
|
||||
if ( blendEnabled == VK_TRUE ) {
|
||||
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
}
|
||||
attachment->blendState = blendAttachmentState;
|
||||
}
|
||||
|
||||
return attachments.size()-1;
|
||||
}
|
||||
void ext::vulkan::RenderTarget::initialize( Device& device ) {
|
||||
@ -112,7 +137,8 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
|
||||
if ( initialized ) {
|
||||
for ( auto& attachment: this->attachments ) {
|
||||
if ( attachment.aliased ) continue;
|
||||
attach( attachment.format, attachment.usage, attachment.layout, &attachment );
|
||||
bool blend = attachment.blendState.blendEnable == VK_TRUE;
|
||||
attach( attachment.format, attachment.usage, attachment.layout, blend, &attachment );
|
||||
}
|
||||
}
|
||||
// ensure attachments are already created
|
||||
@ -131,7 +157,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
|
||||
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
description.finalLayout = attachment.layout;
|
||||
description.finalLayout = attachment.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : attachment.layout;
|
||||
description.flags = 0;
|
||||
|
||||
attachments.push_back(description);
|
||||
@ -191,6 +217,39 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
|
||||
dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||
dependencies.push_back(dependency);
|
||||
}
|
||||
|
||||
// depth dependency
|
||||
{
|
||||
VkSubpassDependency dependency;
|
||||
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
||||
|
||||
|
||||
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
dependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
dependency.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
dependency.dstSubpass = 0;
|
||||
dependency.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||
dependency.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
dependencies.push_back(dependency);
|
||||
}
|
||||
{
|
||||
VkSubpassDependency dependency;
|
||||
dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
||||
|
||||
|
||||
dependency.srcSubpass = 0;
|
||||
dependency.srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
|
||||
dependency.dstSubpass = i == 1 ? VK_SUBPASS_EXTERNAL : 1;
|
||||
dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
dependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
dependencies.push_back(dependency);
|
||||
}
|
||||
|
||||
/*
|
||||
for ( auto& dependency : dependencies ) {
|
||||
std::cout << "Pass: " << dependency.srcSubpass << " -> " << dependency.dstSubpass << std::endl;
|
||||
|
||||
@ -3,29 +3,30 @@
|
||||
#include <uf/utils/image/image.h>
|
||||
#include <uf/ext/vulkan/vulkan.h>
|
||||
|
||||
void ext::vulkan::Sampler::initialize( Device& device, VkFilter filter ) {
|
||||
ext::vulkan::Texture2D ext::vulkan::Texture2D::empty;
|
||||
|
||||
void ext::vulkan::Sampler::initialize( Device& device ) {
|
||||
this->device = &device;
|
||||
this->filter = filter;
|
||||
|
||||
{
|
||||
VkSamplerCreateInfo samplerCreateInfo = {};
|
||||
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerCreateInfo.magFilter = filter;
|
||||
samplerCreateInfo.minFilter = filter;
|
||||
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
samplerCreateInfo.mipLodBias = 0.0f;
|
||||
samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER;
|
||||
samplerCreateInfo.minLod = 0.0f;
|
||||
samplerCreateInfo.maxLod = 0.0f;
|
||||
samplerCreateInfo.maxAnisotropy = 1.0f;
|
||||
samplerCreateInfo.minFilter = descriptor.filter.min;
|
||||
samplerCreateInfo.magFilter = descriptor.filter.mag;
|
||||
samplerCreateInfo.addressModeU = descriptor.addressMode.u;
|
||||
samplerCreateInfo.addressModeV = descriptor.addressMode.v;
|
||||
samplerCreateInfo.addressModeW = descriptor.addressMode.w;
|
||||
|
||||
samplerCreateInfo.mipmapMode = descriptor.mip.mode;
|
||||
samplerCreateInfo.mipLodBias = descriptor.mip.lodBias;
|
||||
samplerCreateInfo.compareOp = descriptor.compareOp;
|
||||
samplerCreateInfo.minLod = descriptor.lod.min;
|
||||
samplerCreateInfo.maxLod = descriptor.lod.max;
|
||||
samplerCreateInfo.maxAnisotropy = descriptor.maxAnisotropy;
|
||||
VK_CHECK_RESULT(vkCreateSampler(device.logicalDevice, &samplerCreateInfo, nullptr, &sampler));
|
||||
}
|
||||
|
||||
{
|
||||
descriptor.sampler = sampler;
|
||||
descriptor.info.sampler = sampler;
|
||||
}
|
||||
}
|
||||
void ext::vulkan::Sampler::destroy() {
|
||||
@ -274,7 +275,6 @@ void ext::vulkan::Texture2D::loadFromFile(
|
||||
image.getDimensions()[1],
|
||||
device,
|
||||
copyQueue,
|
||||
sampler.filter,
|
||||
imageUsageFlags,
|
||||
imageLayout
|
||||
);
|
||||
@ -347,7 +347,6 @@ void ext::vulkan::Texture2D::loadFromImage(
|
||||
image.getDimensions()[1],
|
||||
device,
|
||||
copyQueue,
|
||||
sampler.filter,
|
||||
imageUsageFlags,
|
||||
imageLayout
|
||||
);
|
||||
@ -360,7 +359,6 @@ void ext::vulkan::Texture2D::fromBuffers(
|
||||
uint32_t texHeight,
|
||||
Device& device,
|
||||
VkQueue copyQueue,
|
||||
VkFilter filter,
|
||||
VkImageUsageFlags imageUsageFlags,
|
||||
VkImageLayout imageLayout
|
||||
) {
|
||||
@ -466,7 +464,7 @@ void ext::vulkan::Texture2D::fromBuffers(
|
||||
staging.destroy();
|
||||
|
||||
// Create sampler
|
||||
sampler.initialize( device, sampler.filter );
|
||||
sampler.initialize( device );
|
||||
|
||||
// Create image view
|
||||
VkImageViewCreateInfo viewCreateInfo = {};
|
||||
@ -535,7 +533,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
|
||||
device.flushCommandBuffer(layoutCmd, copyQueue, true);
|
||||
|
||||
// Create sampler
|
||||
sampler.initialize( device, sampler.filter );
|
||||
sampler.initialize( device );
|
||||
|
||||
// Create image view
|
||||
VkImageViewCreateInfo viewCreateInfo = ext::vulkan::initializers::imageViewCreateInfo();
|
||||
@ -556,7 +554,7 @@ void ext::vulkan::Texture2D::aliasAttachment( const RenderTarget::Attachment& at
|
||||
deviceMemory = attachment.mem;
|
||||
|
||||
// Create sampler
|
||||
if ( createSampler ) sampler.initialize( ext::vulkan::device, sampler.filter );
|
||||
if ( createSampler ) sampler.initialize( ext::vulkan::device );
|
||||
|
||||
this->updateDescriptors();
|
||||
}
|
||||
@ -12,6 +12,8 @@ uint32_t ext::vulkan::width = 1280;
|
||||
uint32_t ext::vulkan::height = 720;
|
||||
|
||||
bool ext::vulkan::validation = true;
|
||||
std::vector<std::string> ext::vulkan::validationFilters;
|
||||
std::vector<std::string> ext::vulkan::requestedDeviceFeatures;
|
||||
ext::vulkan::Device ext::vulkan::device;
|
||||
ext::vulkan::Allocator ext::vulkan::allocator;
|
||||
ext::vulkan::Swapchain ext::vulkan::swapchain;
|
||||
@ -46,7 +48,11 @@ VKAPI_ATTR VkBool32 VKAPI_CALL ext::vulkan::debugCallback(
|
||||
void* pUserData
|
||||
) {
|
||||
if ( messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) return VK_FALSE;
|
||||
uf::iostream << "[Validation Layer] " << pCallbackData->pMessage << "\n";
|
||||
std::string message = pCallbackData->pMessage;
|
||||
for ( auto& filter : ext::vulkan::validationFilters ) {
|
||||
if ( message.find(filter) != std::string::npos ) return VK_FALSE;
|
||||
}
|
||||
uf::iostream << "[Validation Layer] " << message << "\n";
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
@ -220,6 +226,15 @@ void ext::vulkan::initialize( uint8_t stage ) {
|
||||
allocatorInfo.device = device.logicalDevice;
|
||||
vmaCreateAllocator(&allocatorInfo, &allocator);
|
||||
}
|
||||
{
|
||||
std::vector<uint8_t> pixels = {
|
||||
255, 0, 255, 255, 0, 0, 0, 255,
|
||||
0, 0, 0, 255, 255, 0, 255, 255,
|
||||
};
|
||||
Texture2D::empty.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
Texture2D::empty.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
Texture2D::empty.fromBuffers( (void*) &pixels[0], pixels.size(), VK_FORMAT_R8G8B8A8_UNORM, 2, 2, ext::vulkan::device, ext::vulkan::device.graphicsQueue, VK_IMAGE_USAGE_SAMPLED_BIT );
|
||||
}
|
||||
for ( auto& renderMode : renderModes ) {
|
||||
if ( !renderMode ) continue;
|
||||
renderMode->initialize(device);
|
||||
@ -234,14 +249,7 @@ void ext::vulkan::initialize( uint8_t stage ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( graphic.initialized ) return;
|
||||
/*
|
||||
if ( !entity->hasComponent<uf::Mesh>() ) return;
|
||||
uf::MeshBase& mesh = entity->getComponent<uf::Mesh>();
|
||||
ext::vulkan::Graphic& graphic = mesh.graphic;
|
||||
if ( !mesh.generated ) return;
|
||||
if ( !graphic.process ) return;
|
||||
if ( graphic.initialized ) return;
|
||||
*/
|
||||
|
||||
graphic.initializePipeline();
|
||||
ext::vulkan::rebuild = true;
|
||||
};
|
||||
@ -269,12 +277,7 @@ void ext::vulkan::tick() {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( graphic.initialized ) return;
|
||||
/*
|
||||
if ( !entity->hasComponent<uf::Mesh>() ) return;
|
||||
uf::MeshBase& mesh = entity->getComponent<uf::Mesh>();
|
||||
ext::vulkan::Graphic& graphic = mesh.graphic;
|
||||
if ( !mesh.generated ) return;
|
||||
*/
|
||||
|
||||
if ( !graphic.process ) return;
|
||||
if ( graphic.initialized ) return;
|
||||
graphic.initializePipeline();
|
||||
@ -320,6 +323,8 @@ void ext::vulkan::destroy() {
|
||||
ext::vulkan::mutex.lock();
|
||||
vkDeviceWaitIdle( device );
|
||||
|
||||
Texture2D::empty.destroy();
|
||||
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
uf::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
|
||||
@ -18,6 +18,7 @@ uf::Camera::Camera() :
|
||||
this->m_settings.offset = {0, 0, 0};
|
||||
this->m_settings.mode = 1;
|
||||
|
||||
this->setModel(uf::matrix::identity());
|
||||
this->setView(uf::matrix::identity());
|
||||
this->setProjection(uf::matrix::identity());
|
||||
|
||||
@ -61,6 +62,7 @@ const pod::Transform<>& uf::Camera::getTransform() const {
|
||||
}
|
||||
|
||||
pod::Matrix4& uf::Camera::getView( size_t eye ) {
|
||||
// if ( !this->m_settings.stereoscopic ) eye = 0;
|
||||
switch ( eye ) {
|
||||
case 0:
|
||||
return this->m_matrices.left.view;
|
||||
@ -80,6 +82,7 @@ pod::Matrix4& uf::Camera::getView( size_t eye ) {
|
||||
*/
|
||||
}
|
||||
pod::Matrix4& uf::Camera::getProjection( size_t eye ) {
|
||||
// if ( !this->m_settings.stereoscopic ) eye = 0;
|
||||
switch ( eye ) {
|
||||
case 0:
|
||||
return this->m_matrices.left.projection;
|
||||
@ -103,6 +106,7 @@ pod::Matrix4& uf::Camera::getModel() {
|
||||
}
|
||||
|
||||
const pod::Matrix4& uf::Camera::getView( size_t eye ) const {
|
||||
// if ( !this->m_settings.stereoscopic ) eye = 0;
|
||||
switch ( eye ) {
|
||||
case 0:
|
||||
return this->m_matrices.left.view;
|
||||
@ -122,6 +126,7 @@ const pod::Matrix4& uf::Camera::getView( size_t eye ) const {
|
||||
*/
|
||||
}
|
||||
const pod::Matrix4& uf::Camera::getProjection( size_t eye ) const {
|
||||
// if ( !this->m_settings.stereoscopic ) eye = 0;
|
||||
switch ( eye ) {
|
||||
case 0:
|
||||
return this->m_matrices.left.projection;
|
||||
@ -177,6 +182,7 @@ void uf::Camera::setTransform( const pod::Transform<>& transform ) {
|
||||
this->update(true);
|
||||
}
|
||||
void uf::Camera::setView( const pod::Matrix4& mat, size_t i ) {
|
||||
// if ( !this->m_settings.stereoscopic ) i = 2;
|
||||
switch ( i ) {
|
||||
case 0:
|
||||
this->m_matrices.left.view = mat;
|
||||
@ -191,6 +197,7 @@ void uf::Camera::setView( const pod::Matrix4& mat, size_t i ) {
|
||||
}
|
||||
}
|
||||
void uf::Camera::setProjection( const pod::Matrix4& mat, size_t i ) {
|
||||
// if ( !this->m_settings.stereoscopic ) i = 2;
|
||||
switch ( i ) {
|
||||
case 0:
|
||||
this->m_matrices.left.projection = mat;
|
||||
@ -235,7 +242,9 @@ void uf::Camera::ortho( const pod::Vector2& lr, const pod::Vector2& bt, const po
|
||||
|
||||
this->update(true);
|
||||
}
|
||||
|
||||
void uf::Camera::setStereoscopic(bool settings) {
|
||||
this->m_settings.stereoscopic = settings;
|
||||
}
|
||||
void uf::Camera::update(bool override) {
|
||||
if ( !override && !this->modified() ) return;
|
||||
this->updateView();
|
||||
@ -243,7 +252,7 @@ void uf::Camera::update(bool override) {
|
||||
this->m_modified = true;
|
||||
}
|
||||
void uf::Camera::updateView() {
|
||||
if ( ext::openvr::context ) {
|
||||
if ( this->m_settings.stereoscopic && ext::openvr::context ) {
|
||||
pod::Transform<>& transform = this->getTransform();
|
||||
pod::Vector3t<> position = transform.position;
|
||||
if ( transform.reference ) position += transform.reference->position;
|
||||
@ -251,9 +260,10 @@ void uf::Camera::updateView() {
|
||||
|
||||
pod::Transform<> flatten = uf::transform::flatten( transform );
|
||||
pod::Matrix4t<> translation = uf::matrix::translate( uf::matrix::identity(), position );
|
||||
pod::Matrix4t<> rotation = uf::quaternion::matrix( flatten.orientation );
|
||||
pod::Matrix4t<> rotation = uf::quaternion::matrix( flatten.orientation * pod::Vector4f{1,1,1,-1} );
|
||||
|
||||
pod::Matrix4t<> view = uf::matrix::inverse( translation * rotation );
|
||||
|
||||
transform.orientation = ext::openvr::hmdQuaternion();
|
||||
this->setView( ext::openvr::hmdViewMatrix(vr::Eye_Left, view ), 0 );
|
||||
this->setView( ext::openvr::hmdViewMatrix(vr::Eye_Right, view ), 1 );
|
||||
@ -301,8 +311,11 @@ void uf::Camera::updateView() {
|
||||
pod::Matrix4t<> translation = uf::matrix::translate( uf::matrix::identity(), position * -1 );
|
||||
pod::Transform<> flatten = uf::transform::flatten(transform, true);
|
||||
pod::Matrix4t<> rotation = uf::quaternion::matrix( flatten.orientation );
|
||||
pod::Matrix4t<> scale = uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity(), transform.scale ) );
|
||||
|
||||
this->setView(rotation * translation);
|
||||
// std::cout << transform.scale.x << ", " << transform.scale.y << ", " << transform.scale.z << std::endl;
|
||||
|
||||
this->setView(rotation * translation * scale);
|
||||
/*
|
||||
pod::Transform<> transform = this->getTransform();
|
||||
if ( transform.reference ) transform.position += transform.reference->position;
|
||||
@ -316,7 +329,7 @@ void uf::Camera::updateView() {
|
||||
}
|
||||
}
|
||||
void uf::Camera::updateProjection() {
|
||||
if ( ext::openvr::context ) {
|
||||
if ( this->m_settings.stereoscopic && ext::openvr::context ) {
|
||||
// ::projection.left = ext::openvr::hmdProjectionMatrix( vr::Eye_Left, this->m_settings.perspective.bounds.x, this->m_settings.perspective.bounds.y );
|
||||
// ::projection.right = ext::openvr::hmdProjectionMatrix( vr::Eye_Right, this->m_settings.perspective.bounds.x, this->m_settings.perspective.bounds.y );
|
||||
this->setProjection( ext::openvr::hmdProjectionMatrix( vr::Eye_Left, this->m_settings.perspective.bounds.x, this->m_settings.perspective.bounds.y ), 0 );
|
||||
|
||||
@ -4,6 +4,10 @@
|
||||
#include <fstream> // std::fstream
|
||||
#include <iostream> // std::fstream
|
||||
#include <png/png.h> // libpng
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <gltf/stb_image.h>
|
||||
|
||||
// C-tor
|
||||
// Default
|
||||
uf::Image::Image() :
|
||||
@ -58,9 +62,6 @@ uf::Image::Image( const Image::container_t& copy, const Image::vec2_t& size ) :
|
||||
|
||||
}
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
std::string uf::Image::getFilename() const {
|
||||
return this->m_filename;
|
||||
}
|
||||
@ -189,7 +190,7 @@ bool uf::Image::open( const std::string& filename ) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void uf::Image::loadFromBuffer( const Image::pixel_t::type_t* pointer, const pod::Vector2ui& size, std::size_t bit_depth, std::size_t channels ) {
|
||||
void uf::Image::loadFromBuffer( const Image::pixel_t::type_t* pointer, const pod::Vector2ui& size, std::size_t bit_depth, std::size_t channels, bool flip ) {
|
||||
this->m_dimensions = size;
|
||||
this->m_bpp = bit_depth * channels;
|
||||
this->m_channels = channels;
|
||||
@ -199,6 +200,20 @@ void uf::Image::loadFromBuffer( const Image::pixel_t::type_t* pointer, const pod
|
||||
this->m_pixels.resize( len );
|
||||
//for ( size_t i = 0; i < len; ++i ) this->m_pixels[i] = pointer[i];
|
||||
memcpy( &this->m_pixels[0], pointer, len );
|
||||
|
||||
if ( flip ) {
|
||||
auto w = this->m_dimensions.x;
|
||||
auto h = this->m_dimensions.y;
|
||||
uint8_t* pixels = &this->m_pixels[0];
|
||||
for (uint j = 0; j * 2 < h; ++j) {
|
||||
uint x = j * w * this->m_bpp/8;
|
||||
uint y = (h - 1 - j) * w * this->m_bpp/8;
|
||||
for (uint i = w * this->m_bpp/8; i > 0; --i) {
|
||||
std::swap( pixels[x], pixels[y] );
|
||||
++x, ++y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void uf::Image::loadFromBuffer( const Image::container_t& container, const pod::Vector2ui& size, std::size_t bit_depth, std::size_t channels, bool flip ) {
|
||||
this->m_dimensions = size;
|
||||
@ -206,10 +221,10 @@ void uf::Image::loadFromBuffer( const Image::container_t& container, const pod::
|
||||
this->m_channels = channels;
|
||||
this->m_pixels = container;
|
||||
|
||||
uint8_t* pixels = &this->m_pixels[0];
|
||||
if ( flip ) {
|
||||
auto w = this->m_dimensions.x;
|
||||
auto h = this->m_dimensions.y;
|
||||
uint8_t* pixels = &this->m_pixels[0];
|
||||
for (uint j = 0; j * 2 < h; ++j) {
|
||||
uint x = j * w * this->m_bpp/8;
|
||||
uint y = (h - 1 - j) * w * this->m_bpp/8;
|
||||
|
||||
@ -1,446 +1,62 @@
|
||||
#include <uf/utils/math/collision.h>
|
||||
#include <uf/utils/math/collision/gjk.h>
|
||||
#include <uf/utils/math/collision/boundingbox.h>
|
||||
#include <uf/utils/math/collision/sphere.h>
|
||||
#include <uf/utils/math/collision/mesh.h>
|
||||
#include <uf/utils/math/collision/modular.h>
|
||||
#include <iostream>
|
||||
|
||||
/*
|
||||
pod::Simplex::Simplex( const pod::Vector3& b, const pod::Vector3& c, const pod::Vector3& d ) {
|
||||
this->set(b, c, d);
|
||||
}
|
||||
void pod::Simplex::add( const pod::Vector3& a ) {
|
||||
this->d = this->c;
|
||||
this->c = this->b;
|
||||
this->b = a;
|
||||
}
|
||||
void pod::Simplex::set( const pod::Vector3& b, const pod::Vector3& c, const pod::Vector3& d ) {
|
||||
this->b = b;
|
||||
this->c = c;
|
||||
this->d = d;
|
||||
if ( b != pod::Vector3{} ) this->size++;
|
||||
if ( c != pod::Vector3{} ) this->size++;
|
||||
if ( d != pod::Vector3{} ) this->size++;
|
||||
}
|
||||
*/
|
||||
uf::Collider::~Collider(){}
|
||||
std::string UF_API uf::Collider::type() const { return ""; }
|
||||
uf::Collider::Manifold UF_API uf::Collider::intersects( const uf::Collider& y ) const {
|
||||
const uf::Collider& x = *this;
|
||||
pod::Simplex simplex;
|
||||
pod::Vector3 direction = pod::Vector3{ 1.0f, 0.0f, 0.0f };
|
||||
|
||||
uf::Collider::Manifold manifold(x, y);
|
||||
double dot = -0.1;
|
||||
uint iterations = 0;
|
||||
uint iterations_cap = 25;
|
||||
while ( iterations++ < iterations_cap ) {
|
||||
direction = uf::vector::normalize(direction);
|
||||
|
||||
pod::Simplex::SupportPoint a;
|
||||
a.a = x.support(direction);
|
||||
a.b = y.support(-direction);
|
||||
a.v = a.a - a.b;
|
||||
|
||||
if ( (dot = a.dot(direction)) < 0 ) {
|
||||
return manifold;
|
||||
}
|
||||
if( simplex.size == 0 ) {
|
||||
simplex.b = a;
|
||||
|
||||
direction = direction * -1;
|
||||
simplex.size = 1;
|
||||
continue;
|
||||
}
|
||||
if ( simplex.size == 1 ) {
|
||||
direction = uf::vector::cross(a.cross(simplex.b), a.v);
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
simplex.size = 2;
|
||||
continue;
|
||||
}
|
||||
if ( simplex.size == 2 ) {
|
||||
pod::Vector3 ao = a * -1;
|
||||
pod::Vector3 ab = simplex.b - a;
|
||||
pod::Vector3 ac = simplex.c - a;
|
||||
pod::Vector3 abc = uf::vector::cross(ab, ac);
|
||||
pod::Vector3 abP = uf::vector::cross(ab, abc);
|
||||
if ( uf::vector::dot(abP, ao) > 0 ) {
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = uf::vector::cross(ab, ao);
|
||||
continue;
|
||||
}
|
||||
pod::Vector3 acP = uf::vector::cross(abc, ac);
|
||||
if ( uf::vector::dot(acP, ao) > 0 ) {
|
||||
simplex.b = a;
|
||||
|
||||
direction = uf::vector::cross(ac, ao);
|
||||
continue;
|
||||
}
|
||||
if ( uf::vector::dot(abc, ao) > 0 ) {
|
||||
simplex.d = simplex.c;
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = abc;
|
||||
continue;
|
||||
}
|
||||
simplex.d = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = abc * -1;
|
||||
simplex.size = 3;
|
||||
continue;
|
||||
}
|
||||
if ( simplex.size == 3 ) {
|
||||
pod::Vector3 ao = a * -1;
|
||||
pod::Vector3 ab = simplex.b - a;
|
||||
pod::Vector3 ac = simplex.c - a;
|
||||
pod::Vector3 abc = uf::vector::cross(ab, ac);
|
||||
pod::Vector3 ad, acd, adb;
|
||||
if ( uf::vector::dot(abc, ao) > 0 ) {
|
||||
goto check_face;
|
||||
}
|
||||
ad = simplex.d - a;
|
||||
acd = uf::vector::cross(ac, ad);
|
||||
if ( uf::vector::dot(acd, ao) > 0 ) {
|
||||
simplex.b = simplex.c;
|
||||
simplex.c = simplex.d;
|
||||
|
||||
ab = ac;
|
||||
ac = ad;
|
||||
abc = acd;
|
||||
|
||||
goto check_face;
|
||||
}
|
||||
goto EPA;
|
||||
|
||||
check_face:
|
||||
pod::Vector3 abP = uf::vector::cross(ab, abc);
|
||||
if ( uf::vector::dot(abP, ao) > 0 ) {
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = uf::vector::cross(uf::vector::cross(ab, ao), ab);
|
||||
simplex.size = 2;
|
||||
continue;
|
||||
}
|
||||
pod::Vector3 acP = uf::vector::cross(abc, ac);
|
||||
if ( uf::vector::dot(acP, ao) > 0 ) {
|
||||
simplex.b = a;
|
||||
direction = uf::vector::cross(uf::vector::cross(ac, ao), ac);
|
||||
simplex.size = 2;
|
||||
continue;
|
||||
}
|
||||
simplex.d = simplex.c;
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
direction = abc;
|
||||
simplex.size = 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
goto EPA;
|
||||
|
||||
EPA:
|
||||
manifold.colliding = true;
|
||||
manifold.normal = direction;
|
||||
manifold.depth = dot;
|
||||
return manifold;
|
||||
}
|
||||
/*
|
||||
|
||||
*/
|
||||
UF_API uf::AABBox::AABBox( const pod::Vector3& origin, const pod::Vector3& corner ) {
|
||||
this->m_origin = origin;
|
||||
this->m_corner = corner;
|
||||
}
|
||||
std::string UF_API uf::AABBox::type() const { return "AABBox"; }
|
||||
pod::Vector3* UF_API uf::AABBox::expand() const {
|
||||
pod::Vector3* raw = new pod::Vector3[8];
|
||||
raw[0] = pod::Vector3{ this->m_corner.x, this->m_corner.y, this->m_corner.z};
|
||||
raw[1] = pod::Vector3{ this->m_corner.x, this->m_corner.y, -this->m_corner.z};
|
||||
raw[2] = pod::Vector3{ -this->m_corner.x, this->m_corner.y, -this->m_corner.z};
|
||||
raw[3] = pod::Vector3{ -this->m_corner.x, this->m_corner.y, this->m_corner.z};
|
||||
raw[4] = pod::Vector3{ -this->m_corner.x, -this->m_corner.y, this->m_corner.z};
|
||||
raw[5] = pod::Vector3{ this->m_corner.x, -this->m_corner.y, this->m_corner.z};
|
||||
raw[6] = pod::Vector3{ this->m_corner.x, -this->m_corner.y, -this->m_corner.z};
|
||||
raw[7] = pod::Vector3{ -this->m_corner.x, -this->m_corner.y, this->m_corner.z};
|
||||
|
||||
for ( uint i = 0; i < 8; i++ ) raw[0] += this->m_origin;
|
||||
|
||||
return raw;
|
||||
}
|
||||
pod::Vector3 UF_API uf::AABBox::support( const pod::Vector3& direction ) const {
|
||||
pod::Vector3 res;
|
||||
|
||||
res[0] = this->m_origin.x + this->m_corner.x * (direction.x >= 0 ? 1 : -1);
|
||||
res[1] = this->m_origin.y + this->m_corner.y * (direction.y >= 0 ? 1 : -1);
|
||||
res[2] = this->m_origin.z + this->m_corner.z * (direction.z >= 0 ? 1 : -1);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uf::Collider::Manifold UF_API uf::AABBox::intersects( const uf::AABBox& b ) const {
|
||||
const uf::AABBox& a = *this;
|
||||
uf::Collider::Manifold manifold(a, b);
|
||||
|
||||
float a_left = a.m_origin.x - a.m_corner.x;
|
||||
float a_right = a.m_origin.x + a.m_corner.x;
|
||||
float a_bottom = a.m_origin.y - a.m_corner.y;
|
||||
float a_top = a.m_origin.y + a.m_corner.y;
|
||||
float a_back = a.m_origin.z - a.m_corner.z;
|
||||
float a_front = a.m_origin.z + a.m_corner.z;
|
||||
|
||||
|
||||
float b_left = b.m_origin.x - b.m_corner.x;
|
||||
float b_right = b.m_origin.x + b.m_corner.x;
|
||||
float b_bottom = b.m_origin.y - b.m_corner.y;
|
||||
float b_top = b.m_origin.y + b.m_corner.y;
|
||||
float b_back = b.m_origin.z - b.m_corner.z;
|
||||
float b_front = b.m_origin.z + b.m_corner.z;
|
||||
|
||||
manifold.depth = 9E9;
|
||||
auto test = [&]( const pod::Vector3& axis, float minA, float maxA, float minB, float maxB )->bool{
|
||||
float axisLSqr = uf::vector::dot(axis, axis);
|
||||
if ( axisLSqr < 1E-8f ) return true;
|
||||
|
||||
float d0 = maxB - minA;
|
||||
float d1 = maxA - minB;
|
||||
if ( d0 < 0 || d1 < 0 ) return false;
|
||||
float overlap = d0 < d1 ? d0 : -d1;
|
||||
pod::Vector3 sep = axis * ( overlap / axisLSqr );
|
||||
float sepLSqr = uf::vector::dot( sep, sep );
|
||||
if ( sepLSqr < manifold.depth ) {
|
||||
manifold.normal = sep;
|
||||
manifold.depth = sepLSqr;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if ( !test( {1, 0, 0}, a_left, a_right, b_left, b_right ) ) return manifold;
|
||||
if ( !test( {0, 1, 0}, a_bottom, a_top, b_bottom, b_top ) ) return manifold;
|
||||
if ( !test( {0, 0, 1}, a_back, a_front, b_back, b_front ) ) return manifold;
|
||||
|
||||
manifold.normal = uf::vector::normalize( manifold.normal );
|
||||
manifold.depth = sqrt( manifold.depth ); // * 1.001;
|
||||
manifold.colliding = true;
|
||||
|
||||
return manifold;
|
||||
|
||||
/*
|
||||
if ( a_right < b_left ) return manifold;
|
||||
if ( a_left > b_right ) return manifold;
|
||||
|
||||
if ( a_top < b_bottom ) return manifold;
|
||||
if ( a_bottom > b_top ) return manifold;
|
||||
|
||||
if ( a_front < b_back ) return manifold;
|
||||
if ( a_back > b_front ) return manifold;
|
||||
|
||||
pod::Vector3* a_points = a.expand();
|
||||
pod::Vector3* b_points = b.expand();
|
||||
|
||||
float smallest = 9E9;
|
||||
for ( uint b = 0; b < 8; b++ ) {
|
||||
for ( uint a = 0; a < 8; a++ ) {
|
||||
float distance = uf::vector::distanceSquared(b_points[b], a_points[a]);
|
||||
smallest = fmin( smallest, distance );
|
||||
}
|
||||
}
|
||||
|
||||
delete[] a_points;
|
||||
delete[] b_points;
|
||||
|
||||
manifold.depth = sqrt(smallest);
|
||||
manifold.normal = b.m_origin - a.m_origin;
|
||||
manifold.colliding = true;
|
||||
|
||||
return manifold;
|
||||
*/
|
||||
}
|
||||
/*
|
||||
|
||||
*/
|
||||
UF_API uf::SphereCollider::SphereCollider( float r, const pod::Vector3& origin ) {
|
||||
this->m_radius = r;
|
||||
this->m_origin = origin;
|
||||
}
|
||||
std::string UF_API uf::SphereCollider::type() const { return "Sphere"; }
|
||||
float UF_API uf::SphereCollider::getRadius() const {
|
||||
return this->m_radius;
|
||||
}
|
||||
const pod::Vector3& UF_API uf::SphereCollider::getOrigin() const {
|
||||
return this->m_origin;
|
||||
}
|
||||
|
||||
void UF_API uf::SphereCollider::setRadius( float r ) {
|
||||
this->m_radius = r;
|
||||
}
|
||||
void UF_API uf::SphereCollider::setOrigin( const pod::Vector3& origin ) {
|
||||
this->m_origin = origin;
|
||||
}
|
||||
|
||||
pod::Vector3* UF_API uf::SphereCollider::expand() const {
|
||||
return NULL;
|
||||
}
|
||||
pod::Vector3 UF_API uf::SphereCollider::support( const pod::Vector3& direction ) const {
|
||||
return this->m_origin + direction * (this->m_radius/uf::vector::magnitude(direction));
|
||||
}
|
||||
uf::Collider::Manifold uf::SphereCollider::intersects( const uf::SphereCollider& b ) const {
|
||||
const uf::SphereCollider& a = *this;
|
||||
uf::Collider::Manifold manifold(a, b);
|
||||
float distance = uf::vector::distance(a.m_origin, b.m_origin);
|
||||
float sum = a.m_radius + b.m_radius;
|
||||
|
||||
if ( distance >= sum ) return manifold;
|
||||
|
||||
manifold.depth = fabs(b.m_radius - a.m_radius);
|
||||
manifold.normal = b.m_origin - a.m_origin;
|
||||
manifold.colliding = true;
|
||||
return manifold;
|
||||
}
|
||||
/*
|
||||
|
||||
*/
|
||||
/*
|
||||
uf::MeshCollider::MeshCollider( uf::Mesh& mesh ) : mesh(mesh) {
|
||||
const uf::Mesh::vertices_t verts = this->m_mesh.getVertices();
|
||||
this->m_raw = verts.get();
|
||||
}
|
||||
std::string UF_API uf::Collider::type() const { return "Mesh"; }
|
||||
uf::Mesh& uf::MeshCollider::getMesh() {
|
||||
return this->m_mesh;
|
||||
}
|
||||
const uf::Mesh& uf::MeshCollider::getMesh() const {
|
||||
return this->m_mesh;
|
||||
}
|
||||
void uf::MeshCollider::setMesh( const uf::Mesh& mesh ) {
|
||||
this->m_mesh = mesh;
|
||||
const uf::Mesh::vertices_t verts = this->m_mesh.getVertices();
|
||||
this->m_raw = verts.get();
|
||||
}
|
||||
|
||||
pod::Vector3* uf::MeshCollider::expand() const {
|
||||
return (pod::Vector3*) &this->m_raw[0];
|
||||
}
|
||||
pod::Vector3 uf::MeshCollider::support( const pod::Vector3& direction ) const {
|
||||
uint len = this->m_raw.size();
|
||||
pod::Vector3* points = this->m_expand();
|
||||
|
||||
uint best = 0;
|
||||
float best_dot = points[0].dot(direction);
|
||||
|
||||
for ( uint i = 1; i < len; i++ ) {
|
||||
float dot = points[i].dot(direction);
|
||||
if ( dot > best_dot ) {
|
||||
best = i;
|
||||
best_dot = dot;
|
||||
}
|
||||
}
|
||||
return points[best];
|
||||
}
|
||||
*/
|
||||
/*
|
||||
|
||||
*/
|
||||
UF_API uf::ModularCollider::ModularCollider( uint len, pod::Vector3* container, bool should_free, const uf::ModularCollider::function_expand_t& expand, const uf::ModularCollider::function_support_t& support ) {
|
||||
this->m_len = len;
|
||||
this->m_container = container;
|
||||
this->m_should_free = should_free;
|
||||
this->m_function_expand = expand;
|
||||
this->m_function_support = support;
|
||||
}
|
||||
UF_API uf::ModularCollider::~ModularCollider() {
|
||||
if ( this->m_container != NULL && this->m_should_free ) delete[] this->m_container;
|
||||
}
|
||||
std::string UF_API uf::ModularCollider::type() const { return "Modular"; }
|
||||
void UF_API uf::ModularCollider::setExpand( const uf::ModularCollider::function_expand_t& expand ) {
|
||||
this->m_function_expand = expand;
|
||||
}
|
||||
void UF_API uf::ModularCollider::setSupport( const uf::ModularCollider::function_support_t& support ) {
|
||||
this->m_function_support = support;
|
||||
}
|
||||
|
||||
pod::Vector3* UF_API uf::ModularCollider::getContainer() {
|
||||
return this->m_container;
|
||||
}
|
||||
uint UF_API uf::ModularCollider::getSize() const {
|
||||
return this->m_len;
|
||||
}
|
||||
void UF_API uf::ModularCollider::setContainer( pod::Vector3* container, uint len ) {
|
||||
this->m_container = container;
|
||||
this->m_len = len;
|
||||
}
|
||||
|
||||
pod::Vector3* UF_API uf::ModularCollider::expand() const {
|
||||
return this->m_function_expand ? this->m_function_expand() : this->m_container;
|
||||
}
|
||||
pod::Vector3 UF_API uf::ModularCollider::support( const pod::Vector3& direction ) const {
|
||||
if ( this->m_function_support ) return this->m_function_support(direction);
|
||||
uint len = this->m_len;
|
||||
pod::Vector3* points = this->expand();
|
||||
|
||||
uint best = 0;
|
||||
float best_dot = uf::vector::dot(points[0], direction);
|
||||
|
||||
for ( uint i = 1; i < len; i++ ) {
|
||||
float dot = uf::vector::dot(points[i], direction);
|
||||
if ( dot > best_dot ) {
|
||||
best = i;
|
||||
best_dot = dot;
|
||||
}
|
||||
}
|
||||
return points[best];
|
||||
}
|
||||
|
||||
uf::CollisionBody::~CollisionBody() {
|
||||
uf::Collider::~Collider() {
|
||||
this->clear();
|
||||
}
|
||||
void UF_API uf::CollisionBody::clear() {
|
||||
for ( uf::Collider* pointer : this->m_container ) delete pointer;
|
||||
void UF_API uf::Collider::clear() {
|
||||
for ( pod::Collider* pointer : this->m_container ) delete pointer;
|
||||
this->m_container.clear();
|
||||
}
|
||||
|
||||
void UF_API uf::CollisionBody::add( uf::Collider* pointer ) {
|
||||
void UF_API uf::Collider::add( pod::Collider* pointer ) {
|
||||
this->m_container.push_back(pointer);
|
||||
}
|
||||
uf::CollisionBody::container_t& UF_API uf::CollisionBody::getContainer() {
|
||||
uf::Collider::container_t& UF_API uf::Collider::getContainer() {
|
||||
return this->m_container;
|
||||
}
|
||||
const uf::CollisionBody::container_t& UF_API uf::CollisionBody::getContainer() const {
|
||||
const uf::Collider::container_t& UF_API uf::Collider::getContainer() const {
|
||||
return this->m_container;
|
||||
}
|
||||
|
||||
std::size_t UF_API uf::CollisionBody::getSize() const {
|
||||
std::size_t UF_API uf::Collider::getSize() const {
|
||||
return this->m_container.size();
|
||||
}
|
||||
|
||||
std::vector<uf::Collider::Manifold> UF_API uf::CollisionBody::intersects( const uf::CollisionBody& body ) const {
|
||||
std::vector<uf::Collider::Manifold> manifolds;
|
||||
for ( const uf::Collider* pointer : body.m_container ) {
|
||||
std::vector<uf::Collider::Manifold> result = this->intersects( *pointer );
|
||||
std::vector<pod::Collider::Manifold> UF_API uf::Collider::intersects( const uf::Collider& body, bool smart ) const {
|
||||
std::vector<pod::Collider::Manifold> manifolds;
|
||||
manifolds.reserve( this->m_container.size() * body.m_container.size() );
|
||||
for ( const pod::Collider* pointer : body.m_container ) {
|
||||
std::vector<pod::Collider::Manifold> result = this->intersects( *pointer, smart );
|
||||
manifolds.insert( manifolds.end(), result.begin(), result.end() );
|
||||
}
|
||||
return manifolds;
|
||||
}
|
||||
|
||||
std::vector<uf::Collider::Manifold> UF_API uf::CollisionBody::intersects( const uf::Collider& body ) const {
|
||||
std::vector<uf::Collider::Manifold> manifolds;
|
||||
for ( const uf::Collider* pointer : this->m_container ) {
|
||||
uf::Collider::Manifold manifold;
|
||||
std::vector<pod::Collider::Manifold> UF_API uf::Collider::intersects( const pod::Collider& body, bool smart ) const {
|
||||
// smart = false;
|
||||
std::vector<pod::Collider::Manifold> manifolds;
|
||||
for ( const pod::Collider* pointer : this->m_container ) {
|
||||
pod::Collider::Manifold& manifold = manifolds.emplace_back();
|
||||
if ( !pointer ) continue;
|
||||
if ( pointer->type() == body.type() ) {
|
||||
if ( pointer->type() == "AABBox" ) {
|
||||
const uf::AABBox& a = *((const uf::AABBox*) pointer);
|
||||
const uf::AABBox& b = *((const uf::AABBox*) &body);
|
||||
if ( smart && pointer->type() == body.type() ) {
|
||||
if ( pointer->type() == "BoundingBox" ) {
|
||||
const uf::BoundingBox& a = *((const uf::BoundingBox*) pointer);
|
||||
const uf::BoundingBox& b = *((const uf::BoundingBox*) &body);
|
||||
manifold = a.intersects(b);
|
||||
} else if ( pointer->type() == "Sphere" ) {
|
||||
const uf::SphereCollider& a = *((const uf::SphereCollider*) pointer);
|
||||
const uf::SphereCollider& b = *((const uf::SphereCollider*) &body);
|
||||
manifold = a.intersects(b);
|
||||
}
|
||||
else manifold = pointer->intersects( body );
|
||||
else
|
||||
manifold = pointer->intersects( body );
|
||||
} else manifold = pointer->intersects( body );
|
||||
manifolds.push_back( manifold );
|
||||
}
|
||||
return manifolds;
|
||||
}
|
||||
157
engine/src/utils/math/collision/boundingbox.cpp
Normal file
157
engine/src/utils/math/collision/boundingbox.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
#include <uf/utils/math/collision/boundingbox.h>
|
||||
|
||||
UF_API uf::BoundingBox::BoundingBox( const pod::Vector3& origin, const pod::Vector3& corner ) {
|
||||
this->m_origin = origin;
|
||||
this->m_corner = corner;
|
||||
}
|
||||
const pod::Vector3& uf::BoundingBox::getOrigin() const {
|
||||
return this->m_origin;
|
||||
}
|
||||
const pod::Vector3& uf::BoundingBox::getCorner() const {
|
||||
return this->m_corner;
|
||||
}
|
||||
void uf::BoundingBox::setOrigin( const pod::Vector3& origin ) {
|
||||
this->m_origin = origin;
|
||||
}
|
||||
void uf::BoundingBox::setCorner( const pod::Vector3& corner ) {
|
||||
this->m_corner = corner;
|
||||
}
|
||||
pod::Vector3 uf::BoundingBox::min() const {
|
||||
pod::Vector3f position = this->getPosition() + this->m_origin;
|
||||
// const pod::Vector3f& position = this->m_origin;
|
||||
return position - this->m_corner;
|
||||
}
|
||||
pod::Vector3 uf::BoundingBox::max() const {
|
||||
pod::Vector3f position = this->getPosition() + this->m_origin;
|
||||
// const pod::Vector3f& position = this->m_origin;
|
||||
return position + this->m_corner;
|
||||
}
|
||||
pod::Vector3 uf::BoundingBox::closest( const pod::Vector3f& point ) const {
|
||||
pod::Vector3f position = this->getPosition() + this->m_origin;
|
||||
// const pod::Vector3f& position = this->m_origin;
|
||||
|
||||
float distance = 9E9;
|
||||
pod::Vector3f vector = point;
|
||||
pod::Vector3f min = position - this->m_corner;
|
||||
pod::Vector3f max = position + this->m_corner;
|
||||
|
||||
float test = 0;
|
||||
if ( (test = fabs(min.x - point.x)) < distance ) {
|
||||
distance = test;
|
||||
vector.x = min.x;
|
||||
}
|
||||
if ( (test = fabs(max.x - point.x)) < distance ) {
|
||||
distance = test;
|
||||
vector.x = max.x;
|
||||
}
|
||||
|
||||
if ( (test = fabs(min.y - point.y)) < distance ) {
|
||||
distance = test;
|
||||
vector.y = min.y;
|
||||
}
|
||||
if ( (test = fabs(max.y - point.y)) < distance ) {
|
||||
distance = test;
|
||||
vector.y = max.y;
|
||||
}
|
||||
|
||||
if ( (test = fabs(min.z - point.z)) < distance ) {
|
||||
distance = test;
|
||||
vector.z = min.z;
|
||||
}
|
||||
if ( (test = fabs(max.z - point.z)) < distance ) {
|
||||
distance = test;
|
||||
vector.z = max.z;
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
std::string UF_API uf::BoundingBox::type() const { return "BoundingBox"; }
|
||||
pod::Vector3* UF_API uf::BoundingBox::expand() const {
|
||||
pod::Vector3* raw = new pod::Vector3[8];
|
||||
raw[0] = pod::Vector3{ this->m_corner.x, this->m_corner.y, this->m_corner.z};
|
||||
raw[1] = pod::Vector3{ this->m_corner.x, this->m_corner.y, -this->m_corner.z};
|
||||
raw[2] = pod::Vector3{ -this->m_corner.x, this->m_corner.y, -this->m_corner.z};
|
||||
raw[3] = pod::Vector3{ -this->m_corner.x, this->m_corner.y, this->m_corner.z};
|
||||
raw[4] = pod::Vector3{ -this->m_corner.x, -this->m_corner.y, this->m_corner.z};
|
||||
raw[5] = pod::Vector3{ this->m_corner.x, -this->m_corner.y, this->m_corner.z};
|
||||
raw[6] = pod::Vector3{ this->m_corner.x, -this->m_corner.y, -this->m_corner.z};
|
||||
raw[7] = pod::Vector3{ -this->m_corner.x, -this->m_corner.y, this->m_corner.z};
|
||||
|
||||
pod::Vector3f position = this->getPosition() + this->m_origin;
|
||||
// const pod::Vector3f& position = this->m_origin;
|
||||
for ( uint i = 0; i < 8; i++ ) raw[0] += position;
|
||||
|
||||
return raw;
|
||||
}
|
||||
pod::Vector3 UF_API uf::BoundingBox::support( const pod::Vector3& direction ) const {
|
||||
pod::Vector3f position = this->getPosition() + this->m_origin;
|
||||
// const pod::Vector3f& position = this->m_origin;
|
||||
pod::Vector3 res = {
|
||||
position.x + fabs(this->m_corner.x) * (direction.x > 0 ? 1 : -1),
|
||||
position.y + fabs(this->m_corner.y) * (direction.y > 0 ? 1 : -1),
|
||||
position.z + fabs(this->m_corner.z) * (direction.z > 0 ? 1 : -1),
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
pod::Collider::Manifold UF_API uf::BoundingBox::intersects( const uf::BoundingBox& b ) const {
|
||||
const uf::BoundingBox& a = *this;
|
||||
pod::Collider::Manifold manifold(a, b);
|
||||
|
||||
BoundingBox difference(a.min() - b.max() + a.m_corner + b.m_corner, (a.m_corner + b.m_corner) * 2.0f);
|
||||
|
||||
pod::Vector3f min = difference.m_origin - this->m_corner;
|
||||
pod::Vector3f max = difference.m_origin + this->m_corner;
|
||||
manifold.colliding = min.x <= 0 && max.x >= 0 && min.y <= 0 && max.y >= 0;
|
||||
|
||||
if ( !manifold.colliding ) return manifold;
|
||||
|
||||
pod::Vector3f penetration = difference.closest( {0, 0, 0} );
|
||||
manifold.depth = uf::vector::norm( penetration );
|
||||
manifold.normal = penetration / manifold.depth;
|
||||
|
||||
/*
|
||||
float a_left = position_a.x - a.m_corner.x;
|
||||
float a_right = position_a.x + a.m_corner.x;
|
||||
float a_bottom = position_a.y - a.m_corner.y;
|
||||
float a_top = position_a.y + a.m_corner.y;
|
||||
float a_back = position_a.z - a.m_corner.z;
|
||||
float a_front = position_a.z + a.m_corner.z;
|
||||
|
||||
|
||||
float b_left = position_b.x - b.m_corner.x;
|
||||
float b_right = position_b.x + b.m_corner.x;
|
||||
float b_bottom = position_b.y - b.m_corner.y;
|
||||
float b_top = position_b.y + b.m_corner.y;
|
||||
float b_back = position_b.z - b.m_corner.z;
|
||||
float b_front = position_b.z + b.m_corner.z;
|
||||
|
||||
manifold.depth = 9E9;
|
||||
auto test = [&]( const pod::Vector3& axis, float minA, float maxA, float minB, float maxB )->bool{
|
||||
float axisLSqr = uf::vector::dot(axis, axis);
|
||||
if ( axisLSqr < 1E-8f ) return true;
|
||||
|
||||
float d0 = maxB - minA;
|
||||
float d1 = maxA - minB;
|
||||
if ( d0 < 0 || d1 < 0 ) return false;
|
||||
float overlap = d0 < d1 ? d0 : -d1;
|
||||
pod::Vector3 sep = axis * ( overlap / axisLSqr );
|
||||
float sepLSqr = uf::vector::dot( sep, sep );
|
||||
if ( sepLSqr < manifold.depth ) {
|
||||
manifold.normal = sep;
|
||||
manifold.depth = sepLSqr;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if ( !test( {1, 0, 0}, a_left, a_right, b_left, b_right ) ) return manifold;
|
||||
if ( !test( {0, 1, 0}, a_bottom, a_top, b_bottom, b_top ) ) return manifold;
|
||||
if ( !test( {0, 0, 1}, a_back, a_front, b_back, b_front ) ) return manifold;
|
||||
|
||||
manifold.normal = uf::vector::normalize( manifold.normal );
|
||||
manifold.depth = sqrt( manifold.depth );
|
||||
// manifold.depth = manifold.depth;
|
||||
manifold.colliding = true;
|
||||
*/
|
||||
return manifold;
|
||||
}
|
||||
247
engine/src/utils/math/collision/gjk.cpp
Normal file
247
engine/src/utils/math/collision/gjk.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
#include <uf/utils/math/collision/gjk.h>
|
||||
|
||||
/*
|
||||
pod::Simplex::Simplex( const pod::Vector3& b, const pod::Vector3& c, const pod::Vector3& d ) {
|
||||
this->set(b, c, d);
|
||||
}
|
||||
void pod::Simplex::add( const pod::Vector3& a ) {
|
||||
this->d = this->c;
|
||||
this->c = this->b;
|
||||
this->b = a;
|
||||
}
|
||||
void pod::Simplex::set( const pod::Vector3& b, const pod::Vector3& c, const pod::Vector3& d ) {
|
||||
this->b = b;
|
||||
this->c = c;
|
||||
this->d = d;
|
||||
if ( b != pod::Vector3{} ) this->size++;
|
||||
if ( c != pod::Vector3{} ) this->size++;
|
||||
if ( d != pod::Vector3{} ) this->size++;
|
||||
}
|
||||
*/
|
||||
pod::Collider::~Collider(){}
|
||||
std::string UF_API pod::Collider::type() const { return ""; }
|
||||
pod::Collider::Manifold UF_API pod::Collider::intersects( const pod::Collider& y ) const {
|
||||
const pod::Collider& x = *this;
|
||||
|
||||
pod::Simplex::SupportPoint a;
|
||||
pod::Simplex simplex;
|
||||
pod::Vector3 direction = pod::Vector3{ 1.0f, 0.0f, 0.0f };
|
||||
|
||||
pod::Collider::Manifold manifold(x, y);
|
||||
float dot = -0.1;
|
||||
uint16_t iterations = 0;
|
||||
uint16_t iterations_cap = 25;
|
||||
while ( iterations++ < iterations_cap ) {
|
||||
direction = uf::vector::normalize(direction);
|
||||
|
||||
a = pod::Simplex::SupportPoint{};
|
||||
a.a = x.support(direction);
|
||||
a.b = y.support(-direction);
|
||||
a.v = a.a - a.b;
|
||||
|
||||
if ( (dot = a.dot(direction)) < 0 ) {
|
||||
return manifold;
|
||||
}
|
||||
if( simplex.size == 0 ) {
|
||||
simplex.b = a;
|
||||
|
||||
direction = direction * -1;
|
||||
simplex.size = 1;
|
||||
continue;
|
||||
}
|
||||
if ( simplex.size == 1 ) {
|
||||
direction = uf::vector::cross(a.cross(simplex.b), a.v);
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
simplex.size = 2;
|
||||
continue;
|
||||
}
|
||||
if ( simplex.size == 2 ) {
|
||||
pod::Vector3 ao = a * -1;
|
||||
pod::Vector3 ab = simplex.b - a;
|
||||
pod::Vector3 ac = simplex.c - a;
|
||||
pod::Vector3 abc = uf::vector::cross(ab, ac);
|
||||
pod::Vector3 abP = uf::vector::cross(ab, abc);
|
||||
if ( uf::vector::dot(abP, ao) > 0 ) {
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = uf::vector::cross(ab, ao);
|
||||
continue;
|
||||
}
|
||||
pod::Vector3 acP = uf::vector::cross(abc, ac);
|
||||
if ( uf::vector::dot(acP, ao) > 0 ) {
|
||||
simplex.b = a;
|
||||
|
||||
direction = uf::vector::cross(ac, ao);
|
||||
continue;
|
||||
}
|
||||
if ( uf::vector::dot(abc, ao) > 0 ) {
|
||||
simplex.d = simplex.c;
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = abc;
|
||||
continue;
|
||||
}
|
||||
simplex.d = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = abc * -1;
|
||||
simplex.size = 3;
|
||||
continue;
|
||||
}
|
||||
if ( simplex.size == 3 ) {
|
||||
pod::Vector3 ao = a * -1;
|
||||
pod::Vector3 ab = simplex.b - a;
|
||||
pod::Vector3 ac = simplex.c - a;
|
||||
pod::Vector3 abc = uf::vector::cross(ab, ac);
|
||||
pod::Vector3 ad, acd, adb;
|
||||
if ( uf::vector::dot(abc, ao) > 0 ) {
|
||||
goto check_face;
|
||||
}
|
||||
ad = simplex.d - a;
|
||||
acd = uf::vector::cross(ac, ad);
|
||||
if ( uf::vector::dot(acd, ao) > 0 ) {
|
||||
simplex.b = simplex.c;
|
||||
simplex.c = simplex.d;
|
||||
|
||||
ab = ac;
|
||||
ac = ad;
|
||||
abc = acd;
|
||||
|
||||
goto check_face;
|
||||
}
|
||||
goto EPA;
|
||||
|
||||
check_face:
|
||||
pod::Vector3 abP = uf::vector::cross(ab, abc);
|
||||
if ( uf::vector::dot(abP, ao) > 0 ) {
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
|
||||
direction = uf::vector::cross(uf::vector::cross(ab, ao), ab);
|
||||
simplex.size = 2;
|
||||
continue;
|
||||
}
|
||||
pod::Vector3 acP = uf::vector::cross(abc, ac);
|
||||
if ( uf::vector::dot(acP, ao) > 0 ) {
|
||||
simplex.b = a;
|
||||
direction = uf::vector::cross(uf::vector::cross(ac, ao), ac);
|
||||
simplex.size = 2;
|
||||
continue;
|
||||
}
|
||||
simplex.d = simplex.c;
|
||||
simplex.c = simplex.b;
|
||||
simplex.b = a;
|
||||
direction = abc;
|
||||
simplex.size = 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return manifold;
|
||||
|
||||
EPA:
|
||||
struct Triangle {
|
||||
pod::Simplex::SupportPoint points[3];
|
||||
pod::Vector3f normal;
|
||||
Triangle( const pod::Simplex::SupportPoint& a, const pod::Simplex::SupportPoint& b, const pod::Simplex::SupportPoint& c ) {
|
||||
points[0] = a;
|
||||
points[1] = b;
|
||||
points[2] = c;
|
||||
normal = uf::vector::normalize( uf::vector::cross( b.v - a.v, c.v - a.v ) );
|
||||
}
|
||||
};
|
||||
struct Edge {
|
||||
pod::Simplex::SupportPoint points[2];
|
||||
Edge( const pod::Simplex::SupportPoint& a, const pod::Simplex::SupportPoint& b ) {
|
||||
points[0] = a;
|
||||
points[1] = b;
|
||||
}
|
||||
};
|
||||
|
||||
iterations = 0;
|
||||
manifold.colliding = true;
|
||||
manifold.depth = 0.0f;
|
||||
manifold.normal = { 0, 0, 0 };
|
||||
|
||||
std::vector<Triangle> triangles;
|
||||
std::vector<Edge> edges;
|
||||
|
||||
triangles.emplace_back( a, simplex.b, simplex.c );
|
||||
triangles.emplace_back( a, simplex.b, simplex.d );
|
||||
triangles.emplace_back( a, simplex.c, simplex.d );
|
||||
triangles.emplace_back( simplex.b, simplex.c, simplex.d );
|
||||
|
||||
auto addEdge = [&]( const pod::Simplex::SupportPoint& a, const pod::Simplex::SupportPoint& b ) {
|
||||
for ( auto it = edges.begin(); it != edges.end(); ++it ) {
|
||||
if( it->points[0]== b && it->points[1]== a ) {
|
||||
edges.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
edges.emplace_back( a, b );
|
||||
};
|
||||
|
||||
while ( iterations++ < iterations_cap ) {
|
||||
// find closest triangle to origin
|
||||
struct {
|
||||
std::vector<Triangle>::iterator it;
|
||||
float distance = 9E9;
|
||||
pod::Simplex::SupportPoint support;
|
||||
} closest = { triangles.begin() };
|
||||
|
||||
for(auto it = triangles.begin(); it != triangles.end(); it++) {
|
||||
float distance = fabs( uf::vector::dot(it->normal, it->points[0].v) );
|
||||
if( distance < closest.distance ) {
|
||||
closest.distance = distance;
|
||||
closest.it = it;
|
||||
}
|
||||
}
|
||||
{
|
||||
closest.support.a = x.support(closest.it->normal);
|
||||
closest.support.b = y.support(-closest.it->normal);
|
||||
closest.support.v = closest.support.a - closest.support.b;
|
||||
}
|
||||
|
||||
manifold.normal = -closest.it->normal;
|
||||
manifold.depth = uf::vector::dot( closest.it->normal, closest.support.v );
|
||||
if( manifold.depth - closest.distance < 0.00001f ) {
|
||||
manifold.depth = uf::vector::dot( closest.it->normal, closest.it->points[0].v );
|
||||
return manifold;
|
||||
}
|
||||
|
||||
for(auto it = triangles.begin(); it != triangles.end();) {
|
||||
// can this face be 'seen' by closest.support?
|
||||
if( uf::vector::dot( it->normal, (closest.support.v - it->points[0].v) ) > 0) {
|
||||
addEdge( it->points[0], it->points[1] );
|
||||
addEdge( it->points[1], it->points[2] );
|
||||
addEdge( it->points[2], it->points[0] );
|
||||
it = triangles.erase(it);
|
||||
continue;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
// create new triangles from the edges in the edge list
|
||||
for(auto it = edges.begin(); it != edges.end(); it++)
|
||||
triangles.emplace_back( closest.support, it->points[0], it->points[1] );
|
||||
|
||||
edges.clear();
|
||||
}
|
||||
return manifold;
|
||||
}
|
||||
|
||||
pod::Vector3f pod::Collider::getPosition() const {
|
||||
return this->m_transform.reference ? this->m_transform.reference->position : this->m_transform.position;
|
||||
// return uf::transform::flatten( this->m_transform.reference ? *this->m_transform.reference : this->m_transform ).position;
|
||||
}
|
||||
pod::Transform<>& pod::Collider::getTransform() {
|
||||
return this->m_transform;
|
||||
}
|
||||
const pod::Transform<>& pod::Collider::getTransform() const {
|
||||
return this->m_transform;
|
||||
}
|
||||
void pod::Collider::setTransform( const pod::Transform<>& transform ) {
|
||||
this->m_transform = transform;
|
||||
}
|
||||
42
engine/src/utils/math/collision/mesh.cpp
Normal file
42
engine/src/utils/math/collision/mesh.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include <uf/utils/math/collision/mesh.h>
|
||||
|
||||
uf::MeshCollider::MeshCollider( const pod::Transform<>& transform, const std::vector<pod::Vector3>& positions ) : m_positions(positions) {
|
||||
this->setTransform(transform);
|
||||
}
|
||||
std::string UF_API uf::MeshCollider::type() const { return "Mesh"; }
|
||||
|
||||
std::vector<pod::Vector3>& uf::MeshCollider::getPositions() {
|
||||
return this->m_positions;
|
||||
}
|
||||
|
||||
const std::vector<pod::Vector3>& uf::MeshCollider::getPositions() const {
|
||||
return this->m_positions;
|
||||
}
|
||||
|
||||
void uf::MeshCollider::setPositions( const std::vector<pod::Vector3>& positions ) {
|
||||
this->m_positions = positions;
|
||||
}
|
||||
|
||||
pod::Vector3* uf::MeshCollider::expand() const {
|
||||
return (pod::Vector3*) &this->m_positions[0];
|
||||
}
|
||||
pod::Vector3 uf::MeshCollider::support( const pod::Vector3& direction ) const {
|
||||
size_t len = this->m_positions.size();
|
||||
pod::Vector3* points = this->expand();
|
||||
pod::Matrix4f model = uf::transform::model( this->m_transform );
|
||||
|
||||
struct {
|
||||
size_t i = 0;
|
||||
float dot = 0;
|
||||
} best;
|
||||
|
||||
for ( size_t i = 0; i < len; ++i ) {
|
||||
float dot = uf::vector::dot( uf::matrix::multiply<float>( model, points[i] ), direction);
|
||||
// float dot = uf::vector::dot( points[i], direction);
|
||||
if ( i == 0 || dot > best.dot ) {
|
||||
best.i = i;
|
||||
best.dot = dot;
|
||||
}
|
||||
}
|
||||
return points[best.i];
|
||||
}
|
||||
55
engine/src/utils/math/collision/modular.cpp
Normal file
55
engine/src/utils/math/collision/modular.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include <uf/utils/math/collision/modular.h>
|
||||
|
||||
UF_API uf::ModularCollider::ModularCollider( uint len, pod::Vector3* container, bool should_free, const uf::ModularCollider::function_expand_t& expand, const uf::ModularCollider::function_support_t& support ) {
|
||||
this->m_len = len;
|
||||
this->m_container = container;
|
||||
this->m_should_free = should_free;
|
||||
this->m_function_expand = expand;
|
||||
this->m_function_support = support;
|
||||
}
|
||||
UF_API uf::ModularCollider::~ModularCollider() {
|
||||
if ( this->m_container != NULL && this->m_should_free ) delete[] this->m_container;
|
||||
}
|
||||
std::string UF_API uf::ModularCollider::type() const { return "Modular"; }
|
||||
void UF_API uf::ModularCollider::setExpand( const uf::ModularCollider::function_expand_t& expand ) {
|
||||
this->m_function_expand = expand;
|
||||
}
|
||||
void UF_API uf::ModularCollider::setSupport( const uf::ModularCollider::function_support_t& support ) {
|
||||
this->m_function_support = support;
|
||||
}
|
||||
|
||||
pod::Vector3* UF_API uf::ModularCollider::getContainer() {
|
||||
return this->m_container;
|
||||
}
|
||||
uint UF_API uf::ModularCollider::getSize() const {
|
||||
return this->m_len;
|
||||
}
|
||||
void UF_API uf::ModularCollider::setContainer( pod::Vector3* container, uint len ) {
|
||||
this->m_container = container;
|
||||
this->m_len = len;
|
||||
}
|
||||
|
||||
pod::Vector3* UF_API uf::ModularCollider::expand() const {
|
||||
return this->m_function_expand ? this->m_function_expand() : this->m_container;
|
||||
}
|
||||
pod::Vector3 UF_API uf::ModularCollider::support( const pod::Vector3& direction ) const {
|
||||
if ( this->m_function_support ) return this->m_function_support(direction);
|
||||
|
||||
pod::Vector3* points = this->expand();
|
||||
uint len = this->m_len;
|
||||
|
||||
struct {
|
||||
size_t i = 0;
|
||||
float dot = 0;
|
||||
} best;
|
||||
|
||||
for ( size_t i = 0; i < len; ++i ) {
|
||||
// float dot = uf::vector::dot( uf::matrix::multiply<float>( model, points[i] ), direction);
|
||||
float dot = uf::vector::dot( points[i], direction);
|
||||
if ( i == 0 || dot > best.dot ) {
|
||||
best.i = i;
|
||||
best.dot = dot;
|
||||
}
|
||||
}
|
||||
return points[best.i];
|
||||
}
|
||||
49
engine/src/utils/math/collision/sphere.cpp
Normal file
49
engine/src/utils/math/collision/sphere.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <uf/utils/math/collision/sphere.h>
|
||||
|
||||
UF_API uf::SphereCollider::SphereCollider( float r, const pod::Vector3& origin ) {
|
||||
this->m_radius = r;
|
||||
this->m_origin = origin;
|
||||
}
|
||||
std::string UF_API uf::SphereCollider::type() const { return "Sphere"; }
|
||||
float UF_API uf::SphereCollider::getRadius() const {
|
||||
return this->m_radius;
|
||||
}
|
||||
const pod::Vector3& UF_API uf::SphereCollider::getOrigin() const {
|
||||
return this->m_origin;
|
||||
}
|
||||
|
||||
void UF_API uf::SphereCollider::setRadius( float r ) {
|
||||
this->m_radius = r;
|
||||
}
|
||||
void UF_API uf::SphereCollider::setOrigin( const pod::Vector3& origin ) {
|
||||
this->m_origin = origin;
|
||||
}
|
||||
|
||||
pod::Vector3* UF_API uf::SphereCollider::expand() const {
|
||||
return NULL;
|
||||
}
|
||||
pod::Vector3 UF_API uf::SphereCollider::support( const pod::Vector3& direction ) const {
|
||||
pod::Vector3f position = this->getPosition() + this->m_origin;
|
||||
// const pod::Vector3f& position = this->m_origin;
|
||||
return position + direction * (this->m_radius/uf::vector::magnitude(direction));
|
||||
}
|
||||
pod::Collider::Manifold uf::SphereCollider::intersects( const uf::SphereCollider& b ) const {
|
||||
const uf::SphereCollider& a = *this;
|
||||
pod::Collider::Manifold manifold(a, b);
|
||||
|
||||
pod::Vector3f position_a = a.getPosition() + a.m_origin;
|
||||
pod::Vector3f position_b = b.getPosition() + b.m_origin;
|
||||
// const pod::Vector3f& position_a = a.m_origin;
|
||||
// const pod::Vector3f& position_b = b.m_origin;
|
||||
|
||||
float distanceSquared = uf::vector::distanceSquared(position_a, position_b);
|
||||
float sum = a.m_radius + b.m_radius;
|
||||
float sumSquared = sum * sum;
|
||||
|
||||
if ( distanceSquared >= sumSquared ) return manifold;
|
||||
|
||||
manifold.depth = fabs(b.m_radius - a.m_radius);
|
||||
manifold.normal = position_b - position_a;
|
||||
manifold.colliding = true;
|
||||
return manifold;
|
||||
}
|
||||
@ -1,5 +1,11 @@
|
||||
#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;
|
||||
|
||||
void UF_API uf::physics::tick() {
|
||||
uf::physics::time::previous = uf::physics::time::current;
|
||||
uf::physics::time::current = uf::physics::time::timer.elapsed().asDouble();
|
||||
|
||||
@ -745,7 +745,7 @@ void ext::Gui::initialize() {
|
||||
float delay = 0.0f;
|
||||
float scale = metadata["text settings"]["scale"].asFloat();
|
||||
std::vector<::GlyphBox> glyphs = generateGlyphs(*this);
|
||||
std::cout << "Loading string: " << metadata["text settings"]["string"] << std::endl;
|
||||
// std::cout << "Loading string: " << metadata["text settings"]["string"] << std::endl;
|
||||
for ( auto& glyph : glyphs ) {
|
||||
ext::Gui* glyphElement = (ext::Gui*) this->findByUid( this->loadChild("/gui/text/letter.json", false) );
|
||||
/*
|
||||
@ -860,7 +860,7 @@ void ext::Gui::render() {
|
||||
metadata["text settings"]["stroke"][2].asFloat(),
|
||||
metadata["text settings"]["stroke"][3].asFloat()
|
||||
};
|
||||
|
||||
/*
|
||||
if ( uf::Window::isKeyPressed("V") ) {
|
||||
metadata["text settings"]["weight"] = metadata["text settings"]["weight"].asFloat() + uf::physics::time::delta;
|
||||
std::cout << metadata["text settings"]["weight"].asFloat() << std::endl;
|
||||
@ -877,7 +877,7 @@ void ext::Gui::render() {
|
||||
metadata["text settings"]["spread"] = metadata["text settings"]["spread"].asFloat() - uf::physics::time::delta;
|
||||
std::cout << metadata["text settings"]["spread"].asFloat() << std::endl;
|
||||
}
|
||||
|
||||
*/
|
||||
uniforms.gui.offset = offset;
|
||||
uniforms.gui.color = color;
|
||||
uniforms.gui.stroke = stroke;
|
||||
@ -1036,7 +1036,7 @@ void ext::Gui::render() {
|
||||
alignas(8) pod::Vector2f radius = { 0.1f, 0.1f };
|
||||
alignas(16) pod::Vector4f color = { 1, 1, 1, 1 };
|
||||
} cursor;
|
||||
alignas(4) float alpha;
|
||||
alignas(8) pod::Vector2f alpha;
|
||||
};
|
||||
auto& shader = blitter.material.shaders.front();
|
||||
auto& uniforms = shader.uniforms.front().get<UniformDescriptor>();
|
||||
@ -1077,7 +1077,8 @@ void ext::Gui::render() {
|
||||
pod::Matrix4t<> model = uf::matrix::translate( uf::matrix::identity(), { 0, 0, 1 } );
|
||||
uniforms.matrices.models[i] = model;
|
||||
}
|
||||
uniforms.alpha = metadata["overlay"]["alpha"].asFloat();
|
||||
uniforms.alpha.x = metadata["overlay"]["alpha"].asFloat();
|
||||
uniforms.alpha.y = 0;
|
||||
|
||||
uniforms.cursor.position.x = (metadata["overlay"]["cursor"]["position"][0].asFloat() + 1.0f) * 0.5f; //(::mouse.position.x + 1.0f) * 0.5f;
|
||||
uniforms.cursor.position.y = (metadata["overlay"]["cursor"]["position"][1].asFloat() + 1.0f) * 0.5f; //(::mouse.position.y + 1.0f) * 0.5f;
|
||||
|
||||
45
ext/main.cpp
45
ext/main.cpp
@ -102,12 +102,22 @@ void EXT_API ext::initialize() {
|
||||
// Set worker threads
|
||||
uf::thread::workers = ::config["engine"]["worker threads"].asUInt64();
|
||||
// Enable valiation layer
|
||||
ext::vulkan::validation = ::config["engine"]["ext"]["vulkan"]["validation"].asBool();
|
||||
ext::vulkan::validation = ::config["engine"]["ext"]["vulkan"]["validation"]["enabled"].asBool();
|
||||
|
||||
for ( int i = 0; i < ::config["engine"]["ext"]["vulkan"]["validation"]["filters"].size(); ++i ) {
|
||||
ext::vulkan::validationFilters.push_back( ::config["engine"]["ext"]["vulkan"]["validation"]["filters"][i].asString() );
|
||||
}
|
||||
for ( int i = 0; i < ::config["engine"]["ext"]["vulkan"]["features"].size(); ++i ) {
|
||||
ext::vulkan::requestedDeviceFeatures.push_back( ::config["engine"]["ext"]["vulkan"]["features"][i].asString() );
|
||||
}
|
||||
//
|
||||
// ext::vulkan::DeferredRenderingGraphic::maxLights = ::config["engine"]["scenes"]["max lights"].asUInt();
|
||||
//
|
||||
ext::openvr::enabled = ::config["engine"]["ext"]["vr"]["enable"].asBool();
|
||||
ext::openvr::swapEyes = ::config["engine"]["ext"]["vr"]["swap eyes"].asBool();
|
||||
// ext::openvr::dominantEye = ::config["engine"]["ext"]["vr"]["dominatEye"].asString() == "left" ? 0 : 1;
|
||||
if ( ::config["engine"]["ext"]["vr"]["dominatEye"].asString() == "left" ) ext::openvr::dominantEye = 0;
|
||||
if ( ::config["engine"]["ext"]["vr"]["dominatEye"].asString() == "right" ) ext::openvr::dominantEye = 1;
|
||||
ext::openvr::driver.manifest = ::config["engine"]["ext"]["vr"]["manifest"].asString();
|
||||
if ( ext::openvr::enabled ) {
|
||||
::config["engine"]["render modes"]["stereo deferred"] = true;
|
||||
@ -222,13 +232,42 @@ void EXT_API ext::tick() {
|
||||
uf::iostream << ext::vulkan::allocatorStats() << "\n";
|
||||
}
|
||||
}
|
||||
/* Print Entity Information */ {
|
||||
/* Attempt to reset VR position */ {
|
||||
static uf::Timer<long long> timer(false);
|
||||
if ( !timer.running() ) timer.start();
|
||||
if ( uf::Window::isKeyPressed("Home") && timer.elapsed().asDouble() >= 1 ) { timer.reset();
|
||||
if ( uf::Window::isKeyPressed("Z") && timer.elapsed().asDouble() >= 1 ) { timer.reset();
|
||||
uf::hooks.call("VR:Seat.Reset");
|
||||
}
|
||||
}
|
||||
/* Print controller position */ if ( false ) {
|
||||
static uf::Timer<long long> timer(false);
|
||||
if ( !timer.running() ) timer.start();
|
||||
if ( uf::Window::isKeyPressed("Z") && timer.elapsed().asDouble() >= 1 ) { timer.reset();
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto* controller = scene.getController();
|
||||
auto& camera = controller->getComponent<uf::Camera>();
|
||||
auto& t = camera.getTransform(); //controller->getComponent<pod::Transform<>>();
|
||||
uf::iostream << "Viewport position: (" << t.position.x << ", " << t.position.y << ", " << t.position.z << ") (" << t.orientation.x << ", " << t.orientation.y << ", " << t.orientation.z << ", " << t.orientation.w << ")";
|
||||
uf::iostream << "\n";
|
||||
if ( false ) {
|
||||
uf::Entity* light = scene.findByUid(scene.loadChild("/light.json", true));
|
||||
if ( light ) {
|
||||
auto& lTransform = light->getComponent<pod::Transform<>>();
|
||||
auto& lMetadata = light->getComponent<uf::Serializer>();
|
||||
lTransform.position = t.position;
|
||||
lTransform.orientation = t.orientation;
|
||||
if ( !lMetadata["light"].isArray() ) {
|
||||
lMetadata["light"]["color"][0] = (rand() % 100) / 100.0;
|
||||
lMetadata["light"]["color"][1] = (rand() % 100) / 100.0;
|
||||
lMetadata["light"]["color"][2] = (rand() % 100) / 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
auto& sMetadata = scene.getComponent<uf::Serializer>();
|
||||
sMetadata["light"]["should"] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update physics timer */ {
|
||||
uf::physics::tick();
|
||||
|
||||
@ -7,11 +7,18 @@
|
||||
|
||||
#include <uf/utils/audio/audio.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
|
||||
#include <uf/engine/asset/asset.h>
|
||||
#include <uf/engine/asset/masterdata.h>
|
||||
|
||||
#include <uf/ext/vulkan/vulkan.h>
|
||||
#include <uf/ext/vulkan/rendermodes/deferred.h>
|
||||
#include <uf/ext/vulkan/rendermodes/rendertarget.h>
|
||||
#include <uf/ext/vulkan/rendermodes/stereoscopic_deferred.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
|
||||
#include <uf/utils/math/collision.h>
|
||||
|
||||
#include "../../ext.h"
|
||||
#include "../../gui/gui.h"
|
||||
@ -27,34 +34,6 @@ void ext::TestScene::initialize() {
|
||||
ext::ready = false;
|
||||
return "true";
|
||||
});
|
||||
this->addHook( "asset:Load." + std::to_string(this->getUid()), [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
std::string filename = json["filename"].asString();
|
||||
|
||||
if ( uf::string::extension(filename) != "ogg" ) return "false";
|
||||
const uf::Audio* audioPointer = NULL;
|
||||
try { audioPointer = &assetLoader.get<uf::Audio>(filename); } catch ( ... ) {}
|
||||
if ( !audioPointer ) return "false";
|
||||
|
||||
uf::Audio& audio = this->getComponent<uf::Audio>();
|
||||
if ( audio.playing() ) {
|
||||
/*
|
||||
if ( filename.find("_intro") == std::string::npos ) {
|
||||
metadata["previous bgm"]["filename"] = audio.getFilename();
|
||||
metadata["previous bgm"]["timestamp"] = audio.getTime();
|
||||
}
|
||||
*/
|
||||
audio.stop();
|
||||
}
|
||||
|
||||
// std::cout << metadata["previous bgm"] << std::endl;
|
||||
|
||||
audio.load(filename);
|
||||
audio.setVolume(metadata["volumes"]["bgm"].asFloat());
|
||||
audio.play();
|
||||
|
||||
return "true";
|
||||
});
|
||||
{
|
||||
static uf::Timer<long long> timer(false);
|
||||
if ( !timer.running() ) timer.start();
|
||||
@ -115,6 +94,9 @@ void ext::TestScene::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
void ext::TestScene::render() {
|
||||
uf::Scene::render();
|
||||
}
|
||||
void ext::TestScene::tick() {
|
||||
uf::Scene::tick();
|
||||
|
||||
@ -138,4 +120,57 @@ void ext::TestScene::tick() {
|
||||
ext::oal.listener( "VELOCITY", { 0, 0, 0 } );
|
||||
ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } );
|
||||
}
|
||||
|
||||
/* Collision */ {
|
||||
bool local = false;
|
||||
bool sort = false;
|
||||
bool useStrongest = false;
|
||||
// pod::Thread& thread = uf::thread::fetchWorker();
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
auto function = [&]() -> int {
|
||||
std::vector<uf::Object*> entities;
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
auto& metadata = entity->getComponent<uf::Serializer>();
|
||||
if ( !metadata["system"]["physics"]["collision"].isNull() && !metadata["system"]["physics"]["collision"].asBool() ) return;
|
||||
if ( entity->hasComponent<uf::Collider>() )
|
||||
entities.push_back((uf::Object*) entity);
|
||||
};
|
||||
this->process(filter);
|
||||
auto onCollision = []( pod::Collider::Manifold& manifold, uf::Object* a, uf::Object* b ){
|
||||
uf::Serializer payload;
|
||||
payload["normal"][0] = manifold.normal.x;
|
||||
payload["normal"][1] = manifold.normal.y;
|
||||
payload["normal"][2] = manifold.normal.z;
|
||||
payload["entity"] = b->getUid();
|
||||
payload["depth"] = -manifold.depth;
|
||||
a->callHook("world:Collision.%UID%", payload);
|
||||
|
||||
payload["entity"] = a->getUid();
|
||||
payload["depth"] = manifold.depth;
|
||||
b->callHook("world:Collision.%UID%", payload);
|
||||
};
|
||||
auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, uf::Object* a, uf::Object* b, bool useStrongest ){
|
||||
pod::Collider::Manifold strongest;
|
||||
auto manifolds = colliderA.intersects(colliderB);
|
||||
for ( auto manifold : manifolds ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( !useStrongest ) onCollision(manifold, a, b);
|
||||
else if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) onCollision(strongest, a, b);
|
||||
};
|
||||
// collide with others
|
||||
for ( auto* _a : entities ) {
|
||||
uf::Object& entityA = *_a;
|
||||
for ( auto* _b : entities ) { if ( _a == _b ) continue;
|
||||
uf::Object& entityB = *_b;
|
||||
testColliders( entityA.getComponent<uf::Collider>(), entityB.getComponent<uf::Collider>(), &entityA, &entityB, useStrongest );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
}
|
||||
@ -10,5 +10,6 @@ namespace ext {
|
||||
public:
|
||||
virtual void initialize();
|
||||
virtual void tick();
|
||||
virtual void render();
|
||||
};
|
||||
}
|
||||
@ -44,19 +44,24 @@ void ext::Craeture::initialize() {
|
||||
}
|
||||
*/
|
||||
/* Gravity */ {
|
||||
if ( metadata["collision"]["gravity"] != Json::nullValue ) {
|
||||
physics.linear.acceleration.x = metadata["collision"]["gravity"][0].asFloat();
|
||||
physics.linear.acceleration.y = metadata["collision"]["gravity"][1].asFloat();
|
||||
physics.linear.acceleration.z = metadata["collision"]["gravity"][2].asFloat();
|
||||
if ( metadata["system"]["physics"]["gravity"] != Json::nullValue ) {
|
||||
physics.linear.acceleration.x = metadata["system"]["physics"]["gravity"][0].asFloat();
|
||||
physics.linear.acceleration.y = metadata["system"]["physics"]["gravity"][1].asFloat();
|
||||
physics.linear.acceleration.z = metadata["system"]["physics"]["gravity"][2].asFloat();
|
||||
}
|
||||
if ( !metadata["collision"]["should"].asBool() ) {
|
||||
if ( !metadata["system"]["physics"]["collision"].asBool() ) {
|
||||
physics.linear.acceleration.x = 0;
|
||||
physics.linear.acceleration.y = 0;
|
||||
physics.linear.acceleration.z = 0;
|
||||
}
|
||||
}
|
||||
/* Collider */ {
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
uf::Collider& collider = this->getComponent<uf::Collider>();
|
||||
|
||||
collider.clear();
|
||||
auto* box = new uf::BoundingBox( {0, 1.5, 0}, {0.7, 1.6, 0.7} );
|
||||
box->getTransform().reference = &transform;
|
||||
collider.add(box);
|
||||
}
|
||||
/* RPG */ {
|
||||
ext::HousamoBattle& battle = this->getComponent<ext::HousamoBattle>();
|
||||
@ -70,6 +75,28 @@ void ext::Craeture::initialize() {
|
||||
} timers;
|
||||
*/
|
||||
static uf::Timer<long long> timer(true);
|
||||
this->addHook( "world:Collision.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
|
||||
size_t uid = json["uid"].asUInt64();
|
||||
// do not collide with children
|
||||
// if ( this->findByUid(uid) ) return "false";
|
||||
|
||||
pod::Vector3 normal;
|
||||
float depth = json["depth"].asFloat() * 1.001f;
|
||||
|
||||
normal.x = json["normal"][0].asFloat();
|
||||
normal.y = json["normal"][1].asFloat();
|
||||
normal.z = json["normal"][2].asFloat();
|
||||
pod::Vector3 correction = normal * depth;
|
||||
|
||||
transform.position -= correction;
|
||||
|
||||
if ( normal.x == 1 || normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( normal.y == 1 || normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( normal.z == 1 || normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
return "true";
|
||||
});
|
||||
this->addHook( "asset:Cache.Sound.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
|
||||
@ -148,157 +175,157 @@ void ext::Craeture::tick() {
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
/* Gravity */ {
|
||||
if ( metadata["collision"]["gravity"] != Json::nullValue ) {
|
||||
physics.linear.acceleration.x = metadata["collision"]["gravity"][0].asFloat();
|
||||
physics.linear.acceleration.y = metadata["collision"]["gravity"][1].asFloat();
|
||||
physics.linear.acceleration.z = metadata["collision"]["gravity"][2].asFloat();
|
||||
if ( metadata["system"]["physics"]["gravity"] != Json::nullValue ) {
|
||||
physics.linear.acceleration.x = metadata["system"]["physics"]["gravity"][0].asFloat();
|
||||
physics.linear.acceleration.y = metadata["system"]["physics"]["gravity"][1].asFloat();
|
||||
physics.linear.acceleration.z = metadata["system"]["physics"]["gravity"][2].asFloat();
|
||||
}
|
||||
if ( !metadata["collision"]["should"].asBool() ) {
|
||||
if ( !metadata["system"]["physics"]["collision"].asBool() ) {
|
||||
physics.linear.acceleration.x = 0;
|
||||
physics.linear.acceleration.y = 0;
|
||||
physics.linear.acceleration.z = 0;
|
||||
}
|
||||
}
|
||||
transform = uf::physics::update( transform, physics );
|
||||
#if 0
|
||||
if ( !false ) {
|
||||
bool sort = false;
|
||||
bool local = false;
|
||||
bool useStrongest = true;
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
auto onCollision = []( pod::Collider::Manifold& manifold, uf::Object* a, uf::Object* b ){
|
||||
pod::Transform<>& transform = b->getComponent<pod::Transform<>>();
|
||||
pod::Physics& physics = b->getComponent<pod::Physics>();
|
||||
|
||||
bool local = false;
|
||||
bool sort = false;
|
||||
// pod::Thread& thread = uf::thread::fetchWorker();
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
uf::Serializer payload;
|
||||
pod::Vector3 correction = manifold.normal * manifold.depth;
|
||||
transform.position -= correction;
|
||||
|
||||
/* Collision against world */ {
|
||||
auto function = [&]() -> int {
|
||||
if ( this->hasParent() && metadata["collision"]["should"].asBool() ) {
|
||||
if ( !this->hasParent() ) { return 0; }
|
||||
if ( this->getParent().getName() != "Region" ) { return 0; }
|
||||
|
||||
uf::Entity& parent = this->getParent();
|
||||
ext::TerrainGenerator& generator = parent.getComponent<ext::TerrainGenerator>();
|
||||
uf::Serializer& rMetadata = parent.getComponent<uf::Serializer>();
|
||||
pod::Transform<>& rTransform = parent.getComponent<pod::Transform<>>();
|
||||
|
||||
pod::Vector3ui size; {
|
||||
size.x = rMetadata["region"]["size"][0].asUInt();
|
||||
size.y = rMetadata["region"]["size"][1].asUInt();
|
||||
size.z = rMetadata["region"]["size"][2].asUInt();
|
||||
}
|
||||
pod::Vector3f voxelPosition = transform.position - rTransform.position;
|
||||
voxelPosition.x += size.x / 2.0f;
|
||||
voxelPosition.y += size.y / 2.0f + 1;
|
||||
voxelPosition.z += size.z / 2.0f;
|
||||
|
||||
uf::CollisionBody pCollider;
|
||||
std::vector<pod::Vector3ui> positions = {
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x - 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x + 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z - 1 },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z + 1},
|
||||
};
|
||||
if ( this->m_name == "HousamoSprite" ) {
|
||||
// bottom
|
||||
uint16_t uid = generator.getVoxel( voxelPosition.x, voxelPosition.y, voxelPosition.z );
|
||||
auto light = generator.getLight( voxelPosition.x, voxelPosition.y, voxelPosition.z );
|
||||
metadata["color"][0] = ((light >> 12) & 0xF) / (float) (0xF);
|
||||
metadata["color"][1] = ((light >> 8) & 0xF) / (float) (0xF);
|
||||
metadata["color"][2] = ((light >> 4) & 0xF) / (float) (0xF);
|
||||
metadata["color"][3] = ((light ) & 0xF) / (float) (0xF);
|
||||
/*
|
||||
if ( uid == ext::TerrainVoxelLava().uid() ) {
|
||||
this->callHook("world:Craeture.Hurt.%UID%");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if ( false ) {
|
||||
// top
|
||||
if ( ext::TerrainVoxel::atlas( generator.getVoxel( voxelPosition.x, voxelPosition.y + 1, voxelPosition.z ) ).solid() && physics.linear.velocity.y != 0 ) {
|
||||
transform.position.y += physics.linear.velocity.y * uf::physics::time::delta;
|
||||
physics.linear.velocity.y = 0;
|
||||
}
|
||||
// bottom
|
||||
if ( ext::TerrainVoxel::atlas( generator.getVoxel( voxelPosition.x, voxelPosition.y - 1, voxelPosition.z ) ).solid() && physics.linear.velocity.y != 0 ) {
|
||||
transform.position.y -= physics.linear.velocity.y * uf::physics::time::delta;
|
||||
physics.linear.velocity.y = 0;
|
||||
}
|
||||
} else {
|
||||
positions.push_back( { voxelPosition.x, voxelPosition.y - 1, voxelPosition.z } );
|
||||
positions.push_back( { voxelPosition.x, voxelPosition.y + 1, voxelPosition.z } );
|
||||
}
|
||||
|
||||
for ( auto& position : positions ) {
|
||||
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( generator.getVoxel( position.x, position.y, position.z ) );
|
||||
pod::Vector3 offset = rTransform.position;
|
||||
offset.x += position.x - (size.x / 2.0f);
|
||||
offset.y += position.y - (size.y / 2.0f);
|
||||
offset.z += position.z - (size.z / 2.0f);
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
uf::Collider* box = new uf::AABBox( offset, {0.5, 0.5, 0.5} );
|
||||
pCollider.add(box);
|
||||
}
|
||||
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>(); {
|
||||
collider.clear();
|
||||
uf::Collider* box = new uf::AABBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} );
|
||||
collider.add(box);
|
||||
}
|
||||
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
auto result = pCollider.intersects(collider);
|
||||
uf::Collider::Manifold strongest;
|
||||
strongest.depth = 0.001;
|
||||
bool useStrongest = true;
|
||||
for ( auto manifold : result ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
if ( !useStrongest ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(manifold.normal) * -(manifold.depth * manifold.depth * 1.001);
|
||||
transform.position += correction;
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(strongest.normal) * -(strongest.depth * strongest.depth * 1.001);
|
||||
transform.position += correction;
|
||||
|
||||
// std::cout << "Collision! " << ( strongest.colliding ? "yes" : "no" ) << " " << strongest.normal.x << ", " << strongest.normal.y << ", " << strongest.normal.z << " / " << strongest.depth << std::endl;
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
};
|
||||
auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, uf::Object* a, uf::Object* b, bool useStrongest ){
|
||||
pod::Collider::Manifold strongest;
|
||||
auto manifolds = colliderA.intersects(colliderB);
|
||||
for ( auto manifold : manifolds ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( !useStrongest ) onCollision(manifold, a, b);
|
||||
else if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if ( useStrongest && strongest.colliding ) onCollision(strongest, a, b);
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
/* Collision against world */ {
|
||||
auto function = [&]() -> int {
|
||||
if ( this->hasParent() && metadata["system"]["physics"]["collision"].asBool() ) {
|
||||
if ( !this->hasParent() ) { return 0; }
|
||||
if ( this->getParent().getName() != "Region" ) { return 0; }
|
||||
|
||||
/* Collision against world */ if ( false ) {
|
||||
auto function = [&]() -> int {
|
||||
if ( this->hasParent() && metadata["collision"]["should"].asBool() ) {
|
||||
if ( !this->hasParent() ) { return 0; }
|
||||
if ( this->getName() == "Player" ) { return 0; }
|
||||
if ( this->getParent().getName() != "Region" ) { return 0; }
|
||||
if ( !this->getParent().hasParent() ) { return 0; }
|
||||
if ( this->getParent().getParent().getName() != "Terrain" ) { return 0; }
|
||||
uf::Entity& parent = this->getParent();
|
||||
ext::TerrainGenerator& generator = parent.getComponent<ext::TerrainGenerator>();
|
||||
uf::Serializer& rMetadata = parent.getComponent<uf::Serializer>();
|
||||
pod::Transform<>& rTransform = parent.getComponent<pod::Transform<>>();
|
||||
|
||||
uf::Entity& parentRegion = this->getParent();
|
||||
uf::Entity& parentTerrain = parentRegion.getParent();
|
||||
pod::Vector3ui size; {
|
||||
size.x = rMetadata["region"]["size"][0].asUInt();
|
||||
size.y = rMetadata["region"]["size"][1].asUInt();
|
||||
size.z = rMetadata["region"]["size"][2].asUInt();
|
||||
}
|
||||
pod::Vector3f voxelPosition = transform.position - rTransform.position;
|
||||
voxelPosition.x += size.x / 2.0f;
|
||||
voxelPosition.y += size.y / 2.0f + 1;
|
||||
voxelPosition.z += size.z / 2.0f;
|
||||
|
||||
int regions = 0;
|
||||
std::vector<uf::Entity*> entities;
|
||||
entities.push_back(&parentRegion);
|
||||
if ( false ) {
|
||||
/* Retrieve close entities */ for ( uf::Entity* kv : parentTerrain.getChildren() ) { if ( !kv ) continue; if ( kv->getName() != "Region" ) continue;
|
||||
if ( kv->getUid() == parentRegion.getUid() ) continue;
|
||||
uf::Serializer& rMetadata = kv->getComponent<uf::Serializer>();
|
||||
if ( !rMetadata["region"]["initialized"].asBool() ) continue;
|
||||
if ( ++regions <= 2 ) entities.push_back(kv);
|
||||
uf::Collider pCollider;
|
||||
std::vector<pod::Vector3ui> positions = {
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x - 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x + 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y - 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y + 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z - 1 },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z + 1},
|
||||
};
|
||||
if ( this->m_name == "HousamoSprite" ) {
|
||||
// bottom
|
||||
uint16_t uid = generator.getVoxel( voxelPosition.x, voxelPosition.y, voxelPosition.z );
|
||||
auto light = generator.getLight( voxelPosition.x, voxelPosition.y, voxelPosition.z );
|
||||
metadata["color"][0] = ((light >> 12) & 0xF) / (float) (0xF);
|
||||
metadata["color"][1] = ((light >> 8) & 0xF) / (float) (0xF);
|
||||
metadata["color"][2] = ((light >> 4) & 0xF) / (float) (0xF);
|
||||
metadata["color"][3] = ((light ) & 0xF) / (float) (0xF);
|
||||
// if ( uid == ext::TerrainVoxelLava().uid() ) this->callHook("world:Craeture.Hurt.%UID%");
|
||||
}
|
||||
|
||||
for ( auto& position : positions ) {
|
||||
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( generator.getVoxel( position.x, position.y, position.z ) );
|
||||
pod::Vector3 offset = rTransform.position;
|
||||
offset.x += position.x - (size.x / 2.0f);
|
||||
offset.y += position.y - (size.y / 2.0f);
|
||||
offset.z += position.z - (size.z / 2.0f);
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
pCollider.add( new uf::BoundingBox( offset, {0.5, 0.5, 0.5} ) );
|
||||
}
|
||||
|
||||
uf::Collider& collider = this->getComponent<uf::Collider>();
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
|
||||
{
|
||||
collider.clear();
|
||||
collider.add(new uf::BoundingBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} ));
|
||||
}
|
||||
|
||||
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
|
||||
auto result = pCollider.intersects(collider);
|
||||
pod::Collider::Manifold strongest;
|
||||
|
||||
for ( auto manifold : result ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
if ( !useStrongest ) {
|
||||
pod::Vector3 correction = manifold.normal * manifold.depth;
|
||||
transform.position -= correction;
|
||||
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) {
|
||||
pod::Vector3 correction = strongest.normal * strongest.depth;
|
||||
transform.position -= correction;
|
||||
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
|
||||
/* Collision against other craetures */ {
|
||||
auto function = [&]() -> int {
|
||||
/* Collision */ if ( this->hasParent() && metadata["system"]["physics"]["collision"].asBool() ) {
|
||||
if ( !this->hasParent() ) { return 0; }
|
||||
if ( this->getParent().getName() != "Region" ) { return 0; }
|
||||
|
||||
uf::Entity& parent = this->getParent();
|
||||
|
||||
int regions = 0;
|
||||
std::vector<uf::Entity*> entities;
|
||||
/* Retrieve close entities */ for ( uf::Entity* kv : parent.getChildren() ) {
|
||||
if ( !kv ) continue;
|
||||
if ( kv->getUid() == this->getUid() ) continue;
|
||||
if ( !kv->hasComponent<uf::Collider>() ) continue;
|
||||
entities.push_back(kv);
|
||||
}
|
||||
/* Sort by closest to farthest */ if ( sort ) {
|
||||
const pod::Vector3& position = this->getComponent<pod::Transform<>>().position;
|
||||
@ -309,146 +336,284 @@ void ext::Craeture::tick() {
|
||||
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
for ( uf::Entity* e : entities ) {
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
uf::CollisionBody& pCollider = e->getComponent<uf::CollisionBody>();
|
||||
for ( uf::Entity* e : entities ) {
|
||||
if ( e->getUid() == 0 ) continue;
|
||||
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>(); {
|
||||
collider.clear();
|
||||
uf::Collider* box = new uf::AABBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} );
|
||||
collider.add(box);
|
||||
}
|
||||
uf::Collider& collider = this->getComponent<uf::Collider>();
|
||||
uf::Collider& pCollider = e->getComponent<uf::Collider>();
|
||||
|
||||
if ( !e ) continue;
|
||||
if ( e->getUid() == 0 ) continue;
|
||||
if ( this->getUid() == 0 ) return 0;
|
||||
if ( !this->hasComponent<pod::Physics>() ) return 0;
|
||||
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
auto result = pCollider.intersects(collider);
|
||||
uf::Collider::Manifold strongest;
|
||||
strongest.depth = 0.001;
|
||||
bool useStrongest = true;
|
||||
for ( auto manifold : result ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
if ( !useStrongest ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(manifold.normal) * -(manifold.depth * manifold.depth * 1.001);
|
||||
transform.position += correction;
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(strongest.normal) * -(strongest.depth * strongest.depth * 1.001);
|
||||
transform.position += correction;
|
||||
|
||||
// std::cout << "Collision! " << ( strongest.colliding ? "yes" : "no" ) << " " << strongest.normal.x << ", " << strongest.normal.y << ", " << strongest.normal.z << " / " << strongest.depth << std::endl;
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
|
||||
/* Collision against other craetures */ {
|
||||
auto function = [&]() -> int {
|
||||
/* Collision */ if ( this->hasParent() && metadata["collision"]["should"].asBool() ) {
|
||||
if ( !this->hasParent() ) { return 0; }
|
||||
if ( this->getParent().getName() != "Region" ) { return 0; }
|
||||
|
||||
uf::Entity& parent = this->getParent();
|
||||
|
||||
int regions = 0;
|
||||
std::vector<uf::Entity*> entities;
|
||||
/* Retrieve close entities */ for ( uf::Entity* kv : parent.getChildren() ) {
|
||||
if ( !kv ) continue;
|
||||
if ( kv->getUid() == this->getUid() ) continue;
|
||||
if ( !kv->hasComponent<uf::CollisionBody>() ) continue;
|
||||
entities.push_back(kv);
|
||||
}
|
||||
/* Sort by closest to farthest */ if ( sort ) {
|
||||
const pod::Vector3& position = this->getComponent<pod::Transform<>>().position;
|
||||
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
|
||||
if ( !l ) return false; if ( !r ) return true;
|
||||
if ( l->getUid() == 0 ) return false; if ( r->getUid() == 0 ) return true;
|
||||
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
|
||||
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
|
||||
} );
|
||||
}
|
||||
|
||||
for ( uf::Entity* e : entities ) {
|
||||
if ( e->getUid() == 0 ) continue;
|
||||
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
uf::CollisionBody& pCollider = e->getComponent<uf::CollisionBody>();
|
||||
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>(); {
|
||||
collider.clear();
|
||||
uf::Collider* box = new uf::AABBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} );
|
||||
collider.add(box);
|
||||
}
|
||||
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
auto result = pCollider.intersects(collider);
|
||||
uf::Collider::Manifold strongest;
|
||||
strongest.depth = 0.001;
|
||||
bool useStrongest = true;
|
||||
for ( auto manifold : result ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
if ( !useStrongest ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(manifold.normal) * -(manifold.depth * manifold.depth * 1.001);
|
||||
transform.position += correction;
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
uf::Serializer& pSerializer = e->getComponent<uf::Serializer>();
|
||||
|
||||
|
||||
if ( useStrongest && strongest.colliding ) {
|
||||
// signal collision, if available
|
||||
pod::Vector3 correction = uf::vector::normalize(strongest.normal) * -(strongest.depth * strongest.depth * 1.001);
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
|
||||
{
|
||||
uf::Serializer payload;
|
||||
payload["entity"] = e->getUid();
|
||||
payload["correction"]["x"] = correction.x;
|
||||
payload["correction"]["y"] = correction.y;
|
||||
payload["correction"]["z"] = correction.z;
|
||||
payload["depth"] = strongest.depth;
|
||||
payload["normal"]["x"] = strongest.normal.x;
|
||||
payload["normal"]["y"] = strongest.normal.y;
|
||||
payload["normal"]["z"] = strongest.normal.z;
|
||||
uf::hooks.call("world:Collision." + std::to_string(this->getUid()), payload);
|
||||
collider.clear();
|
||||
collider.add(new uf::BoundingBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} ));
|
||||
}
|
||||
|
||||
|
||||
auto result = pCollider.intersects(collider);
|
||||
|
||||
pod::Collider::Manifold strongest;
|
||||
|
||||
for ( auto manifold : result ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
if ( !useStrongest ) {
|
||||
pod::Vector3 correction = manifold.normal * manifold.depth;
|
||||
transform.position += correction;
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transform.position += correction;
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
uf::Serializer& pSerializer = e->getComponent<uf::Serializer>();
|
||||
|
||||
// std::cout << "Collision! " << ( strongest.colliding ? "yes" : "no" ) << " " << strongest.normal.x << ", " << strongest.normal.y << ", " << strongest.normal.z << " / " << strongest.depth << std::endl;
|
||||
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
if ( useStrongest && strongest.colliding ) {
|
||||
// signal collision, if available
|
||||
pod::Vector3 correction = strongest.normal * strongest.depth;
|
||||
{
|
||||
uf::Serializer payload;
|
||||
payload["entity"] = e->getUid();
|
||||
payload["correction"]["x"] = correction.x;
|
||||
payload["correction"]["y"] = correction.y;
|
||||
payload["correction"]["z"] = correction.z;
|
||||
payload["depth"] = strongest.depth;
|
||||
payload["normal"]["x"] = strongest.normal.x;
|
||||
payload["normal"]["y"] = strongest.normal.y;
|
||||
payload["normal"]["z"] = strongest.normal.z;
|
||||
uf::hooks.call("world:Collision." + std::to_string(this->getUid()), payload);
|
||||
}
|
||||
transform.position -= correction;
|
||||
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
} else if ( false ) {
|
||||
bool sort = false;
|
||||
bool local = false;
|
||||
bool useStrongest = true;
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
auto onCollision = []( pod::Collider::Manifold& manifold, uf::Object* a, uf::Object* b ){
|
||||
pod::Transform<>& transform = b->getComponent<pod::Transform<>>();
|
||||
pod::Physics& physics = b->getComponent<pod::Physics>();
|
||||
|
||||
uf::Serializer payload;
|
||||
pod::Vector3 correction = manifold.normal * manifold.depth;
|
||||
transform.position -= correction;
|
||||
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
};
|
||||
auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, uf::Object* a, uf::Object* b, bool useStrongest ){
|
||||
pod::Collider::Manifold strongest;
|
||||
auto manifolds = colliderA.intersects(colliderB);
|
||||
for ( auto manifold : manifolds ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( !useStrongest ) onCollision(manifold, a, b);
|
||||
else if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) onCollision(strongest, a, b);
|
||||
};
|
||||
/* Collision against world */ {
|
||||
auto function = [&]() -> int {
|
||||
if ( this->hasParent() && metadata["system"]["physics"]["collision"].asBool() ) {
|
||||
if ( !this->hasParent() ) { return 0; }
|
||||
if ( this->getParent().getName() != "Region" ) { return 0; }
|
||||
|
||||
uf::Entity& parent = this->getParent();
|
||||
ext::TerrainGenerator& generator = parent.getComponent<ext::TerrainGenerator>();
|
||||
uf::Serializer& rMetadata = parent.getComponent<uf::Serializer>();
|
||||
pod::Transform<>& rTransform = parent.getComponent<pod::Transform<>>();
|
||||
|
||||
pod::Vector3ui size; {
|
||||
size.x = rMetadata["region"]["size"][0].asUInt();
|
||||
size.y = rMetadata["region"]["size"][1].asUInt();
|
||||
size.z = rMetadata["region"]["size"][2].asUInt();
|
||||
}
|
||||
pod::Vector3f voxelPosition = transform.position - rTransform.position;
|
||||
voxelPosition.x += size.x / 2.0f;
|
||||
voxelPosition.y += size.y / 2.0f + 1;
|
||||
voxelPosition.z += size.z / 2.0f;
|
||||
|
||||
uf::Collider pCollider;
|
||||
std::vector<pod::Vector3ui> positions = {
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x - 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x + 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y - 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y + 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z - 1 },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z + 1},
|
||||
};
|
||||
if ( this->m_name == "HousamoSprite" ) {
|
||||
uint16_t uid = generator.getVoxel( voxelPosition.x, voxelPosition.y, voxelPosition.z );
|
||||
auto light = generator.getLight( voxelPosition.x, voxelPosition.y, voxelPosition.z );
|
||||
metadata["color"][0] = ((light >> 12) & 0xF) / (float) (0xF);
|
||||
metadata["color"][1] = ((light >> 8) & 0xF) / (float) (0xF);
|
||||
metadata["color"][2] = ((light >> 4) & 0xF) / (float) (0xF);
|
||||
metadata["color"][3] = ((light ) & 0xF) / (float) (0xF);
|
||||
// if ( uid == ext::TerrainVoxelLava().uid() ) this->callHook("world:Craeture.Hurt.%UID%");
|
||||
}
|
||||
|
||||
for ( auto& position : positions ) {
|
||||
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( generator.getVoxel( position.x, position.y, position.z ) );
|
||||
pod::Vector3 offset = rTransform.position;
|
||||
offset.x += position.x - (size.x / 2.0f);
|
||||
offset.y += position.y - (size.y / 2.0f);
|
||||
offset.z += position.z - (size.z / 2.0f);
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
pCollider.add( new uf::BoundingBox( offset, {0.5, 0.5, 0.5} ) );
|
||||
}
|
||||
|
||||
uf::Collider& collider = this->getComponent<uf::Collider>();
|
||||
testColliders( pCollider, collider, (uf::Object*) &parent, this, useStrongest );
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
} else if ( false ) {
|
||||
bool local = false;
|
||||
bool sort = false;
|
||||
bool useStrongest = false;
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
auto function = [&]() -> int {
|
||||
std::vector<uf::Object*> entities;
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
auto& metadata = entity->getComponent<uf::Serializer>();
|
||||
if ( !metadata["system"]["physics"]["collision"].isNull() && !metadata["system"]["physics"]["collision"].asBool() ) return;
|
||||
if ( entity->hasComponent<uf::Collider>() )
|
||||
entities.push_back((uf::Object*) entity);
|
||||
};
|
||||
uf::Entity* regionPointer = &this->getParent();
|
||||
if ( regionPointer->getName() != "Region" ) return 0;
|
||||
ext::Region& region = *(ext::Region*) regionPointer;
|
||||
region.process(filter);
|
||||
auto onCollision = []( pod::Collider::Manifold& manifold, uf::Object* a, uf::Object* b ){
|
||||
uf::Serializer payload;
|
||||
payload["normal"][0] = manifold.normal.x;
|
||||
payload["normal"][1] = manifold.normal.y;
|
||||
payload["normal"][2] = manifold.normal.z;
|
||||
payload["entity"] = b->getUid();
|
||||
payload["depth"] = -manifold.depth;
|
||||
a->callHook("world:Collision.%UID%", payload);
|
||||
|
||||
payload["entity"] = a->getUid();
|
||||
payload["depth"] = manifold.depth;
|
||||
b->callHook("world:Collision.%UID%", payload);
|
||||
};
|
||||
auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, uf::Object* a, uf::Object* b, bool useStrongest ){
|
||||
pod::Collider::Manifold strongest;
|
||||
auto manifolds = colliderA.intersects(colliderB);
|
||||
for ( auto manifold : manifolds ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( !useStrongest ) onCollision(manifold, a, b);
|
||||
else if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) onCollision(strongest, a, b);
|
||||
};
|
||||
|
||||
// collide with world
|
||||
auto& metadata = region.getComponent<uf::Serializer>();
|
||||
auto& generator = region.getComponent<ext::TerrainGenerator>();
|
||||
auto& regionPosition = region.getComponent<pod::Transform<>>().position;
|
||||
pod::Vector3f size; {
|
||||
size.x = metadata["region"]["size"][0].asUInt();
|
||||
size.y = metadata["region"]["size"][1].asUInt();
|
||||
size.z = metadata["region"]["size"][2].asUInt();
|
||||
}
|
||||
for ( auto* _ : entities ) {
|
||||
uf::Object& entity = *_;
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
|
||||
pod::Vector3f voxelPosition = transform.position - regionPosition;
|
||||
voxelPosition.x += size.x / 2.0f;
|
||||
voxelPosition.y += size.y / 2.0f + 1;
|
||||
voxelPosition.z += size.z / 2.0f;
|
||||
|
||||
uf::Collider collider;
|
||||
std::vector<pod::Vector3ui> positions = {
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x - 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x + 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y - 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y + 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z - 1 },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z + 1},
|
||||
};
|
||||
for ( auto& position : positions ) {
|
||||
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( generator.getVoxel( position.x, position.y, position.z ) );
|
||||
pod::Vector3 offset = regionPosition;
|
||||
offset.x += position.x - (size.x / 2.0f);
|
||||
offset.y += position.y - (size.y / 2.0f);
|
||||
offset.z += position.z - (size.z / 2.0f);
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
collider.add( new uf::BoundingBox( offset, {0.5, 0.5, 0.5} ) );
|
||||
/*
|
||||
uf::BaseMesh<pod::Vertex_3F> mesh;
|
||||
const ext::TerrainVoxel::Model& model = voxel.model();
|
||||
#define TERRAIN_SHOULD_RENDER_FACE(SIDE)\
|
||||
for ( uint i = 0; i < model.position.SIDE.size() / 3; ++i ) {\
|
||||
auto& vertex = mesh.vertices.emplace_back();\
|
||||
{\
|
||||
pod::Vector3f& p = vertex.position;\
|
||||
p.x = model.position.SIDE[i*3+0]; p.y = model.position.SIDE[i*3+1]; p.z = model.position.SIDE[i*3+2];\
|
||||
p.x += offset.x; p.y += offset.y; p.z += offset.z;\
|
||||
}\
|
||||
}
|
||||
TERRAIN_SHOULD_RENDER_FACE(left)
|
||||
TERRAIN_SHOULD_RENDER_FACE(right)
|
||||
TERRAIN_SHOULD_RENDER_FACE(top)
|
||||
TERRAIN_SHOULD_RENDER_FACE(bottom)
|
||||
TERRAIN_SHOULD_RENDER_FACE(back)
|
||||
TERRAIN_SHOULD_RENDER_FACE(front)
|
||||
uf::MeshCollider* mCollider = new uf::MeshCollider();
|
||||
mCollider->setPositions( mesh );
|
||||
pCollider.add(mCollider);
|
||||
*/
|
||||
}
|
||||
testColliders( collider, entity.getComponent<uf::Collider>(), this, &entity, useStrongest );
|
||||
}
|
||||
|
||||
// collide with others
|
||||
for ( auto* _a : entities ) {
|
||||
uf::Object& entityA = *_a;
|
||||
for ( auto* _b : entities ) { if ( _a == _b ) continue;
|
||||
uf::Object& entityB = *_b;
|
||||
{
|
||||
uf::Collider& collider = entityB.getComponent<uf::Collider>();
|
||||
pod::Transform<>& transform = entityB.getComponent<pod::Transform<>>();
|
||||
collider.clear();
|
||||
collider.add(uf::BoundingBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} ));
|
||||
}
|
||||
testColliders( entityA.getComponent<uf::Collider>(), entityB.getComponent<uf::Collider>(), &entityA, &entityB, useStrongest );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void ext::Craeture::render() {
|
||||
uf::Object::render();
|
||||
|
||||
@ -136,8 +136,21 @@ void ext::HousamoSprite::render() {
|
||||
if ( !metadata["system"]["loaded"].asBool() ) return;
|
||||
|
||||
ext::Craeture::render();
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Mesh>() ) {
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& mesh = this->getComponent<uf::Mesh>();
|
||||
auto& scene = this->getRootParent<uf::Scene>();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& transform = this->getComponent<pod::Transform<>>();
|
||||
auto& camera = scene.getController()->getComponent<uf::Camera>();
|
||||
if ( !graphic.initialized ) return;
|
||||
// auto& uniforms = graphic.uniforms<uf::StereoMeshDescriptor>();
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
uniforms.matrices.model = uf::transform::model( transform );
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
uniforms.matrices.view[i] = camera.getView( i );
|
||||
uniforms.matrices.projection[i] = camera.getProjection( i );
|
||||
}
|
||||
/*
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = *scene.getController();
|
||||
@ -152,6 +165,7 @@ void ext::HousamoSprite::render() {
|
||||
uniforms.matrices.view[i] = camera.getView( i );
|
||||
uniforms.matrices.projection[i] = camera.getProjection( i );
|
||||
}
|
||||
*/
|
||||
uniforms.color[0] = metadata["color"][0].asFloat();
|
||||
uniforms.color[1] = metadata["color"][1].asFloat();
|
||||
uniforms.color[2] = metadata["color"][2].asFloat();
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <uf/ext/vulkan/rendertarget.h>
|
||||
#include <uf/ext/vulkan/rendermodes/rendertarget.h>
|
||||
#include <uf/utils/math/transform.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
|
||||
EXT_OBJECT_REGISTER_CPP(Light)
|
||||
@ -11,86 +12,64 @@ void ext::Light::initialize() {
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
auto& transform = this->getComponent<pod::Transform<>>();
|
||||
auto& camera = this->getComponent<uf::Camera>();
|
||||
{
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = *scene.getController();
|
||||
camera = controller.getComponent<uf::Camera>();
|
||||
|
||||
camera.setFov( metadata["light"]["fov"].asFloat() );
|
||||
}
|
||||
{
|
||||
if ( metadata["light"]["shadows"]["enabled"].asBool() ) {
|
||||
auto& renderMode = this->getComponent<ext::vulkan::RenderTargetRenderMode>();
|
||||
renderMode.width = 512;
|
||||
renderMode.height = 512;
|
||||
std::string name = "Render Target: " + std::to_string((int) this->getUid());
|
||||
ext::vulkan::addRenderMode( &renderMode, name );
|
||||
if ( metadata["light"]["shadows"]["resolution"].isArray() ) {
|
||||
renderMode.width = metadata["light"]["shadows"]["resolution"][0].asUInt64();
|
||||
renderMode.height = metadata["light"]["shadows"]["resolution"][1].asUInt64();
|
||||
} else {
|
||||
renderMode.width = metadata["light"]["shadows"]["resolution"].asUInt64();
|
||||
renderMode.height = metadata["light"]["shadows"]["resolution"].asUInt64();
|
||||
}
|
||||
{
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = *scene.getController();
|
||||
|
||||
camera = controller.getComponent<uf::Camera>();
|
||||
camera.getTransform() = {};
|
||||
camera.setStereoscopic(false);
|
||||
if ( metadata["light"]["shadows"]["fov"].isNumeric() ) {
|
||||
camera.setFov( metadata["light"]["shadows"]["fov"].asFloat() );
|
||||
camera.updateProjection();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !metadata["light"].isArray() ) {
|
||||
metadata["light"]["color"][0] = 1; //metadata["light"]["color"]["random"].asBool() ? (rand() % 100) / 100.0 : 1;
|
||||
metadata["light"]["color"][1] = 1; //metadata["light"]["color"]["random"].asBool() ? (rand() % 100) / 100.0 : 1;
|
||||
metadata["light"]["color"][2] = 1; //metadata["light"]["color"]["random"].asBool() ? (rand() % 100) / 100.0 : 1;
|
||||
}
|
||||
}
|
||||
void ext::Light::tick() {
|
||||
uf::Object::tick();
|
||||
|
||||
auto& renderMode = this->getComponent<ext::vulkan::RenderTargetRenderMode>();
|
||||
renderMode.target = "";
|
||||
if ( this->hasComponent<ext::vulkan::RenderTargetRenderMode>() ) {
|
||||
auto& renderMode = this->getComponent<ext::vulkan::RenderTargetRenderMode>();
|
||||
renderMode.target = "";
|
||||
}
|
||||
|
||||
auto& camera = this->getComponent<uf::Camera>();
|
||||
auto& transform = this->getComponent<pod::Transform<>>();
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform ) ), i );
|
||||
if ( this->hasComponent<pod::Physics>() ) {
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
transform = uf::physics::update( transform, physics );
|
||||
}
|
||||
auto& camera = this->getComponent<uf::Camera>();
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
if ( metadata["light"]["external update"].isNull() || (!metadata["light"]["external update"].isNull() && !metadata["light"]["external update"].asBool()) ) {
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
camera.setView( uf::matrix::inverse( uf::transform::model( transform ) ), i );
|
||||
}
|
||||
}
|
||||
}
|
||||
void ext::Light::render() {
|
||||
uf::Object::render();
|
||||
/*
|
||||
{
|
||||
auto& renderMode = this->getComponent<ext::vulkan::RenderTargetRenderMode>();
|
||||
auto& blitter = renderMode.blitter;
|
||||
|
||||
auto& transform = this->getComponent<pod::Transform<>>();
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = *scene.getController();
|
||||
auto& camera = this->getComponent<uf::Camera>();
|
||||
auto& controllerCamera = controller.getComponent<uf::Camera>();
|
||||
if ( !blitter.initialized ) return;
|
||||
|
||||
struct UniformDescriptor {
|
||||
struct {
|
||||
alignas(16) pod::Matrix4f models[2];
|
||||
} matrices;
|
||||
struct {
|
||||
alignas(8) pod::Vector2f position = { 0.5f, 0.5f };
|
||||
alignas(8) pod::Vector2f radius = { 0.1f, 0.1f };
|
||||
alignas(16) pod::Vector4f color = { 1, 1, 1, 1 };
|
||||
} cursor;
|
||||
alignas(4) float alpha;
|
||||
};
|
||||
|
||||
auto& shader = blitter.material.shaders.front();
|
||||
auto& uniforms = shader.uniforms.front().get<UniformDescriptor>();
|
||||
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
pod::Matrix4f model = uf::transform::model( transform );
|
||||
|
||||
uniforms.matrices.models[i] = controllerCamera.getProjection(i) * controllerCamera.getView(i) * model;
|
||||
|
||||
uniforms.alpha = 1.0f;
|
||||
|
||||
uniforms.cursor.position.x = -1.0f;
|
||||
uniforms.cursor.position.y = -1.0f;
|
||||
|
||||
uniforms.cursor.radius.x = 0.0f;
|
||||
uniforms.cursor.radius.y = 0.0f;
|
||||
|
||||
uniforms.cursor.color.x = 0.0f;
|
||||
uniforms.cursor.color.y = 0.0f;
|
||||
uniforms.cursor.color.z = 0.0f;
|
||||
uniforms.cursor.color.w = 0.0f;
|
||||
}
|
||||
shader.updateBuffer( (void*) &uniforms, sizeof(uniforms), 0 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
void ext::Light::destroy() {
|
||||
auto& renderMode = this->getComponent<ext::vulkan::RenderTargetRenderMode>();
|
||||
ext::vulkan::removeRenderMode( &renderMode, false );
|
||||
if ( this->hasComponent<ext::vulkan::RenderTargetRenderMode>() ) {
|
||||
auto& renderMode = this->getComponent<ext::vulkan::RenderTargetRenderMode>();
|
||||
ext::vulkan::removeRenderMode( &renderMode, false );
|
||||
}
|
||||
uf::Object::destroy();
|
||||
}
|
||||
@ -17,12 +17,11 @@
|
||||
namespace {
|
||||
struct {
|
||||
uf::Object left, right;
|
||||
} hands;
|
||||
|
||||
|
||||
} hands, lines;
|
||||
struct {
|
||||
uf::Object left, right;
|
||||
} lines;
|
||||
uf::Object* left;
|
||||
uf::Object* right;
|
||||
} lights;
|
||||
}
|
||||
|
||||
EXT_OBJECT_REGISTER_CPP(Hands)
|
||||
@ -35,8 +34,8 @@ void ext::Hands::initialize() {
|
||||
this->addChild(::hands.left);
|
||||
this->addChild(::hands.right);
|
||||
|
||||
this->addChild(::lines.left);
|
||||
this->addChild(::lines.right);
|
||||
::hands.left.addChild(::lines.left);
|
||||
::hands.right.addChild(::lines.right);
|
||||
}
|
||||
{
|
||||
bool loaded = true;
|
||||
@ -49,48 +48,51 @@ void ext::Hands::initialize() {
|
||||
uf::Serializer json = event;
|
||||
|
||||
std::string name = json["name"].asString();
|
||||
uf::Object* pointer = NULL;
|
||||
if ( name == metadata["hands"]["left"]["controller"]["model"].asString() ) pointer = &hands.left;
|
||||
else if ( name == metadata["hands"]["right"]["controller"]["model"].asString() ) pointer = &hands.right;
|
||||
else return "false";
|
||||
std::string side = "";
|
||||
if ( name == metadata["hands"]["left"]["controller"]["model"].asString() ) {
|
||||
side = "left";
|
||||
} else if ( name == metadata["hands"]["right"]["controller"]["model"].asString() ) {
|
||||
side = "right";
|
||||
};
|
||||
if ( side == "" ) return "false";
|
||||
|
||||
uf::Object& hand = side == "left" ? hands.left : hands.right;
|
||||
uf::Object& line = side == "left" ? lines.left : lines.right;
|
||||
{
|
||||
uf::Object& hand = *pointer;
|
||||
uf::Graphic& graphic = (hand.getComponent<uf::Graphic>() = ext::openvr::getRenderModel( name ));
|
||||
|
||||
graphic.process = true;
|
||||
|
||||
graphic.descriptor.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
graphic.material.attachShader("./data/shaders/base.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
hand.initialize();
|
||||
}
|
||||
{
|
||||
std::string hand = pointer == &hands.left ? "left" : "right";
|
||||
auto& line = pointer == &hands.left ? lines.left : lines.right;
|
||||
if ( metadata["hands"][side]["pointer"]["length"].asFloat() > 0 ) {
|
||||
line.addAlias<uf::LineMesh, uf::Mesh>();
|
||||
|
||||
pod::Transform<>& transform = line.getComponent<pod::Transform<>>();
|
||||
transform.orientation = uf::quaternion::axisAngle(
|
||||
{
|
||||
metadata["hands"][hand]["pointer"]["orientation"]["axis"][0].asFloat(),
|
||||
metadata["hands"][hand]["pointer"]["orientation"]["axis"][1].asFloat(),
|
||||
metadata["hands"][hand]["pointer"]["orientation"]["axis"][2].asFloat()
|
||||
metadata["hands"][side]["pointer"]["orientation"]["axis"][0].asFloat(),
|
||||
metadata["hands"][side]["pointer"]["orientation"]["axis"][1].asFloat(),
|
||||
metadata["hands"][side]["pointer"]["orientation"]["axis"][2].asFloat()
|
||||
},
|
||||
metadata["hands"][hand]["pointer"]["orientation"]["angle"].asFloat() * 3.14159f / 180.0f
|
||||
metadata["hands"][side]["pointer"]["orientation"]["angle"].asFloat() * 3.14159f / 180.0f
|
||||
);
|
||||
transform.position = {
|
||||
metadata["hands"][hand]["pointer"]["offset"][0].asFloat(),
|
||||
metadata["hands"][hand]["pointer"]["offset"][1].asFloat(),
|
||||
metadata["hands"][hand]["pointer"]["offset"][2].asFloat()
|
||||
metadata["hands"][side]["pointer"]["offset"][0].asFloat(),
|
||||
metadata["hands"][side]["pointer"]["offset"][1].asFloat(),
|
||||
metadata["hands"][side]["pointer"]["offset"][2].asFloat()
|
||||
};
|
||||
|
||||
auto& mesh = line.getComponent<uf::LineMesh>();
|
||||
auto& graphic = line.getComponent<uf::Graphic>();
|
||||
|
||||
mesh.vertices = {
|
||||
{ {0.0f, 0.0f, 0.0f} },
|
||||
{ {0.0f, 0.0f, metadata["hands"][hand]["pointer"]["length"].asFloat()} },
|
||||
{ {0.0f, 0.0f, 0.0f} },
|
||||
{ {0.0f, 0.0f, metadata["hands"][side]["pointer"]["length"].asFloat()} },
|
||||
};
|
||||
graphic.initialize();
|
||||
graphic.initializeGeometry(mesh);
|
||||
@ -99,27 +101,31 @@ void ext::Hands::initialize() {
|
||||
graphic.material.attachShader("./data/shaders/line.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
graphic.descriptor.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
|
||||
graphic.descriptor.fill = VK_POLYGON_MODE_LINE;
|
||||
graphic.descriptor.lineWidth = metadata["hands"][hand]["pointer"]["width"].asFloat();
|
||||
/*
|
||||
graphic.initializeShaders({
|
||||
{"./data/shaders/line.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
|
||||
{"./data/shaders/line.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
|
||||
});
|
||||
mesh.generate();
|
||||
graphic.bindUniform<uf::StereoMeshDescriptor>();
|
||||
graphic.description.rasterMode.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
|
||||
graphic.description.rasterMode.fill = VK_POLYGON_MODE_LINE;
|
||||
graphic.description.rasterMode.lineWidth = metadata["hands"][hand]["pointer"]["width"].asFloat();
|
||||
graphic.initialize();
|
||||
graphic.autoAssign();
|
||||
*/
|
||||
graphic.descriptor.lineWidth = metadata["hands"][side]["pointer"]["width"].asFloat();
|
||||
|
||||
line.initialize();
|
||||
}
|
||||
if ( metadata["hands"][side]["light"]["should"].asBool() ){
|
||||
auto* child = (uf::Object*) hand.findByUid(hand.loadChild("/light.json", false));
|
||||
if ( child ) {
|
||||
if (side == "left" ) lights.left = child; else lights.right = child;
|
||||
auto& json = metadata["hands"][side]["light"];
|
||||
auto& light = side == "left" ? *lights.left : *lights.right;
|
||||
|
||||
auto& metadata = light.getComponent<uf::Serializer>();
|
||||
if ( !json["color"].isNull() ) metadata["light"]["color"] = json["color"];
|
||||
if ( !json["radius"].isNull() ) metadata["light"]["radius"] = json["radius"];
|
||||
if ( !json["power"].isNull() ) metadata["light"]["power"] = json["power"];
|
||||
if ( !json["shadows"].isNull() ) metadata["light"]["shadows"] = json["shadows"];
|
||||
metadata["lights"]["external update"] = true;
|
||||
|
||||
light.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
return "true";
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<uf::Object*> vHands = { &::hands.left, &::hands.right };
|
||||
for ( auto pointer : vHands ) {
|
||||
auto& hand = *pointer;
|
||||
@ -142,12 +148,34 @@ void ext::Hands::initialize() {
|
||||
payload["mouse"]["button"] = side == "left" ? "Right" : "Left";
|
||||
payload["mouse"]["state"] = json["state"].asBool() ? "Down": "Up";
|
||||
|
||||
|
||||
uf::hooks.call( payload["type"].asString(), payload );
|
||||
}
|
||||
|
||||
return "true";
|
||||
});
|
||||
hand.addHook("world:Collision.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
|
||||
std::string side = &hand == &hands.left ? "left" : "right";
|
||||
|
||||
float mag = json["depth"].asFloat();
|
||||
uf::Serializer payload;
|
||||
payload["delay"] = 0.0f;
|
||||
payload["duration"] = uf::physics::time::delta;
|
||||
payload["frequency"] = 1.0f;
|
||||
payload["amplitude"] = fmin(1.0f, 1000.0f * mag);
|
||||
payload["side"] = side;
|
||||
uf::hooks.call( "VR:Haptics." + side, payload );
|
||||
|
||||
return "true";
|
||||
});
|
||||
|
||||
auto& transform = hand.getComponent<pod::Transform<>>();
|
||||
auto& collider = hand.getComponent<uf::Collider>();
|
||||
|
||||
// auto* box = new uf::BoundingBox( transform.position, {0.25, 0.25, 0.25} );
|
||||
// box->getTransform().reference = &transform;
|
||||
// collider.add(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,26 +183,58 @@ void ext::Hands::tick() {
|
||||
uf::Object::tick();
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = *scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
auto& controllerCamera = controller.getComponent<uf::Camera>();
|
||||
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
|
||||
auto& controllerCameraTransform = controllerCamera.getTransform();
|
||||
{
|
||||
pod::Transform<>& transform = hands.left.getComponent<pod::Transform<>>();
|
||||
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Left );
|
||||
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Left );
|
||||
transform.scale = { 1, 1, 1 };
|
||||
// transform.reference = &camera.getTransform();
|
||||
transform.reference = &controllerTransform;
|
||||
|
||||
auto& collider = hands.left.getComponent<uf::Collider>();
|
||||
for ( auto* box : collider.getContainer() ) {
|
||||
box->getTransform().position = transform.position + controllerTransform.position + controllerCameraTransform.position;
|
||||
}
|
||||
}
|
||||
{
|
||||
pod::Transform<>& transform = hands.right.getComponent<pod::Transform<>>();
|
||||
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Right );
|
||||
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right );
|
||||
transform.scale = { 1, 1, 1 };
|
||||
// transform.reference = &camera.getTransform();
|
||||
transform.reference = &controllerTransform;
|
||||
|
||||
auto& collider = hands.right.getComponent<uf::Collider>();
|
||||
for ( auto* box : collider.getContainer() ) {
|
||||
box->getTransform().position = transform.position + controllerTransform.position + controllerCameraTransform.position;
|
||||
}
|
||||
}
|
||||
{
|
||||
pod::Transform<>& transform = lines.left.getComponent<pod::Transform<>>();
|
||||
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Left, true );
|
||||
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Left, true );
|
||||
transform.scale = { 1, 1, 1 };
|
||||
transform.reference = &controllerTransform;
|
||||
|
||||
if ( lights.left ) {
|
||||
auto& light = *lights.left;
|
||||
auto& lightTransform = light.getComponent<pod::Transform<>>();
|
||||
lightTransform.position = controllerCameraTransform.position + controller.getComponent<pod::Transform<>>().position + transform.position;
|
||||
// lightTransform.orientation = controllerTransform.orientation * transform.orientation;
|
||||
auto& lightCamera = light.getComponent<uf::Camera>();
|
||||
pod::Matrix4f playerModel = uf::matrix::identity();
|
||||
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), controllerCameraTransform.position + controllerTransform.position );
|
||||
pod::Matrix4f rotation = uf::quaternion::matrix( controllerTransform.orientation * pod::Vector4f{1,1,1,-1} );
|
||||
playerModel = translation * rotation;
|
||||
|
||||
pod::Matrix4f model = uf::matrix::inverse( playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, true ) );
|
||||
for ( size_t i = 0; i < 2; ++i ) lightCamera.setView( model, i );
|
||||
|
||||
// lightTransform.position = transform.position;
|
||||
// lightTransform.orientation = transform.orientation;
|
||||
// lightTransform.reference = &controllerTransform;
|
||||
}
|
||||
// transform.reference = hands.left.getComponentPointer<pod::Transform<>>();
|
||||
}
|
||||
{
|
||||
@ -182,6 +242,26 @@ void ext::Hands::tick() {
|
||||
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Right, true );
|
||||
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right, true );
|
||||
transform.scale = { 1, 1, 1 };
|
||||
transform.reference = &controllerTransform;
|
||||
|
||||
if ( lights.right ) {
|
||||
auto& light = *lights.right;
|
||||
auto& lightTransform = light.getComponent<pod::Transform<>>();
|
||||
lightTransform.position = controllerCameraTransform.position + controllerTransform.position + transform.position;
|
||||
// lightTransform.orientation = controllerTransform.orientation * transform.orientation;
|
||||
auto& lightCamera = light.getComponent<uf::Camera>();
|
||||
pod::Matrix4f playerModel = uf::matrix::identity();
|
||||
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), controllerCameraTransform.position + controllerTransform.position );
|
||||
pod::Matrix4f rotation = uf::quaternion::matrix( controllerTransform.orientation * pod::Vector4f{1,1,1,-1} );
|
||||
playerModel = translation * rotation;
|
||||
|
||||
pod::Matrix4f model = uf::matrix::inverse( playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, true ) );
|
||||
for ( size_t i = 0; i < 2; ++i ) lightCamera.setView( model, i );
|
||||
|
||||
// lightTransform.position = transform.position;
|
||||
// lightTransform.orientation = transform.orientation;
|
||||
// lightTransform.reference = &controllerTransform;
|
||||
}
|
||||
// transform.reference = hands.right.getComponentPointer<pod::Transform<>>();
|
||||
}
|
||||
|
||||
@ -256,9 +336,7 @@ void ext::Hands::tick() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DEBUG_MARKER() std::cout << side << ": " << __LINE__ << std::endl;
|
||||
|
||||
#if 0
|
||||
/* Collision against world */ {
|
||||
bool local = true;
|
||||
bool sort = false;
|
||||
@ -271,7 +349,7 @@ void ext::Hands::tick() {
|
||||
pod::Transform<> transform = hand.getComponent<pod::Transform<>>();
|
||||
transform.position = uf::quaternion::rotate( controller.getComponent<pod::Transform<>>().orientation, transform.position );
|
||||
transform.position += controller.getComponent<pod::Transform<>>().position;
|
||||
transform.position += camera.getTransform().position;
|
||||
transform.position += controllerCamera.getTransform().position;
|
||||
|
||||
uf::Entity& parent = controller.getParent();
|
||||
ext::TerrainGenerator& generator = parent.getComponent<ext::TerrainGenerator>();
|
||||
@ -319,13 +397,13 @@ void ext::Hands::tick() {
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
uf::Collider* box = new uf::AABBox( offset, {0.5, 0.5, 0.5} );
|
||||
uf::Collider* box = new uf::BoundingBox( offset, {0.5, 0.5, 0.5} );
|
||||
pCollider.add(box);
|
||||
}
|
||||
|
||||
uf::CollisionBody& collider = hand.getComponent<uf::CollisionBody>(); {
|
||||
collider.clear();
|
||||
uf::Collider* box = new uf::AABBox( transform.position, {0.25, 0.25, 0.25} );
|
||||
uf::Collider* box = new uf::BoundingBox( transform.position, {0.25, 0.25, 0.25} );
|
||||
collider.add(box);
|
||||
}
|
||||
|
||||
@ -351,17 +429,12 @@ void ext::Hands::tick() {
|
||||
payload["side"] = side;
|
||||
uf::hooks.call( "VR:Haptics." + side, payload );
|
||||
}
|
||||
/*
|
||||
transform.position += correction;
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
*/
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -373,13 +446,19 @@ void ext::Hands::render() {
|
||||
auto& controller = *scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
|
||||
pod::Matrix4f cameraModel = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position ) * uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation * pod::Vector4f{1,1,1,-1} );
|
||||
if ( hands.left.hasComponent<uf::Mesh>() ) {
|
||||
auto& mesh = hands.left.getComponent<uf::Mesh>();
|
||||
pod::Matrix4f playerModel = uf::matrix::identity(); {
|
||||
auto& controller = this->getParent();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position );
|
||||
pod::Matrix4f rotation = uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation * pod::Vector4f{1,1,1,-1} );
|
||||
playerModel = translation * rotation;
|
||||
}
|
||||
// pod::Matrix4f cameraModel = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position ) * uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation * pod::Vector4f{1,1,1,-1} );
|
||||
if ( hands.left.hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = hands.left.getComponent<uf::Graphic>();
|
||||
auto& transform = hands.left.getComponent<pod::Transform<>>();
|
||||
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Left );
|
||||
pod::Matrix4f model = cameraModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, false );
|
||||
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, false );
|
||||
if ( graphic.initialized ) {
|
||||
// auto& uniforms = graphic.uniforms<uf::StereoMeshDescriptor>();
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
@ -396,12 +475,11 @@ void ext::Hands::render() {
|
||||
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
|
||||
}
|
||||
}
|
||||
if ( hands.right.hasComponent<uf::Mesh>() ) {
|
||||
auto& mesh = hands.right.getComponent<uf::Mesh>();
|
||||
if ( hands.right.hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = hands.right.getComponent<uf::Graphic>();
|
||||
auto& transform = hands.right.getComponent<pod::Transform<>>();
|
||||
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Right );
|
||||
pod::Matrix4f model = cameraModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, false );
|
||||
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, false );
|
||||
if ( graphic.initialized ) {
|
||||
// auto& uniforms = graphic.uniforms<uf::StereoMeshDescriptor>();
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
@ -418,12 +496,11 @@ void ext::Hands::render() {
|
||||
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
|
||||
}
|
||||
}
|
||||
if ( lines.left.hasComponent<uf::Mesh>() ) {
|
||||
auto& mesh = lines.left.getComponent<uf::Mesh>();
|
||||
if ( lines.left.hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = lines.left.getComponent<uf::Graphic>();
|
||||
auto& transform = lines.left.getComponent<pod::Transform<>>();
|
||||
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Left );
|
||||
pod::Matrix4f model = cameraModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, true );
|
||||
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, true );
|
||||
if ( graphic.initialized ) {
|
||||
// auto& uniforms = graphic.uniforms<uf::StereoMeshDescriptor>();
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
@ -440,12 +517,11 @@ void ext::Hands::render() {
|
||||
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
|
||||
}
|
||||
}
|
||||
if ( lines.right.hasComponent<uf::Mesh>() ) {
|
||||
auto& mesh = lines.right.getComponent<uf::Mesh>();
|
||||
if ( lines.right.hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = lines.right.getComponent<uf::Graphic>();
|
||||
auto& transform = lines.right.getComponent<pod::Transform<>>();
|
||||
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Right );
|
||||
pod::Matrix4f model = cameraModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, true );
|
||||
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, true );
|
||||
if ( graphic.initialized ) {
|
||||
// auto& uniforms = graphic.uniforms<uf::StereoMeshDescriptor>();
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
|
||||
@ -63,6 +63,7 @@ void ext::Player::initialize() {
|
||||
pod::Vector2 bounds = {0.5, 128.0};
|
||||
} perspective;
|
||||
pod::Vector3 offset = {0, 0, 0};
|
||||
bool stereoscopic = true;
|
||||
} settings;
|
||||
|
||||
uf::Camera& camera = this->getComponent<uf::Camera>();
|
||||
@ -86,8 +87,8 @@ void ext::Player::initialize() {
|
||||
|
||||
camera.setFov(settings.perspective.fov);
|
||||
camera.setBounds(settings.perspective.bounds);
|
||||
|
||||
}
|
||||
camera.setStereoscopic(true);
|
||||
|
||||
settings.offset.x = metadata["camera"]["offset"][0].asDouble();
|
||||
settings.offset.y = metadata["camera"]["offset"][1].asDouble();
|
||||
@ -98,6 +99,10 @@ void ext::Player::initialize() {
|
||||
transform.position.x = metadata["camera"]["position"][0].asDouble();
|
||||
transform.position.y = metadata["camera"]["position"][1].asDouble();
|
||||
transform.position.z = metadata["camera"]["position"][2].asDouble();
|
||||
|
||||
transform.scale.x = metadata["camera"]["scale"][0].asDouble();
|
||||
transform.scale.y = metadata["camera"]["scale"][1].asDouble();
|
||||
transform.scale.z = metadata["camera"]["scale"][2].asDouble();
|
||||
}
|
||||
|
||||
camera.setOffset(settings.offset);
|
||||
@ -318,14 +323,17 @@ void ext::Player::tick() {
|
||||
if ( ext::openvr::context ) {
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "dpadUp" )["state"].asBool() ) keys.forward = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "dpadDown" )["state"].asBool() ) keys.backwards = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "dpadLeft" )["state"].asBool() ) keys.lookLeft = true; //keys.left = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "dpadRight" )["state"].asBool() ) keys.lookRight = true; //keys.right = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "dpadLeft" )["state"].asBool() ) keys.left = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "dpadRight" )["state"].asBool() ) keys.right = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "thumbclick" )["state"].asBool() ) keys.running = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Right, "a" )["state"].asBool() ) keys.jump = true;
|
||||
|
||||
// if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "dpadUp" )["state"].asBool() ) keys.forward = true;
|
||||
// if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "dpadDown" )["state"].asBool() ) keys.backwards = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "dpadUp" )["state"].asBool() ) keys.forward = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "dpadDown" )["state"].asBool() ) keys.backwards = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "dpadLeft" )["state"].asBool() ) keys.lookLeft = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "dpadRight" )["state"].asBool() ) keys.lookRight = true;
|
||||
// std::cout << ext::openvr::controllerState( vr::Controller_Hand::Hand_Right ) << std::endl;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "thumbclick" )["state"].asBool() ) keys.crouch = true, keys.walk = true;
|
||||
if ( ext::openvr::controllerState( vr::Controller_Hand::Hand_Left, "a" )["state"].asBool() ) keys.paused = true;
|
||||
}
|
||||
|
||||
struct {
|
||||
@ -339,22 +347,32 @@ void ext::Player::tick() {
|
||||
stats.menu = metadata["system"]["menu"].asString();
|
||||
|
||||
struct {
|
||||
float move = 4; //uf::physics::time::delta * 4;
|
||||
float rotate = uf::physics::time::delta * 1.25f;
|
||||
float move = 4;
|
||||
float walk = 1;
|
||||
float run = 8;
|
||||
float rotate = uf::physics::time::delta;
|
||||
float limitSquared = 4*4;
|
||||
} speed;
|
||||
} speed; {
|
||||
speed.rotate *= metadata["system"]["physics"]["rotate"].asFloat();
|
||||
speed.move = metadata["system"]["physics"]["move"].asFloat();
|
||||
speed.run = metadata["system"]["physics"]["run"].asFloat() / metadata["system"]["physics"]["move"].asFloat();
|
||||
speed.walk = metadata["system"]["physics"]["walk"].asFloat() / metadata["system"]["physics"]["move"].asFloat();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uf::Timer<long long> timer(false);
|
||||
if ( !timer.running() ) timer.start();
|
||||
if ( keys.vee ) {
|
||||
if ( timer.elapsed().asDouble() >= 0.25 ) {
|
||||
timer.reset();
|
||||
metadata["collision"]["should"] = !metadata["collision"]["should"].asBool();
|
||||
metadata["system"]["physics"]["collision"] = !metadata["system"]["physics"]["collision"].asBool();
|
||||
|
||||
physics.linear.velocity = {0,0,0};
|
||||
}
|
||||
}
|
||||
if ( keys.running ) speed.move *= 2;
|
||||
else if ( keys.walk ) speed.move /= 4;
|
||||
if ( keys.running ) speed.move *= speed.run;
|
||||
else if ( keys.walk ) speed.move *= speed.walk;
|
||||
speed.limitSquared = speed.move * speed.move;
|
||||
|
||||
uf::Object* menu = (uf::Object*) this->getRootParent().findByName("Gui: Menu");
|
||||
@ -382,7 +400,7 @@ void ext::Player::tick() {
|
||||
// translator.orientation = uf::quaternion::multiply( transform.orientation * pod::Vector4f{1,1,1,-1}, ext::openvr::hmdQuaternion() * pod::Vector4f{1,1,1,-1} );
|
||||
// translator.orientation = uf::quaternion::multiply( ext::openvr::hmdQuaternion(), transform.orientation );
|
||||
//translator.orientation = ext::openvr::hmdQuaternion();
|
||||
bool useController = true;
|
||||
bool useController = false;
|
||||
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 = uf::transform::reorient( translator );
|
||||
{
|
||||
@ -437,15 +455,15 @@ void ext::Player::tick() {
|
||||
physics.linear.velocity.z = correction.z;
|
||||
stats.updateCamera = (stats.walking = true);
|
||||
}
|
||||
if ( keys.jump && metadata["collision"]["jump"] != Json::nullValue ) {
|
||||
if ( !metadata["collision"]["should"].asBool() ) {
|
||||
if ( metadata["collision"]["jump"][0].asFloat() != 0 ) transform.position.x += metadata["collision"]["jump"][0].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["collision"]["jump"][1].asFloat() != 0 ) transform.position.y += metadata["collision"]["jump"][1].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["collision"]["jump"][2].asFloat() != 0 ) transform.position.z += metadata["collision"]["jump"][2].asFloat() * uf::physics::time::delta;
|
||||
if ( keys.jump ) {
|
||||
if ( !metadata["system"]["physics"]["collision"].asBool() ) {
|
||||
if ( metadata["system"]["physics"]["jump"][0].asFloat() != 0 ) transform.position.x += metadata["system"]["physics"]["jump"][0].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["system"]["physics"]["jump"][1].asFloat() != 0 ) transform.position.y += metadata["system"]["physics"]["jump"][1].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["system"]["physics"]["jump"][2].asFloat() != 0 ) transform.position.z += metadata["system"]["physics"]["jump"][2].asFloat() * uf::physics::time::delta;
|
||||
} else {
|
||||
if ( metadata["collision"]["jump"][0].asFloat() != 0 ) physics.linear.velocity.x = metadata["collision"]["jump"][0].asFloat();
|
||||
if ( metadata["collision"]["jump"][1].asFloat() != 0 ) physics.linear.velocity.y = metadata["collision"]["jump"][1].asFloat();
|
||||
if ( metadata["collision"]["jump"][2].asFloat() != 0 ) physics.linear.velocity.z = metadata["collision"]["jump"][2].asFloat();
|
||||
if ( metadata["system"]["physics"]["jump"][0].asFloat() != 0 ) physics.linear.velocity.x = metadata["system"]["physics"]["jump"][0].asFloat();
|
||||
if ( metadata["system"]["physics"]["jump"][1].asFloat() != 0 ) physics.linear.velocity.y = metadata["system"]["physics"]["jump"][1].asFloat();
|
||||
if ( metadata["system"]["physics"]["jump"][2].asFloat() != 0 ) physics.linear.velocity.z = metadata["system"]["physics"]["jump"][2].asFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -458,10 +476,10 @@ void ext::Player::tick() {
|
||||
}
|
||||
|
||||
if ( keys.crouch ) {
|
||||
if ( !metadata["collision"]["should"].asBool() ) {
|
||||
if ( metadata["collision"]["jump"][0].asFloat() != 0 ) transform.position.x -= metadata["collision"]["jump"][0].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["collision"]["jump"][1].asFloat() != 0 ) transform.position.y -= metadata["collision"]["jump"][1].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["collision"]["jump"][2].asFloat() != 0 ) transform.position.z -= metadata["collision"]["jump"][2].asFloat() * uf::physics::time::delta;
|
||||
if ( !metadata["system"]["physics"]["collision"].asBool() ) {
|
||||
if ( metadata["system"]["physics"]["jump"][0].asFloat() != 0 ) transform.position.x -= metadata["system"]["physics"]["jump"][0].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["system"]["physics"]["jump"][1].asFloat() != 0 ) transform.position.y -= metadata["system"]["physics"]["jump"][1].asFloat() * uf::physics::time::delta;
|
||||
if ( metadata["system"]["physics"]["jump"][2].asFloat() != 0 ) transform.position.z -= metadata["system"]["physics"]["jump"][2].asFloat() * uf::physics::time::delta;
|
||||
} else {
|
||||
if ( !metadata["system"]["crouching"].asBool() ) stats.deltaCrouch = true;
|
||||
metadata["system"]["crouching"] = true;
|
||||
@ -472,7 +490,7 @@ void ext::Player::tick() {
|
||||
}
|
||||
}
|
||||
if ( stats.deltaCrouch ) {
|
||||
float delta = 1.0f;
|
||||
float delta = metadata["system"]["physics"]["crouch"].asFloat();
|
||||
if ( metadata["system"]["crouching"].asBool() ) camera.getTransform().position.y -= delta;
|
||||
else camera.getTransform().position.y += delta;
|
||||
stats.updateCamera = true;
|
||||
@ -495,7 +513,7 @@ void ext::Player::tick() {
|
||||
footstep.setVolume(0.1f);
|
||||
footstep.setPosition( transform.position );
|
||||
}
|
||||
} else {
|
||||
} else if ( !keys.jump ) {
|
||||
physics.linear.velocity.x = 0;
|
||||
physics.linear.velocity.y = 0;
|
||||
physics.linear.velocity.z = 0;
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "..//sprite.h"
|
||||
#include <uf/engine/asset/asset.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
#include <uf/utils/math/collision.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
@ -54,7 +55,8 @@ void ext::Region::initialize() {
|
||||
graphic.process = false;
|
||||
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.sampler.filter = VK_FILTER_NEAREST;
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
texture.loadFromFile( textureFilename );
|
||||
|
||||
std::string suffix = ""; {
|
||||
@ -83,9 +85,9 @@ void ext::Region::initialize() {
|
||||
generator.generate(*this);
|
||||
generator.updateLight();
|
||||
|
||||
/* Collider */ {
|
||||
/* Collider */ if ( false ) {
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
uf::Collider& collider = this->getComponent<uf::Collider>();
|
||||
|
||||
std::size_t i = 0;
|
||||
const auto& voxels = generator.getVoxels();
|
||||
@ -108,8 +110,7 @@ void ext::Region::initialize() {
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
uf::Collider* box = new uf::AABBox( offset, {0.5, 0.5, 0.5} );
|
||||
collider.add(box);
|
||||
collider.add(new uf::BoundingBox( offset, {0.5, 0.5, 0.5} ));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,12 +201,16 @@ void ext::Region::initialize() {
|
||||
}
|
||||
if ( should ) {
|
||||
uf::Entity* light = this->findByUid(this->loadChild("./light.json", true));
|
||||
uf::Serializer& metadata = light->getComponent<uf::Serializer>();
|
||||
pod::Transform<>& lTransform = light->getComponent<pod::Transform<>>();
|
||||
lTransform.position = transform.position;
|
||||
metadata["light"]["color"][0] = r;
|
||||
metadata["light"]["color"][1] = r;
|
||||
metadata["light"]["color"][2] = r;
|
||||
if ( light ) {
|
||||
uf::Serializer& metadata = light->getComponent<uf::Serializer>();
|
||||
pod::Transform<>& lTransform = light->getComponent<pod::Transform<>>();
|
||||
lTransform.position += transform.position;
|
||||
if ( !metadata["light"].isArray() ) {
|
||||
metadata["light"]["color"][0] = (rand() % 100) / 100.0;
|
||||
metadata["light"]["color"][1] = (rand() % 100) / 100.0;
|
||||
metadata["light"]["color"][2] = (rand() % 100) / 100.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// add mobs
|
||||
@ -273,6 +278,139 @@ void ext::Region::initialize() {
|
||||
}
|
||||
void ext::Region::tick() {
|
||||
uf::Object::tick();
|
||||
|
||||
// do collision on children
|
||||
#if 1
|
||||
{
|
||||
bool local = false;
|
||||
bool sort = false;
|
||||
bool useStrongest = true;
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
auto function = [&]() -> int {
|
||||
std::vector<uf::Object*> entities;
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
auto& metadata = entity->getComponent<uf::Serializer>();
|
||||
if ( !metadata["system"]["physics"]["collision"].isNull() && !metadata["system"]["physics"]["collision"].asBool() ) return;
|
||||
if ( entity->hasComponent<uf::Collider>() )
|
||||
entities.push_back((uf::Object*) entity);
|
||||
};
|
||||
this->process(filter);
|
||||
auto onCollision = []( pod::Collider::Manifold& manifold, uf::Object* a, uf::Object* b ){
|
||||
uf::Serializer payload;
|
||||
payload["normal"][0] = manifold.normal.x;
|
||||
payload["normal"][1] = manifold.normal.y;
|
||||
payload["normal"][2] = manifold.normal.z;
|
||||
payload["entity"] = b->getUid();
|
||||
payload["depth"] = -manifold.depth;
|
||||
a->callHook("world:Collision.%UID%", payload);
|
||||
|
||||
payload["entity"] = a->getUid();
|
||||
payload["depth"] = manifold.depth;
|
||||
b->callHook("world:Collision.%UID%", payload);
|
||||
/*
|
||||
pod::Transform<>& transform = b->getComponent<pod::Transform<>>();
|
||||
pod::Physics& physics = b->getComponent<pod::Physics>();
|
||||
|
||||
uf::Serializer payload;
|
||||
pod::Vector3 correction = uf::vector::normalize(manifold.normal) * manifold.depth;
|
||||
transform.position -= correction;
|
||||
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
*/
|
||||
};
|
||||
auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, uf::Object* a, uf::Object* b, bool useStrongest ){
|
||||
pod::Collider::Manifold strongest;
|
||||
auto manifolds = colliderA.intersects(colliderB);
|
||||
for ( auto manifold : manifolds ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( !useStrongest ) onCollision(manifold, a, b);
|
||||
else if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) onCollision(strongest, a, b);
|
||||
};
|
||||
|
||||
// collide with world
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
auto& generator = this->getComponent<ext::TerrainGenerator>();
|
||||
auto& regionPosition = this->getComponent<pod::Transform<>>().position;
|
||||
pod::Vector3f size; {
|
||||
size.x = metadata["region"]["size"][0].asUInt();
|
||||
size.y = metadata["region"]["size"][1].asUInt();
|
||||
size.z = metadata["region"]["size"][2].asUInt();
|
||||
}
|
||||
for ( auto* _ : entities ) {
|
||||
uf::Object& entity = *_;
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
|
||||
|
||||
pod::Vector3f voxelPosition = transform.position - regionPosition;
|
||||
voxelPosition.x += size.x / 2.0f;
|
||||
voxelPosition.y += size.y / 2.0f + 1;
|
||||
voxelPosition.z += size.z / 2.0f;
|
||||
|
||||
uf::Collider collider;
|
||||
std::vector<pod::Vector3ui> positions = {
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x - 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x + 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y - 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y + 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z - 1 },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z + 1},
|
||||
};
|
||||
for ( auto& position : positions ) {
|
||||
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( generator.getVoxel( position.x, position.y, position.z ) );
|
||||
pod::Vector3 offset = regionPosition;
|
||||
offset.x += position.x - (size.x / 2.0f);
|
||||
offset.y += position.y - (size.y / 2.0f);
|
||||
offset.z += position.z - (size.z / 2.0f);
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
collider.add( new uf::BoundingBox( offset, {0.5, 0.5, 0.5} ) );
|
||||
/*
|
||||
uf::BaseMesh<pod::Vertex_3F> mesh;
|
||||
const ext::TerrainVoxel::Model& model = voxel.model();
|
||||
#define TERRAIN_SHOULD_RENDER_FACE(SIDE)\
|
||||
for ( uint i = 0; i < model.position.SIDE.size() / 3; ++i ) {\
|
||||
auto& vertex = mesh.vertices.emplace_back();\
|
||||
{\
|
||||
pod::Vector3f& p = vertex.position;\
|
||||
p.x = model.position.SIDE[i*3+0]; p.y = model.position.SIDE[i*3+1]; p.z = model.position.SIDE[i*3+2];\
|
||||
p.x += offset.x; p.y += offset.y; p.z += offset.z;\
|
||||
}\
|
||||
}
|
||||
TERRAIN_SHOULD_RENDER_FACE(left)
|
||||
TERRAIN_SHOULD_RENDER_FACE(right)
|
||||
TERRAIN_SHOULD_RENDER_FACE(top)
|
||||
TERRAIN_SHOULD_RENDER_FACE(bottom)
|
||||
TERRAIN_SHOULD_RENDER_FACE(back)
|
||||
TERRAIN_SHOULD_RENDER_FACE(front)
|
||||
uf::MeshCollider* mCollider = new uf::MeshCollider();
|
||||
mCollider->setPositions( mesh );
|
||||
pCollider.add(mCollider);
|
||||
*/
|
||||
}
|
||||
testColliders( collider, entity.getComponent<uf::Collider>(), this, &entity, useStrongest );
|
||||
}
|
||||
|
||||
// collide with others
|
||||
for ( auto* _a : entities ) {
|
||||
uf::Object& entityA = *_a;
|
||||
for ( auto* _b : entities ) { if ( _a == _b ) continue;
|
||||
uf::Object& entityB = *_b;
|
||||
testColliders( entityA.getComponent<uf::Collider>(), entityB.getComponent<uf::Collider>(), &entityA, &entityB, useStrongest );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void ext::Region::destroy() {
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
@ -289,11 +427,11 @@ void ext::Region::render( ) {
|
||||
uf::Object::render();
|
||||
|
||||
if ( !metadata["region"]["rasterized"].asBool() ) return;
|
||||
/* Update uniforms */ if ( this->hasComponent<ext::TerrainGenerator::mesh_t>() ) {
|
||||
auto& world = this->getRootParent<uf::Scene>();
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& scene = this->getRootParent<uf::Scene>();
|
||||
auto& mesh = this->getComponent<ext::TerrainGenerator::mesh_t>();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& camera = world.getController()->getComponent<uf::Camera>();
|
||||
auto& camera = scene.getController()->getComponent<uf::Camera>();
|
||||
if ( !graphic.initialized ) return;
|
||||
// auto& uniforms = graphic.uniforms<uf::StereoMeshDescriptor>();
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "terrain.h"
|
||||
#include "generator.h"
|
||||
|
||||
#include "../../../ext.h"
|
||||
#include <uf/engine/asset/asset.h>
|
||||
@ -10,6 +11,7 @@
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/utils/math/collision.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
#include <uf/ext/vulkan/graphic.h>
|
||||
#include <uf/ext/vulkan/vulkan.h>
|
||||
@ -145,7 +147,150 @@ void ext::Terrain::tick() {
|
||||
|
||||
// multipurpose timer
|
||||
static uf::Timer<long long> timer(false);
|
||||
// do collision on children
|
||||
#if 0
|
||||
{
|
||||
bool local = false;
|
||||
bool sort = false;
|
||||
bool useStrongest = false;
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
auto function = [&]() -> int {
|
||||
std::vector<uf::Object*> entities;
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
auto& metadata = entity->getComponent<uf::Serializer>();
|
||||
if ( !metadata["system"]["physics"]["collision"].isNull() && !metadata["system"]["physics"]["collision"].asBool() ) return;
|
||||
if ( entity->hasComponent<uf::Collider>() )
|
||||
entities.push_back((uf::Object*) entity);
|
||||
};
|
||||
this->process(filter);
|
||||
auto onCollision = []( pod::Collider::Manifold& manifold, uf::Object* a, uf::Object* b ){
|
||||
uf::Serializer payload;
|
||||
payload["normal"][0] = manifold.normal.x;
|
||||
payload["normal"][1] = manifold.normal.y;
|
||||
payload["normal"][2] = manifold.normal.z;
|
||||
payload["entity"] = b->getUid();
|
||||
payload["depth"] = -manifold.depth;
|
||||
a->callHook("world:Collision.%UID%", payload);
|
||||
|
||||
payload["entity"] = a->getUid();
|
||||
payload["depth"] = manifold.depth;
|
||||
b->callHook("world:Collision.%UID%", payload);
|
||||
};
|
||||
auto testColliders = [&]( uf::Collider& colliderA, uf::Collider& colliderB, uf::Object* a, uf::Object* b, bool useStrongest ){
|
||||
pod::Collider::Manifold strongest;
|
||||
auto manifolds = colliderA.intersects(colliderB);
|
||||
for ( auto manifold : manifolds ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( !useStrongest ) onCollision(manifold, a, b);
|
||||
else if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) onCollision(strongest, a, b);
|
||||
};
|
||||
|
||||
// collide with world
|
||||
for ( auto* _ : entities ) {
|
||||
uf::Object& entity = *_;
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
|
||||
pod::Vector3f size; {
|
||||
size.x = metadata["region"]["size"][0].asUInt();
|
||||
size.y = metadata["region"]["size"][1].asUInt();
|
||||
size.z = metadata["region"]["size"][2].asUInt();
|
||||
}
|
||||
uf::Entity* regionPointer = _;
|
||||
while ( regionPointer->getName() != "Region" ) {
|
||||
regionPointer = ®ionPointer->getParent();
|
||||
if ( regionPointer->getUid() == 0 ) break;
|
||||
if ( regionPointer->getUid() == this->getUid() ) break;
|
||||
}
|
||||
if ( regionPointer == this ) continue;
|
||||
if ( regionPointer->getUid() == 0 ) continue;
|
||||
if ( regionPointer->getName() != "Region" ) continue;
|
||||
if ( !regionPointer ) continue;
|
||||
ext::Region& region = *(ext::Region*) regionPointer;
|
||||
/*
|
||||
pod::Vector3f pointf = transform.position / size;
|
||||
pod::Vector3i point = {
|
||||
(int) (pointf.x + (pointf.x > 0 ? 0.5 : -0.5)),
|
||||
(int) (pointf.y + (pointf.y > 0 ? 0.5 : -0.5)),
|
||||
(int) (pointf.z + (pointf.z > 0 ? 0.5 : -0.5)),
|
||||
};
|
||||
// std::cout << entity.getName() << ": " << entity.getUid() << ": " << point.x << ", " << point.y << ", " << point.z << std::endl;
|
||||
if ( !this->exists(point) ) continue;
|
||||
ext::Region* regionPointer = this->at(point);
|
||||
if ( !regionPointer ) continue;
|
||||
ext::Region& region = *regionPointer;
|
||||
*/
|
||||
|
||||
auto& generator = region.getComponent<ext::TerrainGenerator>();
|
||||
|
||||
auto& regionPosition = region.getComponent<pod::Transform<>>().position;
|
||||
pod::Vector3f voxelPosition = transform.position - regionPosition;
|
||||
voxelPosition.x += size.x / 2.0f;
|
||||
voxelPosition.y += size.y / 2.0f + 1;
|
||||
voxelPosition.z += size.z / 2.0f;
|
||||
|
||||
uf::Collider collider;
|
||||
std::vector<pod::Vector3ui> positions = {
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x - 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x + 1, voxelPosition.y, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y - 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y + 1, voxelPosition.z },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z - 1 },
|
||||
{ voxelPosition.x, voxelPosition.y, voxelPosition.z + 1},
|
||||
};
|
||||
for ( auto& position : positions ) {
|
||||
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas( generator.getVoxel( position.x, position.y, position.z ) );
|
||||
pod::Vector3 offset = regionPosition;
|
||||
offset.x += position.x - (size.x / 2.0f);
|
||||
offset.y += position.y - (size.y / 2.0f);
|
||||
offset.z += position.z - (size.z / 2.0f);
|
||||
|
||||
if ( !voxel.solid() ) continue;
|
||||
|
||||
collider.add( new uf::BoundingBox( offset, {0.5, 0.5, 0.5} ) );
|
||||
/*
|
||||
uf::BaseMesh<pod::Vertex_3F> mesh;
|
||||
const ext::TerrainVoxel::Model& model = voxel.model();
|
||||
#define TERRAIN_SHOULD_RENDER_FACE(SIDE)\
|
||||
for ( uint i = 0; i < model.position.SIDE.size() / 3; ++i ) {\
|
||||
auto& vertex = mesh.vertices.emplace_back();\
|
||||
{\
|
||||
pod::Vector3f& p = vertex.position;\
|
||||
p.x = model.position.SIDE[i*3+0]; p.y = model.position.SIDE[i*3+1]; p.z = model.position.SIDE[i*3+2];\
|
||||
p.x += offset.x; p.y += offset.y; p.z += offset.z;\
|
||||
}\
|
||||
}
|
||||
TERRAIN_SHOULD_RENDER_FACE(left)
|
||||
TERRAIN_SHOULD_RENDER_FACE(right)
|
||||
TERRAIN_SHOULD_RENDER_FACE(top)
|
||||
TERRAIN_SHOULD_RENDER_FACE(bottom)
|
||||
TERRAIN_SHOULD_RENDER_FACE(back)
|
||||
TERRAIN_SHOULD_RENDER_FACE(front)
|
||||
uf::MeshCollider* mCollider = new uf::MeshCollider();
|
||||
mCollider->setPositions( mesh );
|
||||
pCollider.add(mCollider);
|
||||
*/
|
||||
}
|
||||
testColliders( collider, entity.getComponent<uf::Collider>(), ®ion, &entity, useStrongest );
|
||||
}
|
||||
|
||||
// collide with others
|
||||
for ( auto* _a : entities ) {
|
||||
uf::Object& entityA = *_a;
|
||||
for ( auto* _b : entities ) { if ( _a == _b ) continue;
|
||||
uf::Object& entityB = *_b;
|
||||
testColliders( entityA.getComponent<uf::Collider>(), entityB.getComponent<uf::Collider>(), &entityA, &entityB, useStrongest );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
if ( local ) function(); else uf::thread::add( thread, function, true );
|
||||
}
|
||||
#endif
|
||||
// open gamestate, look for work
|
||||
if ( metadata["system"]["state"] == "open" ) { transitionResolvingState(*this);
|
||||
// cleanup orphans
|
||||
|
||||
@ -293,12 +293,8 @@ void ext::World::tick() {
|
||||
ext::oal.listener( "VELOCITY", { 0, 0, 0 } );
|
||||
ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } );
|
||||
}
|
||||
}
|
||||
|
||||
void ext::World::render() {
|
||||
uf::Scene::render();
|
||||
|
||||
/* Update lights */ {
|
||||
/**/ if ( false ) {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
auto& scene = *this;
|
||||
std::vector<ext::vulkan::Graphic*> blitters;
|
||||
@ -311,128 +307,14 @@ void ext::World::render() {
|
||||
auto* renderModePointer = (ext::vulkan::DeferredRenderMode*) &renderMode;
|
||||
blitters.push_back(&renderModePointer->blitter);
|
||||
}
|
||||
auto& controller = *scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
// auto& uniforms = blitter.uniforms;
|
||||
struct UniformDescriptor {
|
||||
struct Matrices {
|
||||
alignas(16) pod::Matrix4f view[2];
|
||||
alignas(16) pod::Matrix4f projection[2];
|
||||
} matrices;
|
||||
alignas(16) pod::Vector4f ambient;
|
||||
struct Light {
|
||||
alignas(16) pod::Vector4f position;
|
||||
alignas(16) pod::Vector4f color;
|
||||
} lights;
|
||||
};
|
||||
|
||||
struct SpecializationConstant {
|
||||
int32_t maxLights = 32;
|
||||
} specializationConstants;
|
||||
|
||||
for ( size_t _ = 0; _ < blitters.size(); ++_ ) {
|
||||
auto& blitter = *blitters[_];
|
||||
|
||||
uint8_t* buffer;
|
||||
size_t len;
|
||||
auto* shader = &blitter.material.shaders.front();
|
||||
|
||||
for ( auto& _ : blitter.material.shaders ) {
|
||||
if ( _.uniforms.empty() ) continue;
|
||||
auto& userdata = _.uniforms.front();
|
||||
buffer = (uint8_t*) (void*) userdata;
|
||||
len = userdata.data().len;
|
||||
shader = &_;
|
||||
specializationConstants = _.specializationConstants.get<SpecializationConstant>();
|
||||
}
|
||||
|
||||
if ( !buffer ) continue;
|
||||
|
||||
UniformDescriptor* uniforms = (UniformDescriptor*) buffer;
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
uniforms->matrices.view[i] = camera.getView( i );
|
||||
uniforms->matrices.projection[i] = camera.getProjection( i );
|
||||
}
|
||||
{
|
||||
uniforms->ambient.x = metadata["light"]["ambient"][0].asFloat();
|
||||
uniforms->ambient.y = metadata["light"]["ambient"][1].asFloat();
|
||||
uniforms->ambient.z = metadata["light"]["ambient"][2].asFloat();
|
||||
uniforms->ambient.w = metadata["light"]["kexp"].asFloat();
|
||||
}
|
||||
{
|
||||
std::vector<uf::Entity*> entities;
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
if ( !entity || entity->getName() != "Light" ) return;
|
||||
entities.push_back(entity);
|
||||
};
|
||||
for ( uf::Scene* scene : ext::vulkan::scenes ) { if ( !scene ) continue;
|
||||
scene->process(filter);
|
||||
}
|
||||
{
|
||||
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
|
||||
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
|
||||
if ( !l ) return false; if ( !r ) return true;
|
||||
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
|
||||
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
|
||||
} );
|
||||
}
|
||||
|
||||
{
|
||||
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
|
||||
if ( metadata["light"]["should"].asBool() ) {
|
||||
entities.push_back(&controller);
|
||||
}
|
||||
}
|
||||
UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)];
|
||||
for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) {
|
||||
UniformDescriptor::Light& light = lights[i];
|
||||
light.position = { 0, 0, 0, 0 };
|
||||
light.color = { 0, 0, 0, 0 };
|
||||
}
|
||||
for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) {
|
||||
UniformDescriptor::Light& light = lights[i];
|
||||
uf::Entity* entity = entities[i];
|
||||
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();
|
||||
uf::Serializer& metadata = entity->getComponent<uf::Serializer>();
|
||||
|
||||
light.position.x = transform.position.x;
|
||||
light.position.y = transform.position.y;
|
||||
light.position.z = transform.position.z;
|
||||
|
||||
if ( entity == &controller ) {
|
||||
light.position.y += 2;
|
||||
}
|
||||
|
||||
light.position.w = metadata["light"]["power"].asFloat();
|
||||
|
||||
light.color.x = metadata["light"]["color"][0].asFloat();
|
||||
light.color.y = metadata["light"]["color"][1].asFloat();
|
||||
light.color.z = metadata["light"]["color"][2].asFloat();
|
||||
|
||||
light.color.w = metadata["light"]["radius"].asFloat();
|
||||
}
|
||||
}
|
||||
// blitter.updateBuffer( (void*) buffer, blitter.uniforms.data().len, 0, false );
|
||||
shader->updateBuffer( (void*) buffer, len, 0, false );
|
||||
blitter.getPipeline().update( blitter );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uf::Entity* ext::World::getController() {
|
||||
if ( ext::vulkan::currentRenderMode ) {
|
||||
auto& renderMode = *ext::vulkan::currentRenderMode;
|
||||
std::string name = renderMode.name;
|
||||
auto split = uf::string::split( name, ": " );
|
||||
if ( split.front() == "Render Target" ) {
|
||||
uint64_t uid = std::stoi( split.back() );
|
||||
uf::Entity* ent = this->findByUid( uid );
|
||||
if ( ent ) return ent;
|
||||
}
|
||||
}
|
||||
return uf::Scene::getController();
|
||||
}
|
||||
|
||||
const uf::Entity* ext::World::getController() const {
|
||||
return uf::Scene::getController();
|
||||
void ext::World::render() {
|
||||
uf::Scene::render();
|
||||
}
|
||||
@ -12,8 +12,5 @@ namespace ext {
|
||||
virtual void initialize();
|
||||
virtual void tick();
|
||||
virtual void render();
|
||||
|
||||
virtual uf::Entity* getController();
|
||||
virtual const uf::Entity* getController() const;
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user