From a97418d88ed7567b117885b4c92906fe4e9f921d Mon Sep 17 00:00:00 2001 From: mrq Date: Sun, 27 Sep 2020 00:00:00 -0500 Subject: [PATCH] Commit for 2020.09.27.7z --- bin/data/shaders/display.subpass.frag.glsl | 135 ++++--- bin/data/shaders/raytracing.comp.glsl | 57 ++- engine/inc/uf/engine/behavior/behavior.h | 70 ++++ engine/inc/uf/engine/entity/entity.h | 45 ++- engine/inc/uf/engine/entity/entity.inl | 5 +- engine/inc/uf/engine/scene/scene.h | 8 +- engine/inc/uf/ext/vulkan/device.h | 10 +- engine/inc/uf/utils/math/math.h | 12 +- engine/inc/uf/utils/mempool/mempool.h | 2 + engine/inc/uf/utils/userdata/userdata.inl | 81 ---- engine/src/engine/behavior/behavior.cpp | 27 ++ engine/src/engine/entity/entity.cpp | 126 +++--- engine/src/engine/object/object.cpp | 59 ++- engine/src/engine/scene/scene.cpp | 233 +---------- engine/src/ext/openvr/openvr.cpp | 25 +- engine/src/ext/vulkan/device.cpp | 136 ++++--- engine/src/ext/vulkan/graphic.cpp | 34 +- .../rendermodes/stereoscopic_deferred.cpp | 44 +- engine/src/ext/vulkan/vulkan.cpp | 7 +- engine/src/utils/camera/camera.cpp | 2 +- engine/src/utils/mempool/mempool.cpp | 77 +++- ext/gui/gui.cpp | 13 +- ext/main.cpp | 4 +- ext/scenes/base.cpp | 377 ++++++++++++++++++ ext/scenes/base.h | 16 + ext/scenes/map/behavior_test.cpp | 35 ++ ext/scenes/map/behavior_test.h | 15 + ext/scenes/map/scene.cpp | 92 +---- ext/scenes/map/scene.h | 7 +- ext/scenes/marchingcubes/scene.cpp | 93 +---- ext/scenes/marchingcubes/scene.h | 7 +- .../marchingcubes/terrain/heightmap.cpp | 8 +- ext/scenes/marchingcubes/terrain/marching.cpp | 6 +- ext/scenes/raytrace/scene.cpp | 127 ++---- ext/scenes/raytrace/scene.h | 7 +- ext/scenes/start/menu.cpp | 148 +------ ext/scenes/start/menu.h | 13 +- ext/scenes/worldscape/craeture/craeture.cpp | 4 +- ext/scenes/worldscape/gui/pause.cpp | 2 +- ext/scenes/worldscape/housamo/sprite.cpp | 6 +- ext/scenes/worldscape/light/light.cpp | 117 +++++- ext/scenes/worldscape/player/hands.cpp | 4 +- ext/scenes/worldscape/portal/portal.cpp | 6 +- ext/scenes/worldscape/scene.cpp | 182 +-------- ext/scenes/worldscape/scene.h | 8 +- ext/scenes/worldscape/terrain/region.cpp | 4 +- ext/scenes/worldscape/terrain/terrain.cpp | 14 +- 47 files changed, 1251 insertions(+), 1259 deletions(-) create mode 100644 engine/inc/uf/engine/behavior/behavior.h create mode 100644 engine/src/engine/behavior/behavior.cpp create mode 100644 ext/scenes/base.cpp create mode 100644 ext/scenes/base.h create mode 100644 ext/scenes/map/behavior_test.cpp create mode 100644 ext/scenes/map/behavior_test.h diff --git a/bin/data/shaders/display.subpass.frag.glsl b/bin/data/shaders/display.subpass.frag.glsl index 716f099c..39815dad 100644 --- a/bin/data/shaders/display.subpass.frag.glsl +++ b/bin/data/shaders/display.subpass.frag.glsl @@ -1,7 +1,6 @@ #version 450 -#define BASE_LIGHTS_SIZE 16 -layout (constant_id = 0) const uint LIGHTS = BASE_LIGHTS_SIZE; +layout (constant_id = 0) const uint LIGHTS = 32; layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedo; layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormal; @@ -14,6 +13,33 @@ layout (location = 1) in flat uint inPushConstantPass; layout (location = 0) out vec4 outFragColor; +/* +const vec2 poissonDisk[4] = vec2[]( + vec2( -0.94201624, -0.39906216 ), + vec2( 0.94558609, -0.76890725 ), + vec2( -0.094184101, -0.92938870 ), + vec2( 0.34495938, 0.29387760 ) +); +*/ + +vec2 poissonDisk[16] = vec2[]( + vec2( -0.94201624, -0.39906216 ), + vec2( 0.94558609, -0.76890725 ), + vec2( -0.094184101, -0.92938870 ), + vec2( 0.34495938, 0.29387760 ), + vec2( -0.91588581, 0.45771432 ), + vec2( -0.81544232, -0.87912464 ), + vec2( -0.38277543, 0.27676845 ), + vec2( 0.97484398, 0.75648379 ), + vec2( 0.44323325, -0.97511554 ), + vec2( 0.53742981, -0.47373420 ), + vec2( -0.26496911, -0.41893023 ), + vec2( 0.79197514, 0.19090188 ), + vec2( -0.24188840, 0.99706507 ), + vec2( -0.81409955, 0.91437590 ), + vec2( 0.19984126, 0.78641367 ), + vec2( 0.14383161, -0.14100790 ) +); struct Light { vec3 position; @@ -36,16 +62,25 @@ struct Space { vec3 world; } position, normal, view; +struct Fog { + vec2 range; + vec4 color; +}; + layout (binding = 0) uniform UBO { Matrices matrices; vec3 ambient; float kexp; + Fog fog; Light lights[LIGHTS]; } ubo; void fog( inout vec3 i ) { - vec3 color = vec3( 0.1, 0.1, 0.1 ); - float inner = 4, outer = 32; + if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return; + + vec3 color = ubo.fog.color.rgb; + float inner = ubo.fog.range.x; + float outer = ubo.fog.range.y; float distance = length(-position.eye); float factor = (distance - inner) / (outer - inner); factor = clamp( factor, 0.0, 1.0 ); @@ -67,7 +102,7 @@ void phong( Light light, vec4 albedoSpecular, inout vec3 i ) { vec3 L = light.position.xyz - position.eye; float dist = length(L); - if ( light.radius < dist ) return; + if ( light.radius > 0.001 && light.radius < dist ) return; vec3 D = normalize(L); float d_dot = max(dot( D, normal.eye ), 0.0); @@ -77,6 +112,7 @@ void phong( Light light, vec4 albedoSpecular, inout vec3 i ) { float s_factor = pow( max(dot( R, S ), 0.0), Kexp ); float attenuation = light.radius / (pow(dist, 2.0) + 1.0); + if ( light.radius <= 0.0001 ) attenuation = 1; vec3 Ia = La * Ka; vec3 Id = Ld * Kd * d_dot * attenuation; @@ -85,53 +121,41 @@ void phong( Light light, vec4 albedoSpecular, inout vec3 i ) { i += Id * light.power; } -bool debugShadow( Light light, uint i ) { -// return false; - - { - outFragColor.rgb = texture(samplerShadows[i], inUv).rgb; - outFragColor.a = 1; - return true; - } - - 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 random(vec3 seed, int i){ + vec4 seed4 = vec4(seed,i); + float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673)); + return fract(sin(dot_product) * 43758.5453); } -float shadowFactor( Light light, uint i ) { +float shadowFactor( Light light, uint shadowMap ) { vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0); positionClip.xyz /= positionClip.w; - float lightDepth = texture(samplerShadows[(i*4)+3], 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; + if ( positionClip.z <= 0 || positionClip.z >= 1 ) return 0.0; + + vec2 uv = positionClip.xy * 0.5 + 0.5; + float bias = 0.00005; + if ( true ) { + float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1); + bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01); + } - return eyeDepth - bias < lightDepth ? 1.0 : 0.0; + float factor = 1.0; + float eyeDepth = positionClip.z; + int samples = poissonDisk.length(); + if ( samples <= 1 ) { + return eyeDepth < texture(samplerShadows[shadowMap], uv).r - bias ? 0.0 : factor; + } + for ( int i = 0; i < samples; ++i ) { + // int index = i; + // int index = int( float(samples) * random(gl_FragCoord.xyy, i) ) % samples; + int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples; + float lightDepth = texture(samplerShadows[shadowMap], uv + poissonDisk[index] / 700.0 ).r; + if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples; + } + return factor; } void main() { @@ -183,7 +207,7 @@ void main() { vec3 fragColor = albedoSpecular.rgb * ubo.ambient.rgb; bool lit = false; - + uint shadowMap = 0; for ( uint i = 0; i < LIGHTS; ++i ) { Light light = ubo.lights[i]; @@ -192,29 +216,12 @@ void main() { light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1)); if ( light.shadowed > 0 ) { - float shadowFactor = shadowFactor( light, i ); + float shadowFactor = shadowFactor( light, shadowMap++ ); if ( shadowFactor <= 0.0001 ) continue; } phong( light, albedoSpecular, fragColor ); } - - if ( !lit ) fragColor = albedoSpecular.rgb; - + // 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; - } -*/ } \ No newline at end of file diff --git a/bin/data/shaders/raytracing.comp.glsl b/bin/data/shaders/raytracing.comp.glsl index 72f02e20..b288af7d 100644 --- a/bin/data/shaders/raytracing.comp.glsl +++ b/bin/data/shaders/raytracing.comp.glsl @@ -6,18 +6,15 @@ layout (constant_id = 0) const uint LIGHTS = 16; layout (constant_id = 1) const uint EYES = 2; layout (binding = 0, rgba8) uniform writeonly image2D resultImage[EYES]; -#define RAY_MARCH false -#define MARCH_STEPS 32 #define EPSILON 0.0001 #define MAXLEN 1000.0 -#define SHADOW 0.5 -#define SHADOWS true -#define RAYBOUNCES 0 -#define REFLECTION_STRENGTH 0.4 -#define REFLECTION_FALLOFF 0.5 layout( push_constant ) uniform PushBlock { - uint pass; + uint marchingSteps; + uint rayBounces; + float shadowFactor; + float reflectionStrength; + float reflectionFalloff; } PushConstant; struct Ray { @@ -45,9 +42,15 @@ struct State { Result result; } state; +struct Fog { + vec2 range; + vec4 color; +}; + layout (binding = 2) uniform UBO { mat4 matrices[2]; vec4 ambient; + Fog fog; Light lights[LIGHTS]; } ubo; @@ -138,7 +141,7 @@ float calcShadow(in vec3 rayO, in vec3 rayD, in int objectID, inout float resT) float tShape = shapeIntersect(rayO, rayD, shape); if ((tShape > EPSILON) && (tShape < resT)) { resT = tShape; - return SHADOW; + return PushConstant.shadowFactor; } } return 1.0; @@ -146,7 +149,7 @@ float calcShadow(in vec3 rayO, in vec3 rayD, in int objectID, inout float resT) // Marching ======================================== int intersectMarch( in vec3 rayO, in vec3 rayD, inout float resT ) { resT = 0; - for (int i = 0; i < MARCH_STEPS; ++i) { + for (int i = 0; i < PushConstant.marchingSteps; ++i) { vec3 position = resT * rayD + rayO; float tNearest = MAXLEN; int objectID = -1; @@ -171,7 +174,7 @@ int intersectMarch( in vec3 rayO, in vec3 rayD, inout float resT ) { float calcShadowMarch( in vec3 rayO, in vec3 rayD, in int objectID, inout float resT ) { float distance = resT; resT = 0; - for (int i = 0; i < MARCH_STEPS; ++i) { + for (int i = 0; i < PushConstant.marchingSteps; ++i) { vec3 position = resT * rayD + rayO; float tNearest = distance; int objectID = -1; @@ -186,7 +189,7 @@ float calcShadowMarch( in vec3 rayO, in vec3 rayD, in int objectID, inout float } } if (tNearest < EPSILON) { - return SHADOW; + return PushConstant.shadowFactor; } if (resT > distance) break; resT += tNearest; @@ -195,16 +198,26 @@ float calcShadowMarch( in vec3 rayO, in vec3 rayD, in int objectID, inout float return 1.0; } -vec3 fog(in float t, in vec3 color) { - vec3 fogColor = vec3(0.1); - return mix(color, fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0)); +void fog(inout vec3 i, in float t ) { +/* + vec3 fogColor = ubo.ambient.rgb; + i = mix(i, fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0)); +*/ + if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return; + + vec3 color = ubo.fog.color.rgb; + float inner = ubo.fog.range.x, outer = ubo.fog.range.y; + float factor = (t - inner) / (outer - inner); + factor = clamp( factor, 0.0, 1.0 ); + + i = mix(i.rgb, color, factor); } Result renderScene(inout vec3 rayO, inout vec3 rayD ) { Result result; result.color = vec3(0.0); result.t = MAXLEN; - result.id = RAY_MARCH ? intersectMarch(rayO, rayD, result.t) : intersect(rayO, rayD, result.t); + result.id = PushConstant.marchingSteps > 0 ? intersectMarch(rayO, rayD, result.t) : intersect(rayO, rayD, result.t); if (result.id == -1) return result; Shape shape = shapes[result.id]; @@ -232,13 +245,13 @@ Result renderScene(inout vec3 rayO, inout vec3 rayD ) { // Shadows float tShadow = dist; float shadowed = 1; - if ( SHADOWS ) - shadowed = RAY_MARCH ? calcShadowMarch(position, D, result.id, tShadow) : calcShadow(position, D, result.id, tShadow); + if ( PushConstant.shadowFactor < 1.0 ) + shadowed = PushConstant.marchingSteps > 0 ? calcShadowMarch(position, D, result.id, tShadow) : calcShadow(position, D, result.id, tShadow); result.color += color * light.power * attenuation * shadowed; } // Fog - // result.color = fog(t, result.color); + // fog(t, result.color); // Reflect ray for next render pass reflectRay(rayD, normal); @@ -266,13 +279,13 @@ void main() { vec3 finalColor = state.result.color; // Reflection - float reflectionStrength = REFLECTION_STRENGTH; - for (int i = 0; i < RAYBOUNCES; i++) { + float reflectionStrength = PushConstant.reflectionStrength; + for (int i = 0; i < PushConstant.rayBounces; i++) { Result result = renderScene(state.ray.origin, state.ray.direction); vec3 reflectionColor = result.color; finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * mix(reflectionColor, finalColor, 1.0 - reflectionStrength); - reflectionStrength *= REFLECTION_FALLOFF; + reflectionStrength *= PushConstant.reflectionFalloff; } imageStore(resultImage[pass], ivec2(gl_GlobalInvocationID.xy), vec4(finalColor, 1.0)); diff --git a/engine/inc/uf/engine/behavior/behavior.h b/engine/inc/uf/engine/behavior/behavior.h new file mode 100644 index 00000000..691bcf2b --- /dev/null +++ b/engine/inc/uf/engine/behavior/behavior.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include +#include +#include + + +namespace pod { + struct UF_API Behavior { + typedef std::type_index type_t; + typedef std::function function_t; + + type_t type; + function_t initialize; + function_t tick; + function_t render; + function_t destroy; + }; +} + +namespace uf { + class UF_API Behaviors : public uf::Component { + protected: + typedef std::vector container_t; + container_t m_behaviors; + public: + void initialize(); + void tick(); + void render(); + void destroy(); + + void addBehavior( const pod::Behavior& ); + + template + static pod::Behavior::type_t getType() { + return std::type_index(typeid(T)); + } + template + void addBehavior() { + this->addBehavior(pod::Behavior{ + .type = getType(), + .initialize = T::initialize, + .tick = T::tick, + .render = T::render, + .destroy = T::destroy, + }); + } + template + void removeBehavior() { + auto it = this->m_behaviors.begin(); + while ( it != this->m_behaviors.end() ) { + if ( (it++)->type == getType() ) break; + } + if ( it != this->m_behaviors.end() ) + this->m_behaviors.erase(it); + } + }; + +} + +#define UF_BEHAVIOR_ENTITY_HEADER( OBJ )\ + class UF_API OBJ ## Behavior {\ + public:\ + void initialize();\ + void tick();\ + void render();\ + void destroy();\ + }; diff --git a/engine/inc/uf/engine/entity/entity.h b/engine/inc/uf/engine/entity/entity.h index b55dd59e..57d3cd25 100644 --- a/engine/inc/uf/engine/entity/entity.h +++ b/engine/inc/uf/engine/entity/entity.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -9,7 +9,16 @@ #include namespace uf { - class UF_API Entity : public uf::Component { +/* + class UF_API EntityBehavior { + public: + void initialize(); + void destroy(); + void tick(); + void render(); + }; +*/ + class UF_API Entity : public uf::Behaviors { public: typedef std::vector container_t; protected: @@ -25,15 +34,15 @@ namespace uf { static uf::MemoryPool memoryPool; Entity( bool = false ); virtual ~Entity(); - + // identifiers + const std::string& getName() const; + std::size_t getUid() const; + // parent-child relationship bool hasParent() const; template T& getParent(); template T& getRootParent(); template const T& getParent() const; template const T& getRootParent() const; - const std::string& getName() const; - std::size_t getUid() const; - void setParent(); void setParent( uf::Entity& parent ); uf::Entity& addChild( uf::Entity& child ); @@ -41,30 +50,26 @@ namespace uf { void removeChild( uf::Entity& child ); uf::Entity::container_t& getChildren(); const uf::Entity::container_t& getChildren() const; - - virtual void initialize(); - virtual void destroy(); - virtual void tick(); - virtual void render(); - + // use instantiate to allocate void* operator new(size_t, const std::string& = ""); void operator delete(void*); - - template void initialize(); - template void destroy(); - template void tick(); - template void render(); - + // search uf::Entity* findByName( const std::string& name ); uf::Entity* findByUid( std::size_t id ); const uf::Entity* findByName( const std::string& name ) const; const uf::Entity* findByUid( std::size_t id ) const; + // filters void process( std::function ); void process( std::function, int depth = 0 ); - // void process( std::function ) const ; - // void process( std::function, int depth = 0 ) const; + // globals static uf::Entity* globalFindByUid( size_t id ); static uf::Entity* globalFindByName( const std::string& name ); + + // behavior + virtual void initialize(); + virtual void destroy(); + virtual void tick(); + virtual void render(); }; } #include "entity.inl" \ No newline at end of file diff --git a/engine/inc/uf/engine/entity/entity.inl b/engine/inc/uf/engine/entity/entity.inl index e2b5976e..4140cfb4 100644 --- a/engine/inc/uf/engine/entity/entity.inl +++ b/engine/inc/uf/engine/entity/entity.inl @@ -30,7 +30,7 @@ template const T& uf::Entity::getRootParent() const { } return *(const T*) last; } - +/* template void uf::Entity::initialize() { static_cast(this)->initialize(); this->initialize(); @@ -46,4 +46,5 @@ template void uf::Entity::tick() { template void uf::Entity::render() { static_cast(this)->render(); this->render(); -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/engine/inc/uf/engine/scene/scene.h b/engine/inc/uf/engine/scene/scene.h index 7e6c1069..b06b97b6 100644 --- a/engine/inc/uf/engine/scene/scene.h +++ b/engine/inc/uf/engine/scene/scene.h @@ -12,14 +12,14 @@ namespace uf { virtual void render(); virtual void destroy(); - virtual uf::Entity* getController(); - virtual const uf::Entity* getController() const; + virtual uf::Entity& getController(); + virtual const uf::Entity& getController() const; template T& getController() { - return *((T*) this->getController()); + return *((T*) &this->getController()); } template const T& getController() const { - return *((const T*) this->getController()); + return *((const T*) &this->getController()); } }; diff --git a/engine/inc/uf/ext/vulkan/device.h b/engine/inc/uf/ext/vulkan/device.h index 6e79de89..5ec2f73b 100644 --- a/engine/inc/uf/ext/vulkan/device.h +++ b/engine/inc/uf/ext/vulkan/device.h @@ -27,11 +27,19 @@ namespace ext { VkPhysicalDeviceFeatures2 features2; VkPhysicalDeviceFeatures2 enabledFeatures2; VkPhysicalDeviceMemoryProperties2 memoryProperties2; + + struct { + std::vector instance; + std::vector device; + } extensionProperties; + struct { + std::vector instance; + std::vector device; + } supportedExtensions; VkPipelineCache pipelineCache; std::vector queueFamilyProperties; - std::vector supportedExtensions; struct { VkQueue graphics; diff --git a/engine/inc/uf/utils/math/math.h b/engine/inc/uf/utils/math/math.h index 9029108a..0947ecd5 100644 --- a/engine/inc/uf/utils/math/math.h +++ b/engine/inc/uf/utils/math/math.h @@ -9,4 +9,14 @@ namespace pod { namespace { // Sometimes uint isn't declared typedef unsigned int uint; -} \ No newline at end of file +} +/* +namespace uf { + namespace math { + template + T lerp( const T& from, const T& to, double delta ) { + + } + } +} +*/ \ No newline at end of file diff --git a/engine/inc/uf/utils/mempool/mempool.h b/engine/inc/uf/utils/mempool/mempool.h index cecea236..51315ef8 100644 --- a/engine/inc/uf/utils/mempool/mempool.h +++ b/engine/inc/uf/utils/mempool/mempool.h @@ -10,6 +10,7 @@ #define UF_MEMORYPOOL_INVALID_MALLOC 0 #define UF_MEMORYPOOL_INVALID_FREE 0 #define UF_MEMORYPOOL_OVERRIDE_NEW_DELETE 0 +#define UF_MEMORYPOOL_CACHED_ALLOCATIONS 0 namespace pod { struct UF_API Userdata; @@ -29,6 +30,7 @@ namespace uf { typedef std::vector allocations_t; allocations_t m_allocations; + allocations_t m_cachedFreeAllocations; public: static bool globalOverride; static bool subPool; diff --git a/engine/inc/uf/utils/userdata/userdata.inl b/engine/inc/uf/utils/userdata/userdata.inl index 885d20ca..8c311e54 100644 --- a/engine/inc/uf/utils/userdata/userdata.inl +++ b/engine/inc/uf/utils/userdata/userdata.inl @@ -4,36 +4,6 @@ template pod::Userdata* uf::userdata::create( const T& data ) { return uf::userdata::create( uf::userdata::memoryPool, data ); -/* - if ( uf::userdata::memoryPool.size() > 0 ) { - return uf::userdata::create( uf::userdata::memoryPool, data ); - } else { -#if UF_USERDATA_KLUDGE - void* pointer = operator new( sizeof(pod::Userdata) + sizeof data ); - pod::Userdata* userdata = (pod::Userdata*) pointer; - userdata->len = sizeof data; - userdata->pointer = NULL; - union { - uint8_t* from; - T* to; - } static kludge; - kludge.from = userdata->data; - ::new (kludge.to) T(data); - return userdata; -#else - pod::Userdata* userdata = new pod::Userdata; - userdata->len = sizeof data; - userdata->data = (uint8_t*) operator new(userdata->len); - union { - uint8_t* from; - T* to; - } static kludge; - kludge.from = userdata->data; - ::new (kludge.to) T(data); - return userdata; -#endif - } -*/ } template pod::Userdata* uf::userdata::create( uf::MemoryPool& requestedMemoryPool, const T& data ) { @@ -59,57 +29,6 @@ pod::Userdata* uf::userdata::create( uf::MemoryPool& requestedMemoryPool, const kludge.from = userdata->data; ::new (kludge.to) T(data); return userdata; -/* - uf::MemoryPool* memoryPool = NULL; - if ( requestedMemoryPool.size() > 0 ) memoryPool = &requestedMemoryPool; - else if ( uf::MemoryPool::global.size() > 0 ) memoryPool = &uf::MemoryPool::global; - pod::Userdata* userdata; - if ( memoryPool ) - userdata = (pod::Userdata*) memoryPool->alloc( NULL, sizeof(pod::Userdata) + sizeof(data) ); - else { - userdata = uf::userdata::create( requestedMemoryPool, sizeof(data), NULL ); - } - userdata->len = sizeof(data); -#if UF_USERDATA_KLUDGE - userdata->pointer = NULL; -#endif - union { - uint8_t* from; - T* to; - } static kludge; - kludge.from = userdata->data; - ::new (kludge.to) T(data); - return userdata; -*/ -/* - if ( uf::userdata::memoryPool.size() > 0 ) { - // pod::Userdata* userdata = uf::userdata::create( memoryPool, sizeof(pod::Userdata) + sizeof(data), NULL ); - void* pointer = uf::userdata::memoryPool.alloc( NULL, sizeof(pod::Userdata) + sizeof(data) ); - pod::Userdata* userdata = (pod::Userdata*) pointer; - userdata->len = sizeof(data); - #if UF_USERDATA_KLUDGE - userdata->pointer = NULL; - #endif - union { - uint8_t* from; - T* to; - } static kludge; - kludge.from = userdata->data; - ::new (kludge.to) T(data); - return userdata; - } else { - if ( memoryPool.size() <= 0 ) return uf::userdata::create(data); - pod::Userdata* userdata = new pod::Userdata; - auto allocation = memoryPool.allocate( data ); - userdata->len = allocation.size; - #if UF_USERDATA_KLUDGE - userdata->pointer = (uint8_t*) allocation.pointer; - #else - userdata->data = (uint8_t*) allocation.pointer; - #endif - return userdata; - } -*/ } // Easy way to get the userdata as a reference #include diff --git a/engine/src/engine/behavior/behavior.cpp b/engine/src/engine/behavior/behavior.cpp new file mode 100644 index 00000000..06134f20 --- /dev/null +++ b/engine/src/engine/behavior/behavior.cpp @@ -0,0 +1,27 @@ +#include + +void uf::Behaviors::addBehavior( const pod::Behavior& behavior ) { + std::cout << "[!!!] behavior attached" << std::endl; + this->m_behaviors.emplace_back(behavior); +} + +void uf::Behaviors::initialize() { + for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) { + std::cout << "[!!!] behavior called: initialize" << std::endl; + it->initialize(); + } +} +void uf::Behaviors::tick() { + for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) + it->tick(); +} +void uf::Behaviors::render() { + for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) + it->render(); +} +void uf::Behaviors::destroy() { + for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) { + std::cout << "[!!!] behavior called: destroy" << std::endl; + it->destroy(); + } +} \ No newline at end of file diff --git a/engine/src/engine/entity/entity.cpp b/engine/src/engine/entity/entity.cpp index d515dbb2..5acacae7 100644 --- a/engine/src/engine/entity/entity.cpp +++ b/engine/src/engine/entity/entity.cpp @@ -49,38 +49,6 @@ const std::string& uf::Entity::getName() const { std::size_t uf::Entity::getUid() const { return this->m_uid; } -void uf::Entity::initialize(){ - if ( this->m_uid == 0 ) this->m_uid = ++uf::Entity::uids; -} -void uf::Entity::destroy(){ - for ( uf::Entity* kv : this->m_children ) { - if ( !kv ) continue; - if ( kv->getUid() == 0 ) continue; - kv->destroy(); - kv->setParent(); - delete kv; - } - this->m_children.clear(); - this->m_uid = 0; -/* - auto it = std::find(uf::Entity::entities.begin(), uf::Entity::entities.end(), this); - if ( it != uf::Entity::entities.end() ) uf::Entity::entities.erase(it); -*/ -} -void uf::Entity::tick(){ - for ( uf::Entity* kv : this->m_children ) { - if ( !kv ) continue; - if ( kv->getUid() == 0 ) continue; - kv->tick(); - } -} -void uf::Entity::render(){ - for ( uf::Entity* kv : this->m_children ) { - if ( !kv ) continue; - if ( kv->getUid() == 0 ) continue; - kv->render(); - } -} void* uf::Entity::operator new(size_t size, const std::string& type ) { return type != "" && size == sizeof(uf::Entity) ? uf::instantiator::instantiate( type ) : uf::instantiator::alloc( size ); @@ -137,22 +105,6 @@ void uf::Entity::process( std::function fn, int depth ) entity->process(fn, depth + 1); } } -/* -void uf::Entity::process( std::function fn ) const { - fn(this); - for ( uf::Entity* entity : this->getChildren() ) { - if ( !entity ) continue; - entity->process(fn); - } -} -void uf::Entity::process( std::function fn, int depth ) const { - fn(this, depth); - for ( uf::Entity* entity : this->getChildren() ) { - if ( !entity ) continue; - entity->process(fn, depth + 1); - } -} -*/ uf::Entity* uf::Entity::globalFindByUid( size_t uid ) { for ( auto& allocation : uf::Entity::memoryPool.allocations() ) { uf::Entity* entity = (uf::Entity*) allocation.pointer; @@ -166,12 +118,74 @@ uf::Entity* uf::Entity::globalFindByName( const std::string& name ) { if ( entity->getUid() == 0 ) continue; if ( entity->getName() == name ) return entity; } -/* - for ( uf::Entity* e : uf::Entity::entities ) { - if ( !e ) continue; - if ( e->getUid() == 0 ) continue; - if ( e->getName() == name ) return e; - } -*/ return NULL; -} \ No newline at end of file +} + + +void uf::Entity::initialize( ){ + if ( this->m_uid == 0 ) this->m_uid = ++uf::Entity::uids; + + uf::Behaviors::initialize(); +} +void uf::Entity::tick( ){ + uf::Behaviors::tick(); + + for ( uf::Entity* kv : this->m_children ) { + if ( !kv ) continue; + if ( kv->getUid() == 0 ) continue; + kv->tick(); + } +} +void uf::Entity::render( ){ + uf::Behaviors::render(); + + for ( uf::Entity* kv : this->m_children ) { + if ( !kv ) continue; + if ( kv->getUid() == 0 ) continue; + kv->render(); + } +} +void uf::Entity::destroy( ){ + uf::Behaviors::destroy(); + + for ( uf::Entity* kv : this->m_children ) { + if ( !kv ) continue; + if ( kv->getUid() == 0 ) continue; + kv->destroy(); + kv->setParent(); + delete kv; + } + this->m_children.clear(); + this->m_uid = 0; +} + +/* +void uf::EntityBehavior::initialize( uf::Entity& base ){ + if ( base.m_uid == 0 ) base.m_uid = ++uf::Entity::uids; +} +void uf::EntityBehavior::destroy( uf::Entity& entity ){ + for ( uf::Entity* kv : base.m_children ) { + if ( !kv ) continue; + if ( kv->getUid() == 0 ) continue; + kv->destroy(); + kv->setParent(); + delete kv; + } + base.m_children.clear(); + base.m_uid = 0; +} +void uf::EntityBehavior::tick( uf::Entity& entity ){ + for ( uf::Entity* kv : base.m_children ) { + if ( !kv ) continue; + if ( kv->getUid() == 0 ) continue; + kv->tick(); + } +} +void uf::EntityBehavior::render( uf::Entity& entity ){ + for ( uf::Entity* kv : base.m_children ) { + if ( !kv ) continue; + if ( kv->getUid() == 0 ) continue; + kv->render(); + } +} +*/ \ No newline at end of file diff --git a/engine/src/engine/object/object.cpp b/engine/src/engine/object/object.cpp index 4e919fcc..2468a177 100644 --- a/engine/src/engine/object/object.cpp +++ b/engine/src/engine/object/object.cpp @@ -71,14 +71,10 @@ void uf::Object::destroy() { } void uf::Object::tick() { uf::Entity::tick(); + // listen for metadata file changes uf::Serializer& metadata = this->getComponent(); 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; @@ -115,7 +111,8 @@ void uf::Object::render() { auto& scene = uf::scene::getCurrentScene(); auto& graphic = this->getComponent(); auto& transform = this->getComponent>(); - auto& camera = scene.getController()->getComponent(); + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); if ( !graphic.initialized ) return; @@ -399,23 +396,45 @@ bool uf::Object::load( const uf::Serializer& json ) { 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(); - auto& transform = light->getComponent>(); - 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(); + std::vector orientations; + if ( json["transform"]["orientation"].isNull() && json["shadows"]["fov"].asFloat() == 0.0f ) { + orientations.reserve(6); + orientations.push_back({0, 0, 0, -1}); + orientations.push_back({0, 0.707107, 0, -0.707107}); + orientations.push_back({0, 1, 0, 0}); + orientations.push_back({0, 0.707107, 0, 0.707107}); + orientations.push_back({-0.707107, 0, 0, -0.707107}); + orientations.push_back({0.707107, 0, 0, -0.707107}); + json["shadows"]["fov"] = 90.0f; + } else { + pod::Vector4f orientation; + for ( uint j = 0; j < 4; ++j ) orientation[j] = json["transform"]["orientation"][j].asFloat(); + orientations.push_back(orientation); + } + uf::Object* target = this; + for ( auto& orientation : orientations ) { + auto* light = target->findByUid(target->loadChild("/light.json", false)); + if ( !light ) continue; + if ( target == this ) target = (uf::Object*) light; + auto& metadata = light->getComponent(); + auto& transform = light->getComponent>(); + if ( json["transform"]["position"].isArray() ) + for ( uint j = 0; j < 3; ++j ) + transform.position[j] = json["transform"]["position"][j].asFloat(); + for ( uint j = 0; j < 4; ++j ) + transform.orientation[j] = orientation[j]; - 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"]; + 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"]; + if ( !json["flicker"].isNull() ) metadata["light"]["flicker"] = json["flicker"]; + if ( !json["fade"].isNull() ) metadata["light"]["fade"] = json["fade"]; - light->initialize(); + if ( !json["system"]["track"].isNull() ) metadata["system"]["track"] = json["system"]["track"]; - // std::cout << json << "\t" << metadata["light"] << std::endl; + light->initialize(); + } } } diff --git a/engine/src/engine/scene/scene.cpp b/engine/src/engine/scene/scene.cpp index cb3d4e75..f35d270e 100644 --- a/engine/src/engine/scene/scene.cpp +++ b/engine/src/engine/scene/scene.cpp @@ -1,184 +1,17 @@ #include -#include #include #include - -#include -#include -#include -#include +#include UF_OBJECT_REGISTER_CPP(Scene) void uf::Scene::initialize() { - ext::vulkan::scenes.push_back(this); - ext::vulkan::rebuild = true; + uf::renderer::scenes.push_back(this); + uf::renderer::rebuild = true; + uf::Object::initialize(); } void uf::Scene::tick() { uf::Object::tick(); - - if ( uf::scene::getCurrentScene().getUid() == this->getUid() ) { - uf::Serializer& metadata = this->getComponent(); - /* Update lights */ if ( metadata["light"]["should"].asBool() ) { - // if ( !ext::vulkan::currentRenderMode || ext::vulkan::currentRenderMode->name != "" ) return; - - auto& scene = uf::scene::getCurrentScene(); - - std::vector blitters; - auto& renderMode = ext::vulkan::getRenderMode("", true); - bool hasCompute = ext::vulkan::hasRenderMode("C:RT:" + std::to_string(this->getUid()), true); - if ( hasCompute ) { - // auto& renderMode = ext::vulkan::getRenderMode("C:RT:" + std::to_string(this->getUid()), true); - // auto* renderModePointer = (ext::vulkan::ComputeRenderMode*) &renderMode; - // if ( renderModePointer->compute.initialized ) { - // blitters.push_back(&renderModePointer->compute); - // } else { - // hasCompute = false; - // } - } else 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(); - - // 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(); - } - - 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 entities; - std::function 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>().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>() ) return false; if ( !r->hasComponent>() ) return true; - return uf::vector::magnitude( uf::vector::subtract( l->getComponent>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent>().position, position ) ); - } ); - } - - { - uf::Serializer& metadata = controller.getComponent(); - 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>(); - uf::Serializer& metadata = entity->getComponent(); - uf::Camera& camera = entity->getComponent(); - - 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"]["radius"].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"]["power"].asFloat(); - - light.type.x = metadata["light"]["type"].asUInt64(); - light.type.y = metadata["light"]["shadows"]["enabled"].asBool(); - - if ( !hasCompute && entity->hasComponent() ) { - auto& renderMode = entity->getComponent(); - auto& renderTarget = renderMode.renderTarget; - - uint8_t i = 0; - for ( auto& attachment : renderTarget.attachments ) { - // if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; - // if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; - if ( (attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) ) 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() { uf::Object::render(); @@ -188,32 +21,21 @@ void uf::Scene::destroy() { uf::Object::destroy(); { - auto it = std::find(ext::vulkan::scenes.begin(), ext::vulkan::scenes.end(), this); - if ( it != ext::vulkan::scenes.end() ) { - ext::vulkan::scenes.erase(it); - } + auto it = std::find(uf::renderer::scenes.begin(), uf::renderer::scenes.end(), this); + if ( it != uf::renderer::scenes.end() ) uf::renderer::scenes.erase(it); + uf::renderer::rebuild = true; } - ext::vulkan::rebuild = true; } - -/* -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() { +uf::Entity& uf::Scene::getController() { static uf::Entity* cachedController = NULL; - if ( ext::vulkan::currentRenderMode ) { - static ext::vulkan::RenderMode* cachedRenderMode = NULL; - auto& renderMode = *ext::vulkan::currentRenderMode; + if ( uf::renderer::currentRenderMode ) { + static uf::renderer::RenderMode* cachedRenderMode = NULL; + auto& renderMode = *uf::renderer::currentRenderMode; if ( cachedRenderMode == &renderMode && cachedController && cachedController->getUid() > 0 ) { - return cachedController; + return *cachedController; } cachedController = NULL; cachedRenderMode = &renderMode; @@ -221,34 +43,17 @@ uf::Entity* uf::Scene::getController() { if ( split.front() == "RT" ) { uint64_t uid = std::stoi( split.back() ); uf::Entity* ent = this->findByUid( uid ); - if ( ent ) return cachedController = ent; + if ( ent ) return *(cachedController = ent); } } - if ( cachedController && cachedController->getUid() > 0 ) return cachedController; - return cachedController = this->findByName("Player"); + if ( cachedController && cachedController->getUid() > 0 ) return *cachedController; + cachedController = this->findByName("Player"); + return cachedController ? *cachedController : *this; // return this; } -const uf::Entity* uf::Scene::getController() const { - static const uf::Entity* cachedController = NULL; - if ( ext::vulkan::currentRenderMode ) { - static ext::vulkan::RenderMode* cachedRenderMode = NULL; - auto& renderMode = *ext::vulkan::currentRenderMode; - - if ( cachedRenderMode == &renderMode && cachedController && cachedController->getUid() > 0 ) { - return cachedController; - } - cachedController = NULL; - cachedRenderMode = &renderMode; - auto split = uf::string::split( renderMode.name, ":" ); - if ( split.front() == "RT" ) { - uint64_t uid = std::stoi( split.back() ); - const uf::Entity* ent = this->findByUid( uid ); - if ( ent ) return cachedController = ent; - } - } - if ( cachedController && cachedController->getUid() > 0 ) return cachedController; - return cachedController = this->findByName("Player"); - // return this; +const uf::Entity& uf::Scene::getController() const { + uf::Scene& scene = *const_cast(this); + return scene.getController(); } #include std::vector uf::scene::scenes; diff --git a/engine/src/ext/openvr/openvr.cpp b/engine/src/ext/openvr/openvr.cpp index 2f71e7de..a4ae9f59 100644 --- a/engine/src/ext/openvr/openvr.cpp +++ b/engine/src/ext/openvr/openvr.cpp @@ -7,6 +7,8 @@ #include +#define DEBUG_MARKER 0 + vr::IVRSystem* ext::openvr::context; ext::openvr::Driver ext::openvr::driver; uint8_t ext::openvr::renderPass = 0; @@ -163,14 +165,14 @@ bool ext::openvr::initialize( int stage ) { uf::Serializer manifest; manifest.readFromFile(ext::openvr::driver.manifest); - std::cout << ext::openvr::driver.manifest << std::endl; + if ( DEBUG_MARKER ) std::cout << ext::openvr::driver.manifest << std::endl; for ( auto i = 0; i < manifest["action_sets"].size(); ++i ) { - std::cout << manifest["action_sets"][i] << std::endl; + if ( DEBUG_MARKER ) std::cout << manifest["action_sets"][i] << std::endl; std::string name = manifest["action_sets"][i]["name"].asString(); vr::VRActionSetHandle_t handle; VR_CHECK_INPUT_RESULT( vr::VRInput()->GetActionSetHandle( name.c_str(), &handle ) ); handles.actionSets[name] = handle; - std::cout << "Registered action set: " << name << std::endl; + if ( DEBUG_MARKER ) std::cout << "Registered action set: " << name << std::endl; // handles.actionSets.push_back(handle); } for ( auto i = 0; i < manifest["actions"].size(); ++i ) { @@ -178,7 +180,7 @@ bool ext::openvr::initialize( int stage ) { vr::VRActionHandle_t handle; VR_CHECK_INPUT_RESULT( vr::VRInput()->GetActionHandle( name.c_str(), &handle ) ); handles.actions[name] = handle; - std::cout << "Registered action: " << name << std::endl; + if ( DEBUG_MARKER ) std::cout << "Registered action: " << name << std::endl; // handles.actions.push_back(handle); // add haptics to hooks @@ -187,7 +189,7 @@ bool ext::openvr::initialize( int stage ) { std::string shortname = split.back(); split = uf::string::split( shortname, "." ); if ( split.front() == "hapticVibration" ) { - std::cout << "Registered hook for haptic: " << ("VR:Haptics."+split.back()) << std::endl; + if ( DEBUG_MARKER ) std::cout << "Registered hook for haptic: " << ("VR:Haptics."+split.back()) << std::endl; uf::hooks.addHook( "VR:Haptics."+split.back(), [&](const std::string& event)->std::string{ uf::Serializer json = event; if ( vr::VRInputError_None != vr::VRInput()->TriggerHapticVibrationAction( handle, json["delay"].asFloat(), json["duration"].asFloat(), json["frequency"].asFloat(), json["amplitude"].asFloat(), vr::k_ulInvalidInputValueHandle ) ) @@ -234,7 +236,7 @@ void ext::openvr::tick() { if ( !ext::openvr::context ) return; // load render model from api - for ( auto pair : ::queuedRenderModels ) { + for ( auto& pair : ::queuedRenderModels ) { std::string name = pair.first; auto& queued = pair.second; { @@ -243,7 +245,7 @@ void ext::openvr::tick() { if ( status == vr::VRRenderModelError_Loading ) continue; // error'd out if ( status != vr::VRRenderModelError_None ) { - std::cout << "Failed to load render model " << name << ": " << vr::VRRenderModels()->GetRenderModelErrorNameFromEnum( status ) << std::endl; + if ( DEBUG_MARKER ) std::cout << "Failed to load render model " << name << ": " << vr::VRRenderModels()->GetRenderModelErrorNameFromEnum( status ) << std::endl; ::queuedRenderModels.erase(name); continue; } @@ -255,7 +257,7 @@ void ext::openvr::tick() { if ( status == vr::VRRenderModelError_Loading ) continue; // error'd out if ( status != vr::VRRenderModelError_None ) { - std::cout << "Failed to load render model " << name << "'s texture: " << vr::VRRenderModels()->GetRenderModelErrorNameFromEnum( status ) << std::endl; + if ( DEBUG_MARKER ) std::cout << "Failed to load render model " << name << "'s texture: " << vr::VRRenderModels()->GetRenderModelErrorNameFromEnum( status ) << std::endl; vr::VRRenderModels()->FreeRenderModel( queued.model ); ::queuedRenderModels.erase(name); continue; @@ -430,6 +432,7 @@ void ext::openvr::tick() { } } bool ext::openvr::requestRenderModel( const std::string& name ) { + if ( DEBUG_MARKER ) std::cout << "Requesting render model: " << name << std::endl; if ( std::find( renderModelNames.begin(), renderModelNames.end(), name ) == renderModelNames.end() ) return false; if ( renderModels.count(name) == 1 ) return true; ::queuedRenderModels[name]; @@ -466,12 +469,12 @@ void ext::openvr::submit() { bool invert = swapEyes; vulkanData.m_nFormat = leftOutputAttachment.format; vulkanData.m_nImage = (uint64_t) (VkImage) leftOutputAttachment.image; - // std::cout << leftOutputAttachment.image << std::endl; + // if ( DEBUG_MARKER ) std::cout << leftOutputAttachment.image << std::endl; vr::VRCompositor()->Submit( invert ? vr::Eye_Right : vr::Eye_Left, &texture, &bounds ); vulkanData.m_nFormat = rightOutputAttachment.format; vulkanData.m_nImage = (uint64_t) (VkImage) rightOutputAttachment.image; - // std::cout << rightOutputAttachment.image << std::endl; + // if ( DEBUG_MARKER ) std::cout << rightOutputAttachment.image << std::endl; vr::VRCompositor()->Submit( invert ? vr::Eye_Left : vr::Eye_Right, &texture, &bounds ); vr::VRCompositor()->PostPresentHandoff(); @@ -557,7 +560,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; + // if ( DEBUG_MARKER ) 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); diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index 4dc42a0b..94fb829c 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -11,7 +11,7 @@ #include namespace { - void VRExtensions( std::vector& requested ) { + void VRInstanceExtensions( std::vector& requested ) { if ( !vr::VRCompositor() ) return; uint32_t nBufferSize = vr::VRCompositor()->GetVulkanInstanceExtensionsRequired( nullptr, 0 ); if ( nBufferSize < 0 ) return; @@ -19,8 +19,45 @@ namespace { pExtensionStr[0] = 0; vr::VRCompositor()->GetVulkanInstanceExtensionsRequired( pExtensionStr, nBufferSize ); std::vector extensions = uf::string::split( pExtensionStr, " " ); - requested.insert( requested.end(), extensions.begin(), extensions.end() ); + for ( auto& str : extensions ) { + // std::cout << str << std::endl; + requested.push_back(str); + } + // requested.insert( requested.end(), extensions.begin(), extensions.end() ); } + void VRDeviceExtensions( VkPhysicalDevice_T* physicalDevice, std::vector& requested ) { + if ( !vr::VRCompositor() ) return; + uint32_t nBufferSize = vr::VRCompositor()->GetVulkanDeviceExtensionsRequired( physicalDevice, nullptr, 0 ); + if ( nBufferSize < 0 ) return; + char pExtensionStr[nBufferSize]; + pExtensionStr[0] = 0; + vr::VRCompositor()->GetVulkanDeviceExtensionsRequired( physicalDevice , pExtensionStr, nBufferSize ); + std::vector extensions = uf::string::split( pExtensionStr, " " ); + for ( auto& str : extensions ) requested.push_back(str); + // requested.insert( requested.end(), extensions.begin(), extensions.end() ); + } + + void validateRequestedExtensions( const std::vector& extensionProperties, const std::vector& requestedExtensions, std::vector& supportedExtensions ) { + for ( auto& requestedExtension : requestedExtensions ) { + bool found = false; + for ( auto& extensionProperty : extensionProperties ) { + std::string extensionName = extensionProperty.extensionName; + if ( requestedExtension != extensionName ) continue; + if ( std::find( supportedExtensions.begin(), supportedExtensions.end(), extensionName ) != supportedExtensions.end() ) { + found = true; + break; + } + if ( found ) break; + found = true; + supportedExtensions.push_back( extensionName ); + break; + } + if ( !found ) { + std::cout << "Vulkan missing requested extension: " << requestedExtension << std::endl; + } + } + } + void enableRequestedDeviceFeatures( ext::vulkan::Device& device ) { uf::Serializer json; @@ -410,44 +447,29 @@ void ext::vulkan::Device::initialize() { // Load any requested extensions requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::requestedInstanceExtensions.begin(), ext::vulkan::requestedInstanceExtensions.end() ); // OpenVR Support - if ( ext::openvr::enabled ) VRExtensions(requestedExtensions); + if ( ext::openvr::enabled ) VRInstanceExtensions(requestedExtensions); { if ( ext::vulkan::validation ) - for ( auto ext : requestedExtensions ) std::cout << "Requested extension: " << ext << std::endl; + for ( auto ext : requestedExtensions ) + std::cout << "Requested instance extension: " << ext << std::endl; + uint32_t extensionsCount = 0; uint32_t enabledExtensionsCount = 0; VK_CHECK_RESULT(vkEnumerateInstanceExtensionProperties( NULL, &extensionsCount, NULL )); + extensionProperties.instance.resize(extensionsCount); + VK_CHECK_RESULT( vkEnumerateInstanceExtensionProperties( NULL, &extensionsCount, extensionProperties.instance.data() ) ); - std::vector extensionProperties(extensionsCount); - VK_CHECK_RESULT( vkEnumerateInstanceExtensionProperties( NULL, &extensionsCount, &extensionProperties[0] ) ); - - for ( size_t i = 0; i < requestedExtensions.size(); ++i ) { - bool found = false; uint32_t index = 0; - for ( index = 0; index < extensionsCount; index++ ) { - if ( strcmp( requestedExtensions[i].c_str(), extensionProperties[index].extensionName ) == 0 ) { - for ( auto& alreadyAdded : supportedExtensions ) { - if ( requestedExtensions[i] == alreadyAdded ) { - found = true; - break; - } - } - if ( found ) break; - found = true; - supportedExtensions.push_back(extensionProperties[index].extensionName); - break; - } - } - if ( !found ) std::cout << "Vulkan missing requested extension " << requestedExtensions[index] << std::endl; - } + validateRequestedExtensions( extensionProperties.instance, requestedExtensions, supportedExtensions.instance ); } // Create instance { - std::vector extensions; - for ( auto& s : supportedExtensions ) { - if ( ext::vulkan::validation ) std::cout << "Enabled extension: " << s << std::endl; - extensions.push_back( s.c_str() ); + std::vector instanceExtensions; + for ( auto& s : supportedExtensions.instance ) { + if ( ext::vulkan::validation ) + std::cout << "Enabled instance extension: " << s << std::endl; + instanceExtensions.push_back( s.c_str() ); } VkApplicationInfo appInfo = {}; @@ -462,8 +484,8 @@ void ext::vulkan::Device::initialize() { createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; - createInfo.enabledExtensionCount = static_cast(extensions.size()); - createInfo.ppEnabledExtensionNames = extensions.data(); + createInfo.enabledExtensionCount = static_cast(instanceExtensions.size()); + createInfo.ppEnabledExtensionNames = instanceExtensions.data(); if ( ext::vulkan::validation ) { createInfo.enabledLayerCount = static_cast(validationLayers.size()); @@ -536,45 +558,31 @@ void ext::vulkan::Device::initialize() { bool useSwapChain = true; VkQueueFlags requestedQueueTypes = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT; std::vector requestedExtensions; - std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::requestedInstanceExtensions.begin(), ext::vulkan::requestedInstanceExtensions.end() ); - /* OpenVR support */ if ( ext::openvr::enabled && vr::VRCompositor() ) { - uint32_t nBufferSize = vr::VRCompositor()->GetVulkanDeviceExtensionsRequired( ( VkPhysicalDevice_T * ) this->physicalDevice, nullptr, 0 ); - if ( nBufferSize > 0 ) { - char pExtensionStr[nBufferSize]; - pExtensionStr[0] = 0; - vr::VRCompositor()->GetVulkanDeviceExtensionsRequired( ( VkPhysicalDevice_T * ) this->physicalDevice, pExtensionStr, nBufferSize ); - std::vector vrExtensions = uf::string::split( pExtensionStr, " " ); - requestedExtensions.insert( requestedExtensions.end(), vrExtensions.begin(), vrExtensions.end() ); - } + requestedExtensions.insert( requestedExtensions.end(), ext::vulkan::requestedDeviceExtensions.begin(), ext::vulkan::requestedDeviceExtensions.end() ); + // OpenVR Support + if ( ext::openvr::enabled ) { + VRDeviceExtensions( this->physicalDevice, requestedExtensions); + } + { // Allocate enough ExtensionProperties to support all extensions being enabled + if ( ext::vulkan::validation ) + for ( auto ext : requestedExtensions ) std::cout << "Requested device extension: " << ext << std::endl; + uint32_t extensionsCount = 0; uint32_t enabledExtensionsCount = 0; VK_CHECK_RESULT(vkEnumerateDeviceExtensionProperties( this->physicalDevice, NULL, &extensionsCount, NULL )); - std::vector extensionProperties(extensionsCount); - VK_CHECK_RESULT( vkEnumerateDeviceExtensionProperties( this->physicalDevice, NULL, &extensionsCount, &extensionProperties[0] ) ); + extensionProperties.device.resize( extensionsCount ); + VK_CHECK_RESULT( vkEnumerateDeviceExtensionProperties( this->physicalDevice, NULL, &extensionsCount, extensionProperties.device.data() ) ); - for ( size_t i = 0; i < requestedExtensions.size(); ++i ) { - bool found = false; - uint32_t index = 0; - for ( index = 0; index < extensionsCount; index++ ) { - if ( strcmp( requestedExtensions[i].c_str(), extensionProperties[index].extensionName ) == 0 ) { - for ( auto alreadyAdded : deviceExtensions ) { - if ( strcmp( requestedExtensions[i].c_str(), alreadyAdded ) == 0 ) { - found = true; - break; - } - } - if ( found ) break; - found = true; - deviceExtensions.push_back(extensionProperties[index].extensionName); - } - } - if ( !found ) std::cout << "Vulkan missing requested extension " << requestedExtensions[index] << std::endl; - } + validateRequestedExtensions( extensionProperties.device, requestedExtensions, supportedExtensions.device ); + } + std::vector deviceExtensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + for ( auto& s : supportedExtensions.device ) { + if ( ext::vulkan::validation ) std::cout << "Enabled device extension: " << s << std::endl; + deviceExtensions.push_back( s.c_str() ); } // Desired queues need to be requested upon logical device creation diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 81becf94..eeabfb17 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -426,9 +426,42 @@ void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuf } size_t offset = 0; for ( auto& pushConstant : shader.pushConstants ) { + size_t len = 0; + void* pointer = NULL; + if ( bindPoint == VK_PIPELINE_BIND_POINT_COMPUTE ) { + len = pushConstant.data().len; + pointer = pushConstant.data().data; + } else { + struct Stereo { + uint32_t pass; + }; + static Stereo stereo; + stereo.pass = ext::openvr::renderPass; + + len = sizeof(stereo); + pointer = &stereo; + } + if ( len > 0 && pointer ) + vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, len, pointer ); + /* + size_t len = pushConstant.data().len; + void* pointer = pushConstant.data().data; + std::cout << pointer << ": " << len << std::endl; + if ( len == 4 ) { + struct Stereo { + uint32_t pass; + }; + auto& stereo = pushConstant.get(); + std::cout << pointer << ": Got " << stereo.pass << std::endl; + } + vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, len, pointer ); + */ + /* struct PushConstant { uint32_t pass; } p = { ext::openvr::renderPass }; + vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, sizeof(p), &p ); + */ /* pod::Userdata& userdata = pushConstant.data(); { @@ -437,7 +470,6 @@ void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuf vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, offset, userdata.len, userdata.data ); offset += userdata.len; */ - vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, sizeof(p), &p ); } } // Bind descriptor sets describing shader binding points diff --git a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp index f2ef00d7..b8cc1534 100644 --- a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp @@ -237,21 +237,6 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st // transition layers for read for ( auto layer : layers ) { layer->pipelineBarrier( commands[i], 0 ); - /* - if ( layer->getName() == "" ) continue; - 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; - 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); @@ -260,6 +245,20 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st for ( auto graphic : graphics ) { // only draw graphics that are assigned to this type of render mode if ( graphic->descriptor.renderMode != this->getName() ) continue; + // update push constants + /* + auto& shaders = graphic->material.shaders; + for ( auto& shader : shaders ) { + for ( auto& pushConstant : shader.pushConstants ) { + struct Stereo { + uint32_t pass; + }; + auto& stereo = pushConstant.get(); + stereo.pass = ext::openvr::renderPass; + std::cout << pushConstant.data().data << ": Expecting " << stereo.pass << std::endl; + } + } + */ graphic->record(commands[i] ); } // render gui layer @@ -290,21 +289,6 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st for ( auto layer : layers ) { layer->pipelineBarrier( commands[i], 1 ); - /* - if ( layer->getName() == "" ) continue; - 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 = 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 diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index da90c41e..0202d397 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -177,6 +177,7 @@ ext::vulkan::RenderMode& ext::vulkan::addRenderMode( ext::vulkan::RenderMode* mo renderModes.push_back(mode); std::cout << "Adding RenderMode: " << name << ": " << mode->getType() << std::endl; // reorder + ext::vulkan::rebuild = true; return *mode; } ext::vulkan::RenderMode& ext::vulkan::getRenderMode( const std::string& name, bool isName ) { @@ -216,6 +217,7 @@ void ext::vulkan::removeRenderMode( ext::vulkan::RenderMode* mode, bool free ) { renderModes.erase( std::remove( renderModes.begin(), renderModes.end(), mode ), renderModes.end() ); mode->destroy(); if ( free ) delete mode; + ext::vulkan::rebuild = true; } void ext::vulkan::initialize( uint8_t stage ) { @@ -292,7 +294,10 @@ void ext::vulkan::tick() { } for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; - if ( !renderMode->device ) renderMode->initialize(ext::vulkan::device); + if ( !renderMode->device ) { + renderMode->initialize(ext::vulkan::device); + ext::vulkan::rebuild = true; + } renderMode->tick(); } for ( auto& renderMode : renderModes ) { diff --git a/engine/src/utils/camera/camera.cpp b/engine/src/utils/camera/camera.cpp index c7a1361f..6fccb800 100644 --- a/engine/src/utils/camera/camera.cpp +++ b/engine/src/utils/camera/camera.cpp @@ -23,7 +23,7 @@ uf::Camera::Camera() : this->setProjection(uf::matrix::identity()); this->m_transform = uf::transform::initialize(this->m_transform); - this->m_transform.position = {0,1.725,0}; + this->m_transform.position = {0, 0, 0}; } /* uf::Camera::Camera( const pod::Math::num_t& fov, const pod::Vector2& size, const pod::Vector2& bounds, const pod::Vector3& offset, const pod::Vector2& tops ) : diff --git a/engine/src/utils/mempool/mempool.cpp b/engine/src/utils/mempool/mempool.cpp index 182c6546..9d7e4604 100644 --- a/engine/src/utils/mempool/mempool.cpp +++ b/engine/src/utils/mempool/mempool.cpp @@ -43,8 +43,7 @@ std::string uf::MemoryPool::stats() const { metadata["free"] = size - allocated; metadata["objects"] = this->m_allocations.size(); { - std::stringstream ss; - ss << std::hex << (void*) this->m_pool; + std::stringstream ss; ss << std::hex << (void*) this->m_pool; metadata["pool"] = ss.str(); } @@ -53,20 +52,16 @@ std::string uf::MemoryPool::stats() const { void uf::MemoryPool::initialize( size_t size ) { if ( size <= 0 ) return; if ( this->size() > 0 ) this->destroy(); -// this->m_pool = (uint8_t*) malloc( size ); -// this->m_allocations.reserve( 128 ); this->m_size = size; if ( uf::MemoryPool::subPool && uf::MemoryPool::global.size() > 0 && this != &uf::MemoryPool::global ) { this->m_pool = (uint8_t*) uf::MemoryPool::global.alloc( NULL, size ); } else { this->m_pool = (uint8_t*) malloc( size ); } -// this->m_pool = (uint8_t*) operator new( size ); memset( this->m_pool, 0, size ); } void uf::MemoryPool::destroy() { if ( this->size() <= 0 ) return; -// ::free(this->m_pool); if ( uf::MemoryPool::subPool && this != &uf::MemoryPool::global ) { uf::MemoryPool::global.free( this->m_pool ); } else { @@ -79,32 +74,87 @@ void uf::MemoryPool::destroy() { pod::Allocation uf::MemoryPool::allocate( void* data, size_t size ) { if ( UF_MEMORYPOOL_MUTEX ) this->m_mutex.lock(); // find next available allocation - // RLE-esque size_t index = 0; size_t len = this->size(); pod::Allocation allocation; + // pool not initialized if ( len <= 0 ) { if ( DEBUG_PRINT ) std::cout << "CANNOT MALLOC: " << size << ", POOL NOT INITIALIZED" << std::endl; goto MANUAL_MALLOC; } - // find any availble spots in-between existing allocations + + // an optimization by quickly reusing free'd allocations seemed like a good idea + // but still have to iterate through allocation information + // to keep allocation information in order + + // check our cache of first +#if UF_MEMORYPOOL_CACHED_ALLOCATIONS + if ( !this->m_cachedFreeAllocations.empty() ) { + auto it = this->m_cachedFreeAllocations.begin(); + // check if any recently free'd allocation is big enough for our new allocation + for ( ; it != this->m_cachedFreeAllocations.end(); ++it ) { + if ( it->size < size ) break; + } + // found a suitable allocation, use it + if ( it != this->m_cachedFreeAllocations.end() ) { + index = it->index; + // find where to insert in our allocation table + auto next = this->m_allocations.begin(); + while ( next != this->m_allocations.end() ) { + if ( index + size < next->index ) break; + ++next; + } + // check if it was actually valid + if ( next != this->m_allocations.end() ) { + // initialize allocation info + allocation.index = index; + allocation.size = size; + allocation.pointer = &this->m_pool[0] + index; + + // security + if ( data ) memcpy( allocation.pointer, data, size ); + else memset( allocation.pointer, 0, size ); + + // overrides if we're overloading global new/delete + IGNORE_GLOBAL_MEMORYPOOL = true; + // register as allocated + this->m_allocations.insert(next, allocation); + IGNORE_GLOBAL_MEMORYPOOL = false; + + goto RETURN; + } + // remove from cache + this->m_cachedFreeAllocations.erase(it); + } + } +#endif { + // find any availble spots in-between existing allocations auto next = this->m_allocations.begin(); for ( auto it = next; it != this->m_allocations.end(); ++it ) { index = it->index + it->size; if ( ++next == this->m_allocations.end() ) break; + // target index is behind next allocated space, use it if ( index < next->index ) break; } + // no allocation found, OOM if ( index + size > len ) { std::cout << "MemoryPool: " << this << ": Out of Memory!" << std::endl; goto MANUAL_MALLOC; } + + // initialize allocation info allocation.index = index; allocation.size = size; allocation.pointer = &this->m_pool[0] + index; + + // security if ( data ) memcpy( allocation.pointer, data, size ); else memset( allocation.pointer, 0, size ); + + // overrides if we're overloading global new/delete IGNORE_GLOBAL_MEMORYPOOL = true; + // register as allocated this->m_allocations.insert(next, allocation); IGNORE_GLOBAL_MEMORYPOOL = false; } @@ -149,31 +199,40 @@ bool uf::MemoryPool::exists( void* pointer, size_t size ) { } bool uf::MemoryPool::free( void* pointer, size_t size ) { if ( UF_MEMORYPOOL_MUTEX ) this->m_mutex.lock(); + // fail if uninitialized or pointer is outside of our pool if ( this->m_size <= 0 || pointer < &this->m_pool[0] || pointer >= &this->m_pool[0] + this->m_size ) { if ( DEBUG_PRINT ) std::cout << "CANNOT FREE: " << pointer << ", ERROR: " << (this->m_size <= 0) << " " << (pointer < &this->m_pool[0]) << " " << (pointer >= &this->m_pool[0] + this->m_size) << std::endl; goto MANUAL_FREE; } { + // pointer arithmatic size_t index = (uint8_t*) pointer - &this->m_pool[0]; auto it = this->m_allocations.begin(); pod::Allocation allocation; + // find our allocation in the allocation pool for ( ; it != this->m_allocations.end(); ++it ) { if ( it->index == index ) { allocation = *it; break; } } - // if ( allocation.index != index || (size > 0 && allocation.size != size) ) { + // pointer isn't actually allocated if ( allocation.index != index ) { if ( DEBUG_PRINT ) std::cout << "CANNOT FREE: " << pointer << ", NOT FOUND" << std::endl; goto MANUAL_FREE; } + // size validation mismatch, do not free if (size > 0 && allocation.size != size) { if ( DEBUG_PRINT ) std::cout << "CANNOT FREE: " << pointer << ", MISMATCHED SIZES (" << size << " != " << allocation.size << ")" << std::endl; goto MANUAL_FREE; } if ( DEBUG_PRINT ) std::cout << "FREE'D ALLOCATION: " << pointer << ", " << size << "\t" << allocation.pointer << ", " << allocation.size << ", " << allocation.index << std::endl; + // remove from our allocation table... this->m_allocations.erase(it); + // ...but add it to our free'd allocation cache +#if UF_MEMORYPOOL_CACHED_ALLOCATIONS + this->m_cachedFreeAllocations.push_back(allocation); +#endif if ( UF_MEMORYPOOL_MUTEX ) this->m_mutex.unlock(); return true; } diff --git a/ext/gui/gui.cpp b/ext/gui/gui.cpp index 9150c6f4..0e174b0f 100644 --- a/ext/gui/gui.cpp +++ b/ext/gui/gui.cpp @@ -549,7 +549,7 @@ void ext::Gui::initialize() { { auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& metadata = controller.getComponent(); if ( metadata["overlay"]["cursor"]["type"].asString() == "mouse" ) { @@ -816,7 +816,8 @@ void ext::Gui::render() { auto& scene = this->getRootParent(); auto& mesh = this->getComponent(); auto& graphic = this->getComponent(); - auto& camera = scene.getController()->getComponent(); + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); auto& transform = this->getComponent>(); if ( !graphic.initialized ) return; @@ -892,7 +893,8 @@ void ext::Gui::render() { for ( std::size_t i = 0; i < 2; ++i ) { if ( metadata["text settings"]["world"].asBool() ) { auto& scene = this->getRootParent(); - auto& camera = scene.getController()->getComponent(); + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); pod::Transform<> flatten = uf::transform::flatten( this->getComponent>() ); auto model = uf::transform::model( flatten ); @@ -965,7 +967,8 @@ void ext::Gui::render() { uniforms.matrices.model[i] = ::matrix * rotation; */ auto& scene = this->getRootParent(); - auto& camera = scene.getController()->getComponent(); + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); pod::Transform<> flatten = uf::transform::flatten( this->getComponent>() ); auto model = uf::transform::model( flatten ); @@ -1018,7 +1021,7 @@ void ext::Gui::render() { { /* Update GUI panel */ { auto& scene = this->getRootParent(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& camera = controller.getComponent(); auto* renderMode = (uf::renderer::RenderTargetRenderMode*) &uf::renderer::getRenderMode("Gui"); if ( renderMode->getName() == "Gui" ) { diff --git a/ext/main.cpp b/ext/main.cpp index 4c7f42da..896ec5cb 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -321,8 +321,8 @@ void EXT_API ext::tick() { 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(); + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); auto& t = camera.getTransform(); //controller->getComponent>(); 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"; diff --git a/ext/scenes/base.cpp b/ext/scenes/base.cpp new file mode 100644 index 00000000..7cfc5839 --- /dev/null +++ b/ext/scenes/base.cpp @@ -0,0 +1,377 @@ +#include "base.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include "../ext.h" +#include "../gui/gui.h" + +void ext::Scene::initialize() { + uf::Scene::initialize(); + + uf::Asset& assetLoader = this->getComponent(); + uf::Serializer& metadata = this->getComponent(); + + this->addHook( "system:Quit.%UID%", [&](const std::string& event)->std::string{ + std::cout << event << std::endl; + ext::ready = false; + return "true"; + }); + + this->addHook( "world:Music.LoadPrevious.%UID%", [&](const std::string& event)->std::string{ + uf::Serializer json = event; + + if ( metadata["previous bgm"]["filename"] == "" ) return "false"; + + std::string filename = metadata["previous bgm"]["filename"].asString(); + float timestamp = metadata["previous bgm"]["timestamp"].asFloat(); + +// std::cout << metadata["previous bgm"] << std::endl; + + uf::Audio& audio = this->getComponent(); + if ( audio.playing() ) { + metadata["previous bgm"]["filename"] = audio.getFilename(); + metadata["previous bgm"]["timestamp"] = audio.getTime(); + audio.stop(); + } + audio.load(filename); + audio.setVolume(metadata["volumes"]["bgm"].asFloat()); + audio.setTime(timestamp); + audio.play(); + + return "true"; + }); + 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) != "ogg" ) return "false"; + const uf::Audio* audioPointer = NULL; + try { audioPointer = &assetLoader.get(filename); } catch ( ... ) {} + if ( !audioPointer ) return "false"; + + uf::Audio& audio = this->getComponent(); + if ( audio.playing() ) audio.stop(); + + audio.load(filename); + audio.setVolume(metadata["volumes"]["bgm"].asFloat()); + audio.play(); + + return "true"; + }); + + this->addHook( "menu:Pause", [&](const std::string& event)->std::string{ + static uf::Timer timer(false); + if ( !timer.running() ) timer.start(); + if ( timer.elapsed().asDouble() < 1 ) return "false"; + timer.reset(); + + uf::Serializer json = event; + ext::Gui* manager = (ext::Gui*) this->findByName("Gui Manager"); + if ( !manager ) return "false"; + uf::Serializer payload; + ext::Gui* gui = (ext::Gui*) manager->findByUid( (payload["uid"] = manager->loadChild("/scenes/worldscape/gui/pause/menu.json", false)).asUInt64() ); + uf::Serializer& metadata = gui->getComponent(); + metadata["menu"] = json["menu"]; + gui->initialize(); + return payload; + }); + this->addHook( "world:Entity.LoadAsset", [&](const std::string& event)->std::string{ + uf::Serializer json = event; + + std::string asset = json["asset"].asString(); + std::string uid = json["uid"].asString(); + + assetLoader.load(asset, "asset:Load." + uid); + + return "true"; + }); + /* store viewport size */ { + metadata["window"]["size"]["x"] = uf::renderer::width; + metadata["window"]["size"]["y"] = uf::renderer::height; + + this->addHook( "window:Resized", [&](const std::string& event)->std::string{ + uf::Serializer json = event; + + pod::Vector2ui size; { + size.x = json["window"]["size"]["x"].asUInt64(); + size.y = json["window"]["size"]["y"].asUInt64(); + } + + metadata["window"] = json["window"]; + + return "true"; + }); + } + + // lock control + { + uf::Serializer payload; + payload["state"] = false; + uf::hooks.call("window:Mouse.CursorVisibility", payload); + uf::hooks.call("window:Mouse.Lock"); + } +} +void ext::Scene::tick() { + uf::Scene::tick(); + + uf::Serializer& metadata = this->getComponent(); + uf::Asset& assetLoader = this->getComponent(); + + /* check if audio needs to loop */ try { + uf::Audio& bgm = this->getComponent(); + float current = bgm.getTime(); + float end = bgm.getDuration(); + float epsilon = 0.005f; + if ( current + epsilon >= end || !bgm.playing() ) { + // intro to main transition + std::string filename = bgm.getFilename(); + filename = assetLoader.getOriginal(filename); + if ( filename.find("_intro") != std::string::npos ) { + assetLoader.load(uf::string::replace( filename, "_intro", "" ), "asset:Load." + std::to_string(this->getUid())); + // loop + } else { + bgm.setTime(0); + if ( !bgm.playing() ) bgm.play(); + } + } + } catch ( ... ) { + + } + + /* Regain control if nothing requests it */ { + ext::Gui* menu = (ext::Gui*) this->findByName("Gui: Menu"); + if ( !menu ) { + uf::Serializer payload; + payload["state"] = false; + uf::hooks.call("window:Mouse.CursorVisibility", payload); + uf::hooks.call("window:Mouse.Lock"); + } + } + + /* Print Entity Information */ { + static uf::Timer timer(false); + if ( !timer.running() ) timer.start(); + if ( uf::Window::isKeyPressed("U") && timer.elapsed().asDouble() >= 1 ) { timer.reset(); + auto& allocations = uf::Entity::memoryPool.allocations(); + uf::iostream << "Current size: " << allocations.size() << " | UIDs: " << uf::Entity::uids << "\n"; + uint orphans = 0; + uint empty = 0; + for ( auto& allocation : allocations ) { + uf::Entity* e = (uf::Entity*) allocation.pointer; + if ( !e->hasParent() ) { + ++orphans; + uf::iostream << "Orphan: " << e->getName() << ": " << e << "\n"; + } + } + uf::iostream << "Orphans: " << orphans << "\n"; + uf::iostream << "Empty: " << empty << "\n"; + } + } + + /* Updates Sound Listener */ { + auto& controller = this->getController(); + auto& transform = controller.getComponent>(); + + ext::oal.listener( "POSITION", { transform.position.x, transform.position.y, transform.position.z } ); + ext::oal.listener( "VELOCITY", { 0, 0, 0 } ); + ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } ); + } + + if ( uf::scene::getCurrentScene().getUid() == this->getUid() ) { + /* Update lights */ if ( metadata["light"]["should"].asBool() ) { + // if ( !uf::renderer::currentRenderMode || uf::renderer::currentRenderMode->name != "" ) return; + + auto& scene = uf::scene::getCurrentScene(); + + std::vector blitters; + auto& renderMode = uf::renderer::getRenderMode("", true); + bool hasCompute = uf::renderer::hasRenderMode("C:RT:" + std::to_string(this->getUid()), true); + if ( hasCompute ) { + // auto& renderMode = uf::renderer::getRenderMode("C:RT:" + std::to_string(this->getUid()), true); + // auto* renderModePointer = (uf::renderer::ComputeRenderMode*) &renderMode; + // if ( renderModePointer->compute.initialized ) { + // blitters.push_back(&renderModePointer->compute); + // } else { + // hasCompute = false; + // } + } else if ( renderMode.getType() == "Deferred (Stereoscopic)" ) { + auto* renderModePointer = (uf::renderer::StereoscopicDeferredRenderMode*) &renderMode; + blitters.push_back(&renderModePointer->blitters.left); + blitters.push_back(&renderModePointer->blitters.right); + } else if ( renderMode.getType() == "Deferred" ) { + auto* renderModePointer = (uf::renderer::DeferredRenderMode*) &renderMode; + blitters.push_back(&renderModePointer->blitter); + } + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); + + // 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 { + alignas(8) pod::Vector2f range; + alignas(16) pod::Vector4f color; + } fog; + 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 = 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(); + } + + 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(); + } + { + uniforms->fog.color.x = metadata["light"]["fog"]["color"][0].asFloat(); + uniforms->fog.color.y = metadata["light"]["fog"]["color"][1].asFloat(); + uniforms->fog.color.z = metadata["light"]["fog"]["color"][2].asFloat(); + + uniforms->fog.range.x = metadata["light"]["fog"]["range"][0].asFloat(); + uniforms->fog.range.y = metadata["light"]["fog"]["range"][1].asFloat(); + } + { + std::vector entities; + std::function filter = [&]( uf::Entity* entity ) { + if ( !entity || entity->getName() != "Light" ) return; + entities.push_back(entity); + }; + for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue; + scene->process(filter); + } + { + const pod::Vector3& position = controller.getComponent>().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>() ) return false; if ( !r->hasComponent>() ) return true; + return uf::vector::magnitude( uf::vector::subtract( l->getComponent>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent>().position, position ) ); + } ); + } + + { + uf::Serializer& metadata = controller.getComponent(); + 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>(); + uf::Serializer& metadata = entity->getComponent(); + uf::Camera& camera = entity->getComponent(); + + 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"]["radius"][1].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"]["power"].asFloat(); + + light.type.x = metadata["light"]["type"].asUInt64(); + light.type.y = metadata["light"]["shadows"]["enabled"].asBool(); + + if ( !hasCompute && entity->hasComponent() ) { + auto& renderMode = entity->getComponent(); + auto& renderTarget = renderMode.renderTarget; + + uint8_t i = 0; + for ( auto& attachment : renderTarget.attachments ) { + if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; + // if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; + if ( (attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) ) 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 ext::Scene::render() { + uf::Scene::render(); +} +void ext::Scene::destroy() { + uf::Scene::destroy(); +} \ No newline at end of file diff --git a/ext/scenes/base.h b/ext/scenes/base.h new file mode 100644 index 00000000..b83c69a1 --- /dev/null +++ b/ext/scenes/base.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include +#include + +namespace ext { + class EXT_API Scene : public uf::Scene { + public: + virtual void initialize(); + virtual void tick(); + virtual void render(); + virtual void destroy(); + }; +} \ No newline at end of file diff --git a/ext/scenes/map/behavior_test.cpp b/ext/scenes/map/behavior_test.cpp new file mode 100644 index 00000000..7fbbb218 --- /dev/null +++ b/ext/scenes/map/behavior_test.cpp @@ -0,0 +1,35 @@ +#include "behavior_test.h" + +#include + +#define this (&self) +void ext::TestBehavior::attach( uf::Object& self ) { + self.addBehavior({ + .type = uf::Behaviors::getType(), + .initialize = [&]() { + ext::TestBehavior::initialize( self ); + }, + .tick = [&]() { + ext::TestBehavior::tick( self ); + }, + .render = [&]() { + ext::TestBehavior::render( self ); + }, + .destroy = [&]() { + ext::TestBehavior::destroy( self ); + }, + }); +} +void ext::TestBehavior::initialize( uf::Object& self ) { + +} +void ext::TestBehavior::tick( uf::Object& self ) { + +} +void ext::TestBehavior::render( uf::Object& self ) { + +} +void ext::TestBehavior::destroy( uf::Object& self ) { + +} +#undef this \ No newline at end of file diff --git a/ext/scenes/map/behavior_test.h b/ext/scenes/map/behavior_test.h new file mode 100644 index 00000000..2fec26ff --- /dev/null +++ b/ext/scenes/map/behavior_test.h @@ -0,0 +1,15 @@ +#pragma once + +#include "../base.h" + +namespace ext { + class EXT_API TestBehavior { + public: + static void attach( uf::Object& ); + + static void initialize( uf::Object& ); + static void tick( uf::Object& ); + static void render( uf::Object& ); + static void destroy( uf::Object& ); + }; +} \ No newline at end of file diff --git a/ext/scenes/map/scene.cpp b/ext/scenes/map/scene.cpp index eaafddae..7436876d 100644 --- a/ext/scenes/map/scene.cpp +++ b/ext/scenes/map/scene.cpp @@ -22,104 +22,30 @@ #include "../../ext.h" #include "../../gui/gui.h" +#include "behavior_test.h" + EXT_OBJECT_REGISTER_CPP(TestScene_Map) void ext::TestScene_Map::initialize() { - uf::Scene::initialize(); - uf::Serializer& metadata = this->getComponent(); - uf::Asset& assetLoader = this->getComponent(); + ext::Scene::initialize(); - this->addHook( "system:Quit.%UID%", [&](const std::string& event)->std::string{ - std::cout << event << std::endl; - ext::ready = false; - return "true"; - }); { - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); - this->addHook( "world:Entity.LoadAsset", [&](const std::string& event)->std::string{ - uf::Serializer json = event; + uf::Object* object = new uf::Object; + this->addChild(*object); + ext::TestBehavior::attach( *object ); - std::string asset = json["asset"].asString(); - std::string uid = json["uid"].asString(); - - assetLoader.load(asset, "asset:Load." + uid); - - return "true"; - }); - } - { - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); - this->addHook( "menu:Pause", [&](const std::string& event)->std::string{ - if ( timer.elapsed().asDouble() < 1 ) return "false"; - timer.reset(); - - uf::Serializer json = event; - ext::Gui* manager = (ext::Gui*) this->findByName("Gui Manager"); - if ( !manager ) return "false"; - uf::Serializer payload; - ext::Gui* gui = (ext::Gui*) manager->findByUid( (payload["uid"] = manager->loadChild("/scenes/worldscape/gui/pause/menu.json", false)).asUInt64() ); - uf::Serializer& metadata = gui->getComponent(); - metadata["menu"] = json["menu"]; - gui->initialize(); - return payload; - }); - } - - /* store viewport size */ { - metadata["window"]["size"]["x"] = uf::renderer::width; - metadata["window"]["size"]["y"] = uf::renderer::height; - - this->addHook( "window:Resized", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - pod::Vector2ui size; { - size.x = json["window"]["size"]["x"].asUInt64(); - size.y = json["window"]["size"]["y"].asUInt64(); - } - - metadata["window"] = json["window"]; - - return "true"; - }); - } - - // lock control - { - uf::Serializer payload; - payload["state"] = true; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); + object->initialize(); } } void ext::TestScene_Map::render() { - uf::Scene::render(); + ext::Scene::render(); } void ext::TestScene_Map::tick() { - uf::Scene::tick(); + ext::Scene::tick(); uf::Serializer& metadata = this->getComponent(); uf::Asset& assetLoader = this->getComponent(); - /* Regain control if nothing requests it */ { - ext::Gui* menu = (ext::Gui*) this->findByName("Gui: Menu"); - if ( !menu ) { - uf::Serializer payload; - payload["state"] = false; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } - } - - /* Updates Sound Listener */ { - pod::Transform<>& transform = this->getController()->getComponent>(); - - ext::oal.listener( "POSITION", { transform.position.x, transform.position.y, transform.position.z } ); - ext::oal.listener( "VELOCITY", { 0, 0, 0 } ); - ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } ); - } - /* Collision */ { bool local = false; bool sort = false; diff --git a/ext/scenes/map/scene.h b/ext/scenes/map/scene.h index 7d8d6569..e683bec0 100644 --- a/ext/scenes/map/scene.h +++ b/ext/scenes/map/scene.h @@ -1,12 +1,9 @@ #pragma once -#include -#include -#include -#include +#include "../base.h" namespace ext { - class EXT_API TestScene_Map : public uf::Scene { + class EXT_API TestScene_Map : public ext::Scene { public: virtual void initialize(); virtual void tick(); diff --git a/ext/scenes/marchingcubes/scene.cpp b/ext/scenes/marchingcubes/scene.cpp index 5edd9f70..131e11ca 100644 --- a/ext/scenes/marchingcubes/scene.cpp +++ b/ext/scenes/marchingcubes/scene.cpp @@ -22,101 +22,14 @@ EXT_OBJECT_REGISTER_CPP(TestScene_MarchingCubes) void ext::TestScene_MarchingCubes::initialize() { - uf::Scene::initialize(); - uf::Serializer& metadata = this->getComponent(); - uf::Asset& assetLoader = this->getComponent(); - - this->addHook( "system:Quit.%UID%", [&](const std::string& event)->std::string{ - std::cout << event << std::endl; - ext::ready = false; - return "true"; - }); - { - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); - this->addHook( "world:Entity.LoadAsset", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - std::string asset = json["asset"].asString(); - std::string uid = json["uid"].asString(); - - assetLoader.load(asset, "asset:Load." + uid); - - return "true"; - }); - } - { - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); - this->addHook( "menu:Pause", [&](const std::string& event)->std::string{ - if ( timer.elapsed().asDouble() < 1 ) return "false"; - timer.reset(); - - uf::Serializer json = event; - ext::Gui* manager = (ext::Gui*) this->findByName("Gui Manager"); - if ( !manager ) return "false"; - uf::Serializer payload; - ext::Gui* gui = (ext::Gui*) manager->findByUid( (payload["uid"] = manager->loadChild("/scenes/worldscape/gui/pause/menu.json", false)).asUInt64() ); - uf::Serializer& metadata = gui->getComponent(); - metadata["menu"] = json["menu"]; - gui->initialize(); - return payload; - }); - } - - /* store viewport size */ { - metadata["window"]["size"]["x"] = uf::renderer::width; - metadata["window"]["size"]["y"] = uf::renderer::height; - - this->addHook( "window:Resized", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - pod::Vector2ui size; { - size.x = json["window"]["size"]["x"].asUInt64(); - size.y = json["window"]["size"]["y"].asUInt64(); - } - - metadata["window"] = json["window"]; - - return "true"; - }); - } - - // lock control - { - uf::Serializer payload; - payload["state"] = true; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } + ext::Scene::initialize(); } void ext::TestScene_MarchingCubes::render() { - uf::Scene::render(); + ext::Scene::render(); } void ext::TestScene_MarchingCubes::tick() { - uf::Scene::tick(); - - uf::Serializer& metadata = this->getComponent(); - uf::Asset& assetLoader = this->getComponent(); - - /* Regain control if nothing requests it */ { - ext::Gui* menu = (ext::Gui*) this->findByName("Gui: Menu"); - if ( !menu ) { - uf::Serializer payload; - payload["state"] = false; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } - } - - /* Updates Sound Listener */ { - pod::Transform<>& transform = this->getController()->getComponent>(); - - ext::oal.listener( "POSITION", { transform.position.x, transform.position.y, transform.position.z } ); - ext::oal.listener( "VELOCITY", { 0, 0, 0 } ); - ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } ); - } + ext::Scene::tick(); /* Collision */ { bool local = false; diff --git a/ext/scenes/marchingcubes/scene.h b/ext/scenes/marchingcubes/scene.h index 453cdbef..e698af6c 100644 --- a/ext/scenes/marchingcubes/scene.h +++ b/ext/scenes/marchingcubes/scene.h @@ -1,12 +1,9 @@ #pragma once -#include -#include -#include -#include +#include "../base.h" namespace ext { - class EXT_API TestScene_MarchingCubes : public uf::Scene { + class EXT_API TestScene_MarchingCubes : public ext::Scene { public: virtual void initialize(); virtual void tick(); diff --git a/ext/scenes/marchingcubes/terrain/heightmap.cpp b/ext/scenes/marchingcubes/terrain/heightmap.cpp index 13409f03..f3eea618 100644 --- a/ext/scenes/marchingcubes/terrain/heightmap.cpp +++ b/ext/scenes/marchingcubes/terrain/heightmap.cpp @@ -121,10 +121,10 @@ void ext::Heightmap::render() { /* Update uniforms */ if ( this->hasComponent() ) { auto& mesh = this->getComponent(); auto& graphic = this->getComponent(); - auto& root = this->getRootParent(); - auto& player = *root.getController(); - auto& camera = player.getComponent(); - auto& transform = player.getComponent>(); + auto& scene = uf::scene::getCurrentScene(); + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); + auto& transform = controller.getComponent>(); auto& model = this->getComponent>(); if ( !graphic.initialized ) return; uf::Serializer& metadata = this->getComponent(); diff --git a/ext/scenes/marchingcubes/terrain/marching.cpp b/ext/scenes/marchingcubes/terrain/marching.cpp index db94bcd9..e4bada95 100644 --- a/ext/scenes/marchingcubes/terrain/marching.cpp +++ b/ext/scenes/marchingcubes/terrain/marching.cpp @@ -517,9 +517,9 @@ void ext::Marching::render() { /* Update uniforms */ if ( this->hasComponent() ) { auto& mesh = this->getComponent(); auto& graphic = this->getComponent(); - auto& root = this->getRootParent(); - auto& player = *root.getController(); - auto& camera = player.getComponent(); + auto& scene = uf::scene::getCurrentScene(); + auto& controller = scene.getController(); + auto& camera = controller.getComponent(); auto& transform = this->getComponent>(); auto& model = this->getComponent>(); if ( !graphic.initialized ) return; diff --git a/ext/scenes/raytrace/scene.cpp b/ext/scenes/raytrace/scene.cpp index ddfba573..30b65be6 100644 --- a/ext/scenes/raytrace/scene.cpp +++ b/ext/scenes/raytrace/scene.cpp @@ -23,7 +23,7 @@ EXT_OBJECT_REGISTER_CPP(TestScene_RayTracing) void ext::TestScene_RayTracing::initialize() { - uf::Scene::initialize(); + ext::Scene::initialize(); uf::Serializer& metadata = this->getComponent(); uf::Asset& assetLoader = this->getComponent(); @@ -72,84 +72,20 @@ void ext::TestScene_RayTracing::initialize() { ); } } - - this->addHook( "system:Quit.%UID%", [&](const std::string& event)->std::string{ - std::cout << event << std::endl; - ext::ready = false; - return "true"; - }); - { - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); - this->addHook( "world:Entity.LoadAsset", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - std::string asset = json["asset"].asString(); - std::string uid = json["uid"].asString(); - - assetLoader.load(asset, "asset:Load." + uid); - - return "true"; - }); - } - { - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); - this->addHook( "menu:Pause", [&](const std::string& event)->std::string{ - if ( timer.elapsed().asDouble() < 1 ) return "false"; - timer.reset(); - - uf::Serializer json = event; - ext::Gui* manager = (ext::Gui*) this->findByName("Gui Manager"); - if ( !manager ) return "false"; - uf::Serializer payload; - ext::Gui* gui = (ext::Gui*) manager->findByUid( (payload["uid"] = manager->loadChild("/scenes/worldscape/gui/pause/menu.json", false)).asUInt64() ); - uf::Serializer& metadata = gui->getComponent(); - metadata["menu"] = json["menu"]; - gui->initialize(); - return payload; - }); - } - - /* store viewport size */ { - metadata["window"]["size"]["x"] = uf::renderer::width; - metadata["window"]["size"]["y"] = uf::renderer::height; - - this->addHook( "window:Resized", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - pod::Vector2ui size; { - size.x = json["window"]["size"]["x"].asUInt64(); - size.y = json["window"]["size"]["y"].asUInt64(); - } - - metadata["window"] = json["window"]; - - return "true"; - }); - } - - // lock control - { - uf::Serializer payload; - payload["state"] = true; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } } void ext::TestScene_RayTracing::render() { - uf::Scene::render(); + ext::Scene::render(); } void ext::TestScene_RayTracing::destroy() { if ( this->hasComponent() ) { auto& renderMode = this->getComponent(); uf::renderer::removeRenderMode( &renderMode, false ); } - uf::Scene::destroy(); + ext::Scene::destroy(); } void ext::TestScene_RayTracing::tick() { - uf::Scene::tick(); + ext::Scene::tick(); uf::Serializer& metadata = this->getComponent(); uf::Asset& assetLoader = this->getComponent(); @@ -160,6 +96,10 @@ void ext::TestScene_RayTracing::tick() { struct UniformDescriptor { alignas(16) pod::Matrix4f matrices[2]; alignas(16) pod::Vector4f ambient; + struct { + alignas(8) pod::Vector2f range; + alignas(16) pod::Vector4f color; + } fog; struct Light { alignas(16) pod::Vector4f position; alignas(16) pod::Vector4f color; @@ -177,8 +117,22 @@ void ext::TestScene_RayTracing::tick() { auto& shader = renderMode.compute.material.shaders.front(); specializationConstants = shader.specializationConstants.get(); + struct PushConstant { + uint32_t marchingSteps; + uint32_t rayBounces; + float shadowFactor; + float reflectionStrength; + float reflectionFalloff; + }; + auto& pushConstant = shader.pushConstants.front().get(); + pushConstant.marchingSteps = metadata["rays"]["marching steps"].asUInt64(); + pushConstant.rayBounces = metadata["rays"]["ray bounces"].asUInt64(); + pushConstant.shadowFactor = metadata["rays"]["shadow factor"].asFloat(); + pushConstant.reflectionStrength = metadata["rays"]["reflection"]["strength"].asFloat(); + pushConstant.reflectionFalloff = metadata["rays"]["reflection"]["falloff"].asFloat(); + auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& camera = controller.getComponent(); auto& transform = controller.getComponent>(); @@ -190,8 +144,20 @@ void ext::TestScene_RayTracing::tick() { uniforms->matrices[i] = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ); } - // uniforms->lights.position = { 0, 0, 0, 32 }; - // uniforms->lights.color = { 1, 1, 1, 1 }; + { + 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(); + } + { + uniforms->fog.color.x = metadata["light"]["fog"]["color"][0].asFloat(); + uniforms->fog.color.y = metadata["light"]["fog"]["color"][1].asFloat(); + uniforms->fog.color.z = metadata["light"]["fog"]["color"][2].asFloat(); + + uniforms->fog.range.x = metadata["light"]["fog"]["range"][0].asFloat(); + uniforms->fog.range.y = metadata["light"]["fog"]["range"][1].asFloat(); + } std::vector entities; std::function filter = [&]( uf::Entity* entity ) { @@ -229,7 +195,7 @@ void ext::TestScene_RayTracing::tick() { if ( entity == &controller ) light.position.y += 2; - light.position.w = metadata["light"]["radius"].asFloat(); + light.position.w = metadata["light"]["radius"][1].asFloat(); light.color.x = metadata["light"]["color"][0].asFloat(); light.color.y = metadata["light"]["color"][1].asFloat(); @@ -243,23 +209,6 @@ void ext::TestScene_RayTracing::tick() { } } #endif - /* Regain control if nothing requests it */ { - ext::Gui* menu = (ext::Gui*) this->findByName("Gui: Menu"); - if ( !menu ) { - uf::Serializer payload; - payload["state"] = false; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } - } - - /* Updates Sound Listener */ { - pod::Transform<>& transform = this->getController()->getComponent>(); - - ext::oal.listener( "POSITION", { transform.position.x, transform.position.y, transform.position.z } ); - ext::oal.listener( "VELOCITY", { 0, 0, 0 } ); - ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } ); - } /* Collision */ { bool local = false; diff --git a/ext/scenes/raytrace/scene.h b/ext/scenes/raytrace/scene.h index 13cc7e39..53fc960a 100644 --- a/ext/scenes/raytrace/scene.h +++ b/ext/scenes/raytrace/scene.h @@ -1,12 +1,9 @@ #pragma once -#include -#include -#include -#include +#include "../base.h" namespace ext { - class EXT_API TestScene_RayTracing : public uf::Scene { + class EXT_API TestScene_RayTracing : public ext::Scene { public: virtual void initialize(); virtual void tick(); diff --git a/ext/scenes/start/menu.cpp b/ext/scenes/start/menu.cpp index db2bf75a..6f4308d8 100644 --- a/ext/scenes/start/menu.cpp +++ b/ext/scenes/start/menu.cpp @@ -19,124 +19,25 @@ #include "../../gui/gui.h" namespace { - uf::Object controller; - ext::Gui* circleIn; ext::Gui* circleOut; } -uf::Entity* ext::StartMenu::getController() { - return (uf::Entity*) &controller; +uf::Entity& ext::StartMenu::getController() { + return *this; } -const uf::Entity* ext::StartMenu::getController() const { - return (uf::Entity*) &controller; +const uf::Entity& ext::StartMenu::getController() const { + return *this; } EXT_OBJECT_REGISTER_CPP(StartMenu) void ext::StartMenu::initialize() { - uf::Scene::initialize(); + ext::Scene::initialize(); this->m_name = "Main Menu"; -// this->load("./scenes/start/scene.json"); + uf::Serializer& metadata = this->getComponent(); uf::Asset& assetLoader = this->getComponent(); - this->addHook( "system:Quit.%UID%", [&](const std::string& event)->std::string{ - std::cout << event << std::endl; - ext::ready = false; - return "true"; - }); - this->addHook( "world:Music.LoadPrevious.%UID%", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - if ( metadata["previous bgm"]["filename"] == "" ) return "false"; - - std::string filename = metadata["previous bgm"]["filename"].asString(); - float timestamp = metadata["previous bgm"]["timestamp"].asFloat(); - -// std::cout << metadata["previous bgm"] << std::endl; - - uf::Audio& audio = this->getComponent(); - if ( audio.playing() ) { - metadata["previous bgm"]["filename"] = audio.getFilename(); - metadata["previous bgm"]["timestamp"] = audio.getTime(); - audio.stop(); - } - audio.load(filename); - audio.setVolume(metadata["volumes"]["bgm"].asFloat()); - audio.setTime(timestamp); - audio.play(); - - 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(filename); } catch ( ... ) {} - if ( !audioPointer ) return "false"; - - uf::Audio& audio = this->getComponent(); - 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 timer(false); - if ( !timer.running() ) timer.start(); - - this->addHook( "world:Entity.LoadAsset", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - std::string asset = json["asset"].asString(); - std::string uid = json["uid"].asString(); - - assetLoader.load(asset, "asset:Load." + uid); - - return "true"; - }); - - /* store viewport size */ { - metadata["window"]["size"]["x"] = uf::renderer::width; - metadata["window"]["size"]["y"] = uf::renderer::height; - - this->addHook( "window:Resized", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - pod::Vector2ui size; { - size.x = json["window"]["size"]["x"].asUInt64(); - size.y = json["window"]["size"]["y"].asUInt64(); - } - - metadata["window"] = json["window"]; - - return "true"; - }); - } - - // lock control - { - uf::Serializer payload; - payload["state"] = true; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } - /* Magic Circle Outter */ { circleOut = (ext::Gui*) this->findByUid( this->loadChild("./gui/mainmenu/circle-out.json", true) ); } @@ -145,6 +46,7 @@ void ext::StartMenu::initialize() { } // update camera { + auto& controller = this->getController(); controller.getComponent().update(true); pod::Transform<>& transform = controller.getComponent>(); @@ -155,32 +57,11 @@ void ext::StartMenu::initialize() { } void ext::StartMenu::tick() { - uf::Scene::tick(); + ext::Scene::tick(); uf::Serializer& metadata = this->getComponent(); uf::Asset& assetLoader = this->getComponent(); - /* check if audio needs to loop */ try { - uf::Audio& bgm = this->getComponent(); - float current = bgm.getTime(); - float end = bgm.getDuration(); - float epsilon = 0.005f; - if ( current + epsilon >= end || !bgm.playing() ) { - // intro to main transition - std::string filename = bgm.getFilename(); - filename = assetLoader.getOriginal(filename); - if ( filename.find("_intro") != std::string::npos ) { - assetLoader.load(uf::string::replace( filename, "_intro", "" ), "asset:Load." + std::to_string(this->getUid())); - // loop - } else { - bgm.setTime(0); - if ( !bgm.playing() ) bgm.play(); - } - } - } catch ( ... ) { - - } - if ( circleIn ) { pod::Transform<>& transform = circleIn->getComponent>(); static float time = 0.0f; @@ -224,22 +105,13 @@ void ext::StartMenu::tick() { // metadata["color"][3] = alpha; } - // check on controller position -/* - { - pod::Vector3f position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Right ); - pod::Quaternion<> orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right ); - std::cout << "Right hand:\n"; - std::cout << "\tPosition: " << position.x << ", " << position.y << ", " << position.z << "\n"; - std::cout << "\tOrientation: " << orientation.x << ", " << orientation.y << ", " << orientation.z << ", " << orientation.w << std::endl; - } -*/ { + auto& controller = this->getController(); auto& camera = controller.getComponent(); camera.updateView(); } } void ext::StartMenu::render() { - uf::Scene::render(); + ext::Scene::render(); } \ No newline at end of file diff --git a/ext/scenes/start/menu.h b/ext/scenes/start/menu.h index 58b5337d..bd8ca7d2 100644 --- a/ext/scenes/start/menu.h +++ b/ext/scenes/start/menu.h @@ -1,18 +1,15 @@ #pragma once -#include -#include -#include - -#include +#include "../base.h" namespace ext { - class EXT_API StartMenu : public uf::Scene { + class EXT_API StartMenu : public ext::Scene { public: virtual void initialize(); virtual void tick(); virtual void render(); - virtual uf::Entity* getController(); - virtual const uf::Entity* getController() const; + + virtual uf::Entity& getController(); + virtual const uf::Entity& getController() const; }; } \ No newline at end of file diff --git a/ext/scenes/worldscape/craeture/craeture.cpp b/ext/scenes/worldscape/craeture/craeture.cpp index f812c138..7104b0fa 100644 --- a/ext/scenes/worldscape/craeture/craeture.cpp +++ b/ext/scenes/worldscape/craeture/craeture.cpp @@ -111,7 +111,7 @@ void ext::Craeture::initialize() { if ( filename == "" ) return "false"; uf::Audio& sfx = this->getComponent().add(filename); sfx.setVolume(masterdata["volumes"]["sfx"].asFloat()); - auto& pTransform = world.getController()->getComponent>(); + auto& pTransform = world.getController().getComponent>(); sfx.setPosition( transform.position ); sfx.play(); @@ -169,7 +169,7 @@ void ext::Craeture::tick() { uf::Serializer& metadata = this->getComponent(); uf::Scene& world = uf::scene::getCurrentScene(); - uf::Serializer& pMetadata = world.getController()->getComponent(); + uf::Serializer& pMetadata = world.getController().getComponent(); if ( !pMetadata["system"]["control"].asBool() ) return; diff --git a/ext/scenes/worldscape/gui/pause.cpp b/ext/scenes/worldscape/gui/pause.cpp index 64b45507..89f518a6 100644 --- a/ext/scenes/worldscape/gui/pause.cpp +++ b/ext/scenes/worldscape/gui/pause.cpp @@ -118,7 +118,7 @@ void ext::GuiWorldPauseMenu::initialize() { } /* set sprite order */ { metadata["portraits"]["i"] = 0; - uf::Serializer& pMetadata = scene.getController()->getComponent(); + uf::Serializer& pMetadata = scene.getController().getComponent(); int i = 0; for ( auto& k : pMetadata[""]["party"] ) { std::string id = k.asString(); diff --git a/ext/scenes/worldscape/housamo/sprite.cpp b/ext/scenes/worldscape/housamo/sprite.cpp index 33d7508b..499bcbab 100644 --- a/ext/scenes/worldscape/housamo/sprite.cpp +++ b/ext/scenes/worldscape/housamo/sprite.cpp @@ -132,10 +132,10 @@ void ext::HousamoSprite::render() { ext::Craeture::render(); /* Update uniforms */ if ( this->hasComponent() ) { auto& mesh = this->getComponent(); - auto& scene = this->getRootParent(); + auto& scene = uf::scene::getCurrentScene(); auto& graphic = this->getComponent(); auto& transform = this->getComponent>(); - auto& camera = scene.getController()->getComponent(); + auto& camera = scene.getController().getComponent(); if ( !graphic.initialized ) return; // auto& uniforms = graphic.uniforms(); auto& uniforms = graphic.material.shaders.front().uniforms.front().get(); @@ -147,7 +147,7 @@ void ext::HousamoSprite::render() { /* auto& graphic = this->getComponent(); auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& camera = controller.getComponent(); auto& transform = this->getComponent>(); if ( !graphic.initialized ) return; diff --git a/ext/scenes/worldscape/light/light.cpp b/ext/scenes/worldscape/light/light.cpp index cde7934a..137c7bab 100644 --- a/ext/scenes/worldscape/light/light.cpp +++ b/ext/scenes/worldscape/light/light.cpp @@ -16,16 +16,9 @@ void ext::Light::initialize() { auto& renderMode = this->getComponent(); std::string name = "RT:" + std::to_string((int) this->getUid()); uf::renderer::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(); + auto& controller = scene.getController(); camera = controller.getComponent(); camera.getTransform() = {}; @@ -34,17 +27,37 @@ void ext::Light::initialize() { camera.setFov( metadata["light"]["shadows"]["fov"].asFloat() ); camera.updateProjection(); } + if ( metadata["light"]["radius"].isArray() ) { + auto bounds = camera.getBounds(); + bounds.x = metadata["light"]["radius"][0].asFloat(); + bounds.y = metadata["light"]["radius"][1].asFloat(); + camera.setBounds(bounds); + } + } + if ( metadata["light"]["shadows"]["resolution"].isArray() ) { + renderMode.width = metadata["light"]["shadows"]["resolution"][0].asUInt64(); + renderMode.height = metadata["light"]["shadows"]["resolution"][1].asUInt64(); + auto size = camera.getSize(); + size.x = renderMode.width; + size.y = renderMode.height; + camera.setSize(size); + } else { + renderMode.width = metadata["light"]["shadows"]["resolution"].asUInt64(); + renderMode.height = metadata["light"]["shadows"]["resolution"].asUInt64(); + auto size = camera.getSize(); + size.x = renderMode.width; + size.y = renderMode.height; + camera.setSize(size); } } - if ( !metadata["light"].isArray() ) { + if ( !metadata["light"]["color"].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& metadata = this->getComponent(); if ( this->hasComponent() ) { auto& renderMode = this->getComponent(); renderMode.target = ""; @@ -55,16 +68,86 @@ void ext::Light::tick() { pod::Physics& physics = this->getComponent(); transform = uf::physics::update( transform, physics ); } - { - uf::transform::rotate( transform, {0, 1, 0}, uf::physics::time::delta ); + + auto& parent = this->getParent(); + auto& parentMetadata = parent.getComponent(); + if ( parentMetadata["system"]["type"] == "Light" ) { + metadata["light"] = parentMetadata["light"]; + } else { + if ( metadata["light"]["fade"].isObject() ) { + if ( metadata["light"]["backup"]["power"].isNull() ) { + metadata["light"]["backup"]["power"] = metadata["light"]["power"]; + } + if ( metadata["light"]["backup"]["color"].isNull() ) { + metadata["light"]["backup"]["color"] = metadata["light"]["color"]; + } + // fade towards + int direction = metadata["light"]["fade"]["increment"].asBool() ? 1 : -1; + metadata["light"]["fade"]["timer"] = metadata["light"]["fade"]["timer"].asFloat() + metadata["light"]["fade"]["rate"].asFloat() * uf::physics::time::delta * direction; + + // 0 .. delta .. 1 .. (1 + timeout * 0.5) + + if ( direction == 1 && metadata["light"]["fade"]["timer"].asFloat() >= 0.5f * metadata["light"]["fade"]["timeout"].asFloat() + 1.0f ) { + metadata["light"]["fade"]["increment"] = false; + } else if ( direction == -1 && metadata["light"]["fade"]["timer"].asFloat() <= -0.5f * metadata["light"]["fade"]["timeout"].asFloat() ) { + metadata["light"]["fade"]["increment"] = true; + } + { + float delta = metadata["light"]["fade"]["timer"].asFloat(); + delta = std::clamp( delta, 0.f, 1.f ); + if ( metadata["light"]["fade"]["power"].isNumeric() ) { + metadata["light"]["power"] = std::lerp( metadata["light"]["backup"]["power"].asFloat(), metadata["light"]["fade"]["power"].asFloat(), delta ); + } + if ( metadata["light"]["fade"]["color"].isArray() ) { + pod::Vector3f fadeColor; { + fadeColor.x = metadata["light"]["fade"]["color"][0].asFloat(); + fadeColor.y = metadata["light"]["fade"]["color"][1].asFloat(); + fadeColor.z = metadata["light"]["fade"]["color"][2].asFloat(); + } + pod::Vector3f origColor; { + origColor.x = metadata["light"]["backup"]["color"][0].asFloat(); + origColor.y = metadata["light"]["backup"]["color"][1].asFloat(); + origColor.z = metadata["light"]["backup"]["color"][2].asFloat(); + } + pod::Vector3f color = uf::vector::lerp( origColor, fadeColor, delta ); + + metadata["light"]["color"][0] = color[0]; + metadata["light"]["color"][1] = color[1]; + metadata["light"]["color"][2] = color[2]; + } + } + } + if ( metadata["light"]["flicker"].isObject() ) { + float r = (rand() % 100) / 100.0; + float rate = metadata["light"]["flicker"]["rate"].asFloat(); + if ( metadata["light"]["backup"]["power"].isNull() ) { + metadata["light"]["backup"]["power"] = metadata["light"]["power"]; + } + metadata["light"]["flicker"]["timer"] = metadata["light"]["flicker"]["timer"].asFloat() + uf::physics::time::delta; + if ( metadata["light"]["flicker"]["timer"].asFloat() >= metadata["light"]["flicker"]["timeout"].asFloat() ) { + metadata["light"]["flicker"]["timer"] = 0; + metadata["light"]["power"] = (r > rate) ? metadata["light"]["flicker"]["power"].asFloat() : metadata["light"]["backup"]["power"]; + } + } } - auto& camera = this->getComponent(); - auto& metadata = this->getComponent(); -// if ( metadata["light"]["external update"].isNull() || (!metadata["light"]["external update"].isNull() && !metadata["light"]["external update"].asBool()) ) { + + if ( parentMetadata["system"]["type"] == "Light" ) { + auto& parentTransform = parent.getComponent>(); + transform.position = parentTransform.position; + } else if ( metadata["system"]["track"] == "player" ) { + auto& scene = uf::scene::getCurrentScene(); + auto& controllerCamera = scene.getController().getComponent().getTransform(); + auto& controllerTransform = scene.getController().getComponent>(); + transform.position = controllerTransform.position + controllerCamera.position; + } + if ( metadata["light"]["external update"].isNull() || (!metadata["light"]["external update"].isNull() && !metadata["light"]["external update"].asBool()) ) { + auto& camera = this->getComponent(); for ( std::size_t i = 0; i < 2; ++i ) { camera.setView( uf::matrix::inverse( uf::transform::model( transform ) ), i ); } -// } + } + + uf::Object::tick(); } void ext::Light::render() { uf::Object::render(); diff --git a/ext/scenes/worldscape/player/hands.cpp b/ext/scenes/worldscape/player/hands.cpp index 8d9b13d6..596eabc2 100644 --- a/ext/scenes/worldscape/player/hands.cpp +++ b/ext/scenes/worldscape/player/hands.cpp @@ -181,7 +181,7 @@ void ext::Hands::initialize() { void ext::Hands::tick() { uf::Object::tick(); auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& controllerCamera = controller.getComponent(); auto& controllerTransform = controller.getComponent>(); auto& controllerCameraTransform = controllerCamera.getTransform(); @@ -442,7 +442,7 @@ void ext::Hands::render() { uf::Serializer& metadata = this->getComponent(); auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& camera = controller.getComponent(); pod::Matrix4f playerModel = uf::matrix::identity(); { diff --git a/ext/scenes/worldscape/portal/portal.cpp b/ext/scenes/worldscape/portal/portal.cpp index 7fe479ac..d9f54633 100644 --- a/ext/scenes/worldscape/portal/portal.cpp +++ b/ext/scenes/worldscape/portal/portal.cpp @@ -62,7 +62,7 @@ void ext::Portal::initialize() { auto& camera = this->getComponent(); { auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); // copies camera settings camera = controller.getComponent(); } @@ -88,7 +88,7 @@ void ext::Portal::tick() { renderMode.target = ""; auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& camera = this->getComponent(); auto& metadata = this->getComponent(); /* @@ -128,7 +128,7 @@ void ext::Portal::render() { auto& transform = this->getComponent>(); auto& scene = uf::scene::getCurrentScene(); - auto& controller = *scene.getController(); + auto& controller = scene.getController(); auto& camera = this->getComponent(); auto& controllerCamera = controller.getComponent(); if ( !blitter.initialized ) return; diff --git a/ext/scenes/worldscape/scene.cpp b/ext/scenes/worldscape/scene.cpp index b3ade2b6..a8c35d9f 100644 --- a/ext/scenes/worldscape/scene.cpp +++ b/ext/scenes/worldscape/scene.cpp @@ -29,7 +29,7 @@ EXT_OBJECT_REGISTER_CPP(TestScene_WorldScape) void ext::TestScene_WorldScape::initialize() { - uf::Scene::initialize(); + ext::Scene::initialize(); this->m_name = "World"; // this->load("./scenes/world/scene.json"); @@ -49,89 +49,14 @@ void ext::TestScene_WorldScape::initialize() { metadata["system"]["mastertable"][table] = data.load(table); } } - - this->addHook( "world:Music.LoadPrevious.%UID%", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - if ( metadata["previous bgm"]["filename"] == "" ) return "false"; - - std::string filename = metadata["previous bgm"]["filename"].asString(); - float timestamp = metadata["previous bgm"]["timestamp"].asFloat(); - -// std::cout << metadata["previous bgm"] << std::endl; - - uf::Audio& audio = this->getComponent(); - if ( audio.playing() ) { - metadata["previous bgm"]["filename"] = audio.getFilename(); - metadata["previous bgm"]["timestamp"] = audio.getTime(); - audio.stop(); - } - audio.load(filename); - audio.setVolume(metadata["volumes"]["bgm"].asFloat()); - audio.setTime(timestamp); - audio.play(); - - 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(filename); } catch ( ... ) {} - if ( !audioPointer ) return "false"; - - uf::Audio& audio = this->getComponent(); - 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 timer(false); if ( !timer.running() ) timer.start(); - this->addHook( "menu:Pause", [&](const std::string& event)->std::string{ - if ( timer.elapsed().asDouble() < 1 ) return "false"; - timer.reset(); - - uf::Serializer json = event; - ext::Gui* manager = (ext::Gui*) this->findByName("Gui Manager"); - if ( !manager ) return "false"; - uf::Serializer payload; - ext::Gui* gui = (ext::Gui*) manager->findByUid( (payload["uid"] = manager->loadChild("/scenes/worldscape/gui/pause/menu.json", false)).asUInt64() ); - uf::Serializer& metadata = gui->getComponent(); - metadata["menu"] = json["menu"]; - gui->initialize(); - return payload; - }); - this->addHook( "world:Entity.LoadAsset", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - std::string asset = json["asset"].asString(); - std::string uid = json["uid"].asString(); - - assetLoader.load(asset, "asset:Load." + uid); - - return "true"; - }); + this->addHook( "world:Battle.Prepare", [&](const std::string& event)->std::string{ uf::Serializer json = event; - uf::Entity& player = *this->getController(); + uf::Entity& player = this->getController(); uf::Serializer& pMetadata = player.getComponent(); uf::Serializer payload; @@ -200,109 +125,12 @@ void ext::TestScene_WorldScape::initialize() { return "true"; }); - - /* store viewport size */ { - metadata["window"]["size"]["x"] = uf::renderer::width; - metadata["window"]["size"]["y"] = uf::renderer::height; - - this->addHook( "window:Resized", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - - pod::Vector2ui size; { - size.x = json["window"]["size"]["x"].asUInt64(); - size.y = json["window"]["size"]["y"].asUInt64(); - } - - metadata["window"] = json["window"]; - - return "true"; - }); - } - - // lock control - { - uf::Serializer payload; - payload["state"] = false; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } } void ext::TestScene_WorldScape::tick() { - uf::Scene::tick(); - - uf::Serializer& metadata = this->getComponent(); - uf::Asset& assetLoader = this->getComponent(); - - /* check if audio needs to loop */ try { - uf::Audio& bgm = this->getComponent(); - float current = bgm.getTime(); - float end = bgm.getDuration(); - float epsilon = 0.005f; - if ( current + epsilon >= end || !bgm.playing() ) { - // intro to main transition - std::string filename = bgm.getFilename(); - filename = assetLoader.getOriginal(filename); - if ( filename.find("_intro") != std::string::npos ) { - assetLoader.load(uf::string::replace( filename, "_intro", "" ), "asset:Load." + std::to_string(this->getUid())); - // loop - } else { - bgm.setTime(0); - if ( !bgm.playing() ) bgm.play(); - } - } - } catch ( ... ) { - - } - - /* Regain control if nothing requests it */ { - ext::Gui* menu = (ext::Gui*) this->findByName("Gui: Menu"); - if ( !menu ) { - uf::Serializer payload; - payload["state"] = false; - uf::hooks.call("window:Mouse.CursorVisibility", payload); - uf::hooks.call("window:Mouse.Lock"); - } - } - - /* Print Entity Information */ { - static uf::Timer timer(false); - if ( !timer.running() ) timer.start(); - if ( uf::Window::isKeyPressed("U") && timer.elapsed().asDouble() >= 1 ) { timer.reset(); - auto& allocations = uf::Entity::memoryPool.allocations(); - uf::iostream << "Current size: " << allocations.size() << " | UIDs: " << uf::Entity::uids << "\n"; - uint orphans = 0; - uint empty = 0; - for ( auto& allocation : allocations ) { - uf::Entity* e = (uf::Entity*) allocation.pointer; - if ( !e->hasParent() ) { - ++orphans; - uf::iostream << "Orphan: " << e->getName() << ": " << e << "\n"; - } - } - /* - for ( uf::Entity* e : uf::Entity::entities ) { - if ( e && !e->hasParent() ) { - ++orphans; - uf::iostream << "Orphan: " << e->getName() << ": " << e << "\n"; - } - if ( !e ) ++empty; - } - */ - uf::iostream << "Orphans: " << orphans << "\n"; - uf::iostream << "Empty: " << empty << "\n"; - } - } - - /* Updates Sound Listener */ { - pod::Transform<>& transform = this->getController()->getComponent>(); - - ext::oal.listener( "POSITION", { transform.position.x, transform.position.y, transform.position.z } ); - ext::oal.listener( "VELOCITY", { 0, 0, 0 } ); - ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } ); - } + ext::Scene::tick(); } void ext::TestScene_WorldScape::render() { - uf::Scene::render(); + ext::Scene::render(); } \ No newline at end of file diff --git a/ext/scenes/worldscape/scene.h b/ext/scenes/worldscape/scene.h index 8538ac58..fc5a2e31 100644 --- a/ext/scenes/worldscape/scene.h +++ b/ext/scenes/worldscape/scene.h @@ -1,13 +1,9 @@ #pragma once -#include -#include -#include - -#include +#include "../base.h" namespace ext { - class EXT_API TestScene_WorldScape : public uf::Scene { + class EXT_API TestScene_WorldScape : public ext::Scene { public: virtual void initialize(); virtual void tick(); diff --git a/ext/scenes/worldscape/terrain/region.cpp b/ext/scenes/worldscape/terrain/region.cpp index a233f8de..9a7e51da 100644 --- a/ext/scenes/worldscape/terrain/region.cpp +++ b/ext/scenes/worldscape/terrain/region.cpp @@ -433,10 +433,10 @@ void ext::Region::render( ) { if ( !metadata["region"]["rasterized"].asBool() ) return; /* Update uniforms */ if ( this->hasComponent() ) { - auto& scene = this->getRootParent(); + auto& scene = uf::scene::getCurrentScene(); auto& mesh = this->getComponent(); auto& graphic = this->getComponent(); - auto& camera = scene.getController()->getComponent(); + auto& camera = scene.getController().getComponent(); if ( !graphic.initialized ) return; // auto& uniforms = graphic.uniforms(); auto& uniforms = graphic.material.shaders.front().uniforms.front().get(); diff --git a/ext/scenes/worldscape/terrain/terrain.cpp b/ext/scenes/worldscape/terrain/terrain.cpp index 6d27cd99..5fa2411e 100644 --- a/ext/scenes/worldscape/terrain/terrain.cpp +++ b/ext/scenes/worldscape/terrain/terrain.cpp @@ -100,8 +100,8 @@ void ext::Terrain::initialize() { void ext::Terrain::tick() { uf::Object::tick(); - uf::Scene& root = this->getRootParent(); - uf::Object& controller = root.getController(); + auto& scene = uf::scene::getCurrentScene(); + uf::Object& controller = scene.getController(); uf::Serializer& metadata = this->getComponent(); pod::Thread& mainThread = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, true ); // lambda to transition from a resolving state @@ -132,7 +132,7 @@ void ext::Terrain::tick() { }; // generate initial terrain if ( metadata["system"]["state"] == "preinit" ) { - uf::Entity* controller = root.findByName("Player"); + uf::Entity* controller = scene.findByName("Player"); if ( controller ) { transitionState(*this, "initialize", true); this->generate(true); @@ -415,9 +415,9 @@ void ext::Terrain::render() { } void ext::Terrain::relocateChildren() { - uf::Scene& root = this->getRootParent(); + uf::Scene& scene = uf::scene::getCurrentScene(); std::vector entities; - root.process( [&]( uf::Entity* entity ) { + scene.process( [&]( uf::Entity* entity ) { if ( !entity || entity->getUid() == 0 ) return; uf::Serializer& metadata = entity->getComponent(); if ( metadata["region"].isObject() && metadata["region"]["track"].asBool() ) { @@ -485,7 +485,7 @@ bool ext::Terrain::exists( const pod::Vector3i& position ) const { bool ext::Terrain::inBounds( const pod::Vector3i& position ) const { const uf::Scene& scene = uf::scene::getCurrentScene(); - const pod::Transform<>& player = scene.getController()->getComponent>(); + const pod::Transform<>& player = scene.getController().getComponent>(); const uf::Serializer& metadata = this->getComponent(); pod::Vector3ui size = { metadata["region"]["size"][0].asUInt(), @@ -521,7 +521,7 @@ void ext::Terrain::generate( bool single ) { }; uf::Scene& scene = uf::scene::getCurrentScene(); - const pod::Transform<>& player = scene.getController()->getComponent>(); + const pod::Transform<>& player = scene.getController().getComponent>(); pod::Vector3i location = { (int) player.position.x / size.x, (int) player.position.y / size.y,