Commit for 2021.03.14.7z
This commit is contained in:
parent
63ab2a5584
commit
7cae094543
2
Makefile
2
Makefile
@ -43,7 +43,7 @@ ifneq (,$(findstring win64,$(ARCH)))
|
||||
FLAGS +=
|
||||
DEPS += -lgdi32
|
||||
else ifneq (,$(findstring dreamcast,$(ARCH)))
|
||||
REQ_DEPS += opengl gldc json:nlohmann bullet lua # freetype png meshoptimizer ogg openal draco luajit ultralight-ux ncurses curl openvr discord
|
||||
REQ_DEPS += opengl gldc json:nlohmann bullet lua freetype png # meshoptimizer ogg openal draco luajit ultralight-ux ncurses curl openvr discord
|
||||
endif
|
||||
ifneq (,$(findstring vulkan,$(REQ_DEPS)))
|
||||
FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN
|
||||
|
||||
@ -250,23 +250,23 @@ float random(vec3 seed, int i){
|
||||
return fract(sin(dot_product) * 43758.5453);
|
||||
}
|
||||
|
||||
float shadowFactor( Light light, uint shadowMap ) {
|
||||
float shadowFactor( Light light, uint shadowMap, float def ) {
|
||||
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
|
||||
positionClip.xyz /= positionClip.w;
|
||||
|
||||
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.x < -1 || positionClip.x >= 1 ) return def; //0.0;
|
||||
if ( positionClip.y < -1 || positionClip.y >= 1 ) return def; //0.0;
|
||||
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return def; //0.0;
|
||||
|
||||
float factor = 1.0;
|
||||
|
||||
// spot light
|
||||
if ( light.type == 2 || light.type == 3 ) {
|
||||
if ( light.type == 1 || light.type == 2 ) {
|
||||
float dist = length( positionClip.xy );
|
||||
if ( dist > 0.5 ) return 0.0;
|
||||
if ( dist > 0.5 ) return def; //0.0;
|
||||
|
||||
// spot light with attenuation
|
||||
if ( light.type == 3 ) {
|
||||
if ( light.type == 2 ) {
|
||||
factor = 1.0 - (pow(dist * 2,2.0));
|
||||
}
|
||||
}
|
||||
@ -578,7 +578,7 @@ float mipLevel( in vec2 uv ) {
|
||||
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
|
||||
}
|
||||
bool validTextureIndex( int textureIndex ) {
|
||||
return 0 <= textureIndex && textureIndex < ubo.textures;
|
||||
return 0 <= textureIndex; // && textureIndex < ubo.textures;
|
||||
}
|
||||
vec4 resolve( subpassInputMS t ) {
|
||||
int samples = int(ubo.msaa);
|
||||
@ -698,30 +698,25 @@ void main() {
|
||||
bool useLightmap = 0 <= material.indexLightmap;
|
||||
if ( useLightmap ) {
|
||||
fragColor = C.rgb + ubo.ambient.rgb;
|
||||
} else {
|
||||
fragColor = C.rgb * ubo.ambient.rgb * AO;
|
||||
} {
|
||||
/*
|
||||
fragColor = C.rgb + ubo.ambient.rgb;
|
||||
float factor = 0.0;
|
||||
int total = 0;
|
||||
/*
|
||||
float totalShadows = 0.0;
|
||||
float totalLights = 0.0;
|
||||
|
||||
for ( uint i = 0; i < ubo.lights; ++i ) {
|
||||
Light light = lights[i];
|
||||
|
||||
if ( light.power <= 0.001 ) continue;
|
||||
if ( !validTextureIndex(light.mapIndex) ) continue;
|
||||
|
||||
vec3 lightPositionWorld = light.position.xyz;
|
||||
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
|
||||
factor += (1 - shadowFactor( light, light.mapIndex, 1.0 )) * 3;
|
||||
++total;
|
||||
}
|
||||
if ( total > 0 ) {
|
||||
float darken = 1 - factor / total;
|
||||
fragColor *= darken;
|
||||
++totalLights;
|
||||
if ( !validTextureIndex(light.mapIndex) ) continue;
|
||||
totalShadows += shadowFactor( light, light.mapIndex, 1.0 );
|
||||
}
|
||||
fragColor = vec3(totalShadows / totalLights);
|
||||
*/
|
||||
} else {
|
||||
fragColor = C.rgb * ubo.ambient.rgb * AO;
|
||||
*/
|
||||
for ( uint i = 0; i < ubo.lights; ++i ) {
|
||||
Light light = lights[i];
|
||||
|
||||
@ -731,7 +726,7 @@ void main() {
|
||||
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
|
||||
|
||||
if ( validTextureIndex(light.mapIndex) ) {
|
||||
float factor = shadowFactor( light, light.mapIndex );
|
||||
float factor = shadowFactor( light, light.mapIndex, 0.0 );
|
||||
light.power *= factor;
|
||||
litFactor += light.power;
|
||||
}
|
||||
@ -747,6 +742,7 @@ void main() {
|
||||
fog(rayO, rayD, fragColor, litFactor);
|
||||
|
||||
/*
|
||||
|
||||
if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) {
|
||||
//dither1(fragColor);
|
||||
fragColor += dither2();
|
||||
|
||||
@ -112,7 +112,7 @@ void main() {
|
||||
}
|
||||
if ( C.a == 0 ) discard;
|
||||
}
|
||||
#if 0
|
||||
#if 1
|
||||
if ( validTextureIndex( material.indexLightmap ) ) {
|
||||
#if UF_DEFERRED_SAMPLING
|
||||
outUvs = inSt;
|
||||
|
||||
@ -57,7 +57,7 @@ namespace pod {
|
||||
ext::gltf::load_mode_t mode;
|
||||
uf::Serializer metadata;
|
||||
|
||||
uf::Atlas* atlas = NULL;
|
||||
uf::Atlas atlas;
|
||||
std::vector<uf::Image> images;
|
||||
std::vector<uf::renderer::Sampler> samplers;
|
||||
std::vector<pod::Texture> textures;
|
||||
|
||||
@ -12,6 +12,7 @@ namespace {\
|
||||
|
||||
#define UF_LUA_REGISTER_USERTYPE_DEFINE_RT(k, v) usertype[#k] = v;
|
||||
#define UF_LUA_REGISTER_USERTYPE_MEMBER_RT(member) usertype[UF_NS_GET_LAST(member)] = &member;
|
||||
#define UF_LUA_REGISTER_USERTYPE_MEMBER_FUN_RT(member) usertype[UF_NS_GET_LAST(member)] = UF_LUA_C_FUN(member);
|
||||
|
||||
#define UF_LUA_REGISTER_USERTYPE_END() \
|
||||
});\
|
||||
@ -29,4 +30,8 @@ namespace {\
|
||||
}
|
||||
|
||||
#define UF_LUA_REGISTER_USERTYPE_DEFINE(k, v) #k, v
|
||||
#define UF_LUA_REGISTER_USERTYPE_MEMBER(member) UF_NS_GET_LAST(member), &member
|
||||
#define UF_LUA_REGISTER_USERTYPE_MEMBER(member) UF_NS_GET_LAST(member), &member
|
||||
#define UF_LUA_REGISTER_USERTYPE_MEMBER_FUN(member) UF_NS_GET_LAST(member), UF_LUA_C_FUN(member)
|
||||
|
||||
#define UF_LUA_C_FUN(x) sol::c_call<decltype(&x), &x>
|
||||
#define UF_LUA_WRAP_FUN(x) sol::c_call<sol::wrap<decltype(&x), &x>>
|
||||
@ -119,7 +119,7 @@ namespace ext {
|
||||
void end();
|
||||
size_t size() const;
|
||||
protected:
|
||||
void bindUniform( const Buffer::Descriptor& descriptor );
|
||||
pod::Matrix4f bindUniform( const Buffer::Descriptor& descriptor );
|
||||
void drawIndexed( const InfoDraw& );
|
||||
// void draw( const InfoDraw&, const Info&, const std::vector<InfoTexture*>& = {} );
|
||||
// void drawIndexed( const InfoDraw&, const Info&, const Info&, const std::vector<InfoTexture*>& = {} );
|
||||
|
||||
@ -48,15 +48,23 @@
|
||||
#define GL_DEBUG_MESSAGE(...) UF_DEBUG_MSG(__VA_ARGS__);
|
||||
#define GL_VALIDATION_MESSAGE(...) if ( ext::opengl::settings::validation ) GL_DEBUG_MESSAGE(__VA_ARGS__);
|
||||
|
||||
#define GL_ERROR_CHECK(f) { \
|
||||
{f;} \
|
||||
GLenum res = glGetError(); \
|
||||
if (res != GL_NO_ERROR) { \
|
||||
std::string errorString = ext::opengl::errorString( res ); \
|
||||
GL_VALIDATION_MESSAGE("[Validation Error] " << #f << ": " << errorString); \
|
||||
} \
|
||||
}
|
||||
#if UF_ENV_DREAMCAST
|
||||
#define GL_VALIDATION_ENABLED 0
|
||||
#else
|
||||
#define GL_VALIDATION_ENABLED 1
|
||||
#endif
|
||||
|
||||
#if GL_VALIDATION_ENABLED
|
||||
#define GL_ERROR_CHECK(f) { \
|
||||
{f;} \
|
||||
if ( ext::opengl::settings::validation ) { \
|
||||
GLenum res = glGetError(); \
|
||||
if (res != GL_NO_ERROR) GL_DEBUG_MESSAGE("[Validation Error] " << #f << ": " << ext::opengl::errorString( res )); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define GL_ERROR_CHECK(f) {f;}
|
||||
#endif
|
||||
#if 0
|
||||
#define GL_MUTEX_LOCK() ext::opengl::mutex.lock();
|
||||
#define GL_MUTEX_UNLOCK() ext::opengl::mutex.unlock();
|
||||
|
||||
@ -36,6 +36,7 @@ namespace ext {
|
||||
extern UF_API bool multiview;
|
||||
extern UF_API bool vsync;
|
||||
extern UF_API bool hdr;
|
||||
extern UF_API bool frustrumCull;
|
||||
}
|
||||
|
||||
namespace formats {
|
||||
|
||||
@ -85,11 +85,11 @@ namespace ext {
|
||||
enums::Format::type_t format = enums::Format::R8G8B8A8_UNORM
|
||||
);
|
||||
void loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
enums::Format::type_t format = enums::Format::R8G8B8A8_UNORM
|
||||
);
|
||||
void loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
Device& device,
|
||||
enums::Format::type_t format = enums::Format::R8G8B8A8_UNORM
|
||||
);
|
||||
|
||||
@ -93,14 +93,14 @@ namespace ext {
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
void loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
Device& device,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
void loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
|
||||
@ -63,6 +63,7 @@ namespace ext {
|
||||
extern UF_API bool multiview;
|
||||
extern UF_API bool vsync;
|
||||
extern UF_API bool hdr;
|
||||
extern UF_API bool frustrumCull;
|
||||
}
|
||||
|
||||
namespace formats {
|
||||
|
||||
@ -63,7 +63,6 @@ namespace pod {
|
||||
namespace uf {
|
||||
typedef BaseMesh<pod::Vertex_3F2F3F32B> ColoredMesh;
|
||||
typedef BaseMesh<pod::Vertex_3F2F3F> Mesh;
|
||||
typedef BaseMesh<pod::Vertex_3F2F> GuiMesh;
|
||||
typedef BaseMesh<pod::Vertex_3F> LineMesh;
|
||||
|
||||
template<size_t N = 6>
|
||||
|
||||
@ -1,39 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/utils/image/image.h>
|
||||
#include <binpack2d/binpack2d.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace uf {
|
||||
class UF_API Atlas {
|
||||
public:
|
||||
typedef std::string hash_t;
|
||||
struct Identifier {
|
||||
size_t index;
|
||||
hash_t hash;
|
||||
};
|
||||
struct Tile {
|
||||
uf::Image image;
|
||||
Identifier identifier = {0,""};
|
||||
pod::Vector2ui size = {};
|
||||
pod::Vector2ui coord = {};
|
||||
};
|
||||
typedef std::vector<uf::Image> images_t;
|
||||
typedef Identifier identifier_t;
|
||||
typedef BinPack2D::CanvasArray<identifier_t> atlas_t;
|
||||
typedef std::unordered_map<hash_t, Tile> atlas_t;
|
||||
protected:
|
||||
uf::Image m_image;
|
||||
images_t m_images;
|
||||
atlas_t m_atlas;
|
||||
uf::Image m_atlas;
|
||||
atlas_t m_tiles;
|
||||
public:
|
||||
void addImage( const uf::Image&, bool = false );
|
||||
void addImage( uf::Image&&, bool = false );
|
||||
void addImage( const uint8_t*, const pod::Vector2ui&, std::size_t, std::size_t, bool = false, bool = false );
|
||||
hash_t addImage( const uf::Image&, bool = false );
|
||||
hash_t addImage( uf::Image&&, bool = false );
|
||||
hash_t addImage( const uint8_t*, const pod::Vector2ui&, std::size_t, std::size_t, bool = false, bool = false );
|
||||
|
||||
void generate(float padding = 1);
|
||||
void generate( const images_t&, float padding = 1);
|
||||
void clear();
|
||||
void generate( const std::vector<uf::Image>&, float padding = 1);
|
||||
void clear(bool = true);
|
||||
bool generated() const;
|
||||
|
||||
pod::Vector2f mapUv( const pod::Vector2f&, const hash_t& );
|
||||
pod::Vector2f mapUv( const pod::Vector2f&, size_t );
|
||||
pod::Vector3f mapUv( const pod::Vector3f& );
|
||||
|
||||
uf::Image& getAtlas();
|
||||
images_t& getImages();
|
||||
const images_t& getImages() const;
|
||||
const uf::Image& getAtlas() const;
|
||||
|
||||
atlas_t& getImages();
|
||||
const atlas_t& getImages() const;
|
||||
};
|
||||
|
||||
#if 0
|
||||
class UF_API HashAtlas {
|
||||
public:
|
||||
typedef std::string hash_t;
|
||||
@ -65,4 +74,5 @@ namespace uf {
|
||||
images_t& getImages();
|
||||
const images_t& getImages() const;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
@ -63,8 +63,8 @@ namespace uf {
|
||||
template<typename T> pod::Matrix<T,4,4> multiply( const pod::Matrix<T,4,4>& left, const pod::Matrix<T,4,4>& right ); // Multiplies two matrices of same type and size together
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ transpose( const T& matrix ); // Flip sign of all components
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ inverse( const T& matrix ); // Flip sign of all components
|
||||
template<typename T=pod::Math::num_t> pod::Vector3t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector3t<T>& vector, T w = 1 );
|
||||
template<typename T=pod::Math::num_t> pod::Vector4t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector4t<T>& vector );
|
||||
template<typename T=pod::Math::num_t> pod::Vector3t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector3t<T>& vector, T w = 1, bool = false );
|
||||
template<typename T=pod::Math::num_t> pod::Vector4t<T> multiply( const pod::Matrix4t<T>& mat, const pod::Vector4t<T>& vector, bool = false );
|
||||
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ multiplyAll( const T& matrix, typename T::type_t scalar );
|
||||
template<typename T=pod::Matrix4> T /*UF_API*/ add( const T& lhs, const T& rhs );
|
||||
|
||||
@ -410,21 +410,25 @@ template<typename T> T uf::matrix::inverse( const T& matrix ) {
|
||||
template<typename T> pod::Matrix<typename T::type_t, T::columns, T::columns> uf::matrix::multiply( T& left, const T& right ) {
|
||||
return left = uf::matrix::multiply((const T&) left, right);
|
||||
}
|
||||
template<typename T> pod::Vector3t<T> uf::matrix::multiply( const pod::Matrix4t<T>& mat, const pod::Vector3t<T>& vector, T w ) {
|
||||
return uf::matrix::multiply( mat, pod::Vector4t<T>{ vector[0], vector[1], vector[2], w } );
|
||||
template<typename T> pod::Vector3t<T> uf::matrix::multiply( const pod::Matrix4t<T>& mat, const pod::Vector3t<T>& vector, T w, bool div ) {
|
||||
return uf::matrix::multiply( mat, pod::Vector4t<T>{ vector[0], vector[1], vector[2], w }, div );
|
||||
}
|
||||
template<typename T> pod::Vector4t<T> uf::matrix::multiply( const pod::Matrix4t<T>& mat, const pod::Vector4t<T>& vector ) {
|
||||
template<typename T> pod::Vector4t<T> uf::matrix::multiply( const pod::Matrix4t<T>& mat, const pod::Vector4t<T>& vector, bool div ) {
|
||||
#if UF_ENV_DREAMCAST
|
||||
MATH_Load_XMTRX( (ALL_FLOATS_STRUCT*) &mat[0] );
|
||||
auto res = MATH_Matrix_Transform( vector[0], vector[1], vector[2], vector[3] );
|
||||
return *((pod::Vector4t<T>*) &res);
|
||||
auto t = MATH_Matrix_Transform( vector[0], vector[1], vector[2], vector[3] );
|
||||
auto res = *((pod::Vector4t<T>*) &t);
|
||||
if ( div && res.w > 0 ) res /= res.w;
|
||||
return res;
|
||||
#endif
|
||||
return {
|
||||
auto res = pod::Vector4t<T>{
|
||||
vector[0] * mat[0] + vector[1] * mat[4] + vector[2] * mat[8] + vector[3] * mat[12],
|
||||
vector[0] * mat[1] + vector[1] * mat[5] + vector[2] * mat[9] + vector[3] * mat[13],
|
||||
vector[0] * mat[2] + vector[1] * mat[6] + vector[2] * mat[10] + vector[3] * mat[14],
|
||||
vector[0] * mat[3] + vector[1] * mat[7] + vector[2] * mat[11] + vector[3] * mat[15]
|
||||
};
|
||||
if ( div && res.w > 0 ) res /= res.w;
|
||||
return res;
|
||||
}
|
||||
// Flip sign of all components
|
||||
template<typename T> T& uf::matrix::invert( T& matrix ) {
|
||||
|
||||
@ -175,9 +175,9 @@ std::string uf::Asset::load( const std::string& uri, const std::string& hash, co
|
||||
// force disable use of a texture atlas, for now
|
||||
metadata[uri]["flags"]["ATLAS"] = false;
|
||||
metadata[uri]["flags"]["SEPARATE"] = true;
|
||||
metadata[uri]["flags"]["NORMALS"] = true;
|
||||
// metadata[uri]["flags"]["NORMALS"] = true;
|
||||
#else
|
||||
metadata[uri]["flags"]["ATLAS"] = true;
|
||||
// metadata[uri]["flags"]["ATLAS"] = true;
|
||||
#endif
|
||||
ext::gltf::load_mode_t LOAD_FLAGS = 0;
|
||||
#define LOAD_FLAG(name)\
|
||||
|
||||
@ -88,8 +88,15 @@ void uf::Behaviors::tick() {
|
||||
uf::Object& self = *((uf::Object*) this);
|
||||
if ( !self.isValid() ) return;
|
||||
// UF_TIMER_TRACE_INIT();
|
||||
UF_BEHAVIOR_POLYFILL(tick)
|
||||
// UF_BEHAVIOR_POLYFILL(tick)
|
||||
// UF_TIMER_TRACE(self.getName() << ": " << self.getUid());
|
||||
|
||||
// UF_TIMER_MULTITRACE_START("==== START TICKING BEHAVIORS ====");
|
||||
for ( auto& behavior : this->m_behaviors ) {
|
||||
behavior.tick(self);
|
||||
// UF_TIMER_MULTITRACE(behavior.type);
|
||||
}
|
||||
// UF_TIMER_MULTITRACE_END("==== END TICKING BEHAVIORS ====");
|
||||
}
|
||||
void uf::Behaviors::render() {
|
||||
uf::Object& self = *((uf::Object*) this);
|
||||
|
||||
@ -167,6 +167,10 @@ void uf::ObjectBehavior::destroy( uf::Object& self ) {
|
||||
graphic.destroy();
|
||||
uf::renderer::states::rebuild = true;
|
||||
}
|
||||
if ( this->hasComponent<uf::Atlas>() ) {
|
||||
auto& atlas = this->getComponent<uf::Atlas>();
|
||||
atlas.clear();
|
||||
}
|
||||
}
|
||||
void uf::ObjectBehavior::tick( uf::Object& self ) {
|
||||
// listen for metadata file changes
|
||||
@ -201,18 +205,29 @@ void uf::ObjectBehavior::tick( uf::Object& self ) {
|
||||
if ( ext::json::isObject( metadata ) ) queue = newQueue;
|
||||
}
|
||||
#else
|
||||
|
||||
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
|
||||
{
|
||||
auto& queue = metadata.hooks.queue;
|
||||
if ( !uf::Object::timer.running() ) uf::Object::timer.start();
|
||||
float curTime = uf::Object::timer.elapsed().asDouble();
|
||||
for ( auto it = queue.begin(); it != queue.end(); ) {
|
||||
auto& q = *it;
|
||||
if ( q.timeout < curTime ) { this->callHook( q.name, q.payload ); it = queue.erase( it ); }
|
||||
else ++it;
|
||||
}
|
||||
auto& queue = metadata.hooks.queue;
|
||||
if ( !uf::Object::timer.running() ) uf::Object::timer.start();
|
||||
float curTime = uf::Object::timer.elapsed().asDouble();
|
||||
#if 1
|
||||
decltype(metadata.hooks.queue) unprocessed;
|
||||
unprocessed.reserve( metadata.hooks.queue.size() );
|
||||
|
||||
decltype(metadata.hooks.queue) executeQueue;
|
||||
executeQueue.reserve( metadata.hooks.queue.size() );
|
||||
|
||||
for ( auto& q : queue ) if ( q.timeout < curTime ) executeQueue.emplace_back(q); else unprocessed.emplace_back(q);
|
||||
for ( auto& q : executeQueue ) this->callHook( q.name, q.payload );
|
||||
queue = std::move(unprocessed);
|
||||
#else
|
||||
for ( auto it = queue.begin(); it != queue.end(); ) {
|
||||
auto& q = *it;
|
||||
if ( q.timeout < curTime ) { this->callHook( q.name, q.payload ); it = queue.erase( it ); }
|
||||
else ++it;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
void uf::ObjectBehavior::render( uf::Object& self ) {}
|
||||
#undef this
|
||||
|
||||
@ -97,19 +97,19 @@ std::vector<uf::Entity*> uf::scene::generateGraph() {
|
||||
|
||||
void uf::scene::tick() {
|
||||
auto graph = uf::scene::generateGraph();
|
||||
// UF_TIMER_MULTITRACE_START("==== START RENDER ====");
|
||||
// UF_TIMER_MULTITRACE_START("==== START TICK ====");
|
||||
for ( auto it = graph.rbegin(); it != graph.rend(); ++it ) {
|
||||
(*it)->tick();
|
||||
// UF_TIMER_MULTITRACE_START((*it)->getName() << ": " << (*it)->getUid());
|
||||
// UF_TIMER_MULTITRACE((*it)->getName() << ": " << (*it)->getUid());
|
||||
}
|
||||
// UF_TIMER_MULTITRACE_END("==== END RENDER ====");
|
||||
// UF_TIMER_MULTITRACE_END("==== END TICK ====");
|
||||
}
|
||||
void uf::scene::render() {
|
||||
auto graph = uf::scene::generateGraph();
|
||||
// UF_TIMER_MULTITRACE_START("==== START RENDER ====");
|
||||
for ( auto it = graph.rbegin(); it != graph.rend(); ++it ) {
|
||||
(*it)->render();
|
||||
// UF_TIMER_MULTITRACE_START((*it)->getName() << ": " << (*it)->getUid());
|
||||
// UF_TIMER_MULTITRACE((*it)->getName() << ": " << (*it)->getUid());
|
||||
}
|
||||
// UF_TIMER_MULTITRACE_END("==== END RENDER ====");
|
||||
}
|
||||
|
||||
@ -151,14 +151,14 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
{
|
||||
graph.images.reserve(model.images.size());
|
||||
for ( auto& i : model.images ) {
|
||||
size_t index = graph.images.size();
|
||||
auto& image = graph.images.emplace_back();
|
||||
image.loadFromBuffer( &i.image[0], {i.width, i.height}, 8, i.component, true );
|
||||
}
|
||||
}
|
||||
// generate atlas
|
||||
if ( mode & ext::gltf::LoadMode::ATLAS ) { if ( graph.atlas ) delete graph.atlas; graph.atlas = new uf::Atlas;
|
||||
auto& atlas = *graph.atlas;
|
||||
atlas.generate( graph.images );
|
||||
if ( mode & ext::gltf::LoadMode::ATLAS ) {
|
||||
graph.atlas.generate( graph.images );
|
||||
}
|
||||
// load textures
|
||||
{
|
||||
@ -169,10 +169,11 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
|
||||
texture.storage.index = t.source;
|
||||
texture.storage.sampler = t.sampler;
|
||||
if ( graph.atlas ) {
|
||||
auto& atlas = *graph.atlas;
|
||||
auto atlasMin = atlas.mapUv( {0, 0}, t.source );
|
||||
auto atlasMax = atlas.mapUv( {1, 1}, t.source );
|
||||
if ( 0 <= t.source && graph.atlas.generated() ) {
|
||||
size_t index = t.source;
|
||||
const auto& hash = graph.images[index].getHash();
|
||||
auto atlasMin = graph.atlas.mapUv( {0, 0}, hash );
|
||||
auto atlasMax = graph.atlas.mapUv( {1, 1}, hash );
|
||||
|
||||
texture.storage.lerp = {
|
||||
atlasMin.x,
|
||||
@ -184,6 +185,9 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( graph.atlas.generated() ) {
|
||||
graph.atlas.clear(false);
|
||||
}
|
||||
// load materials
|
||||
{
|
||||
graph.materials.reserve(model.materials.size());
|
||||
|
||||
@ -155,17 +155,16 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if ( graph.atlas ) {
|
||||
for ( auto& texture : graph.textures ) {
|
||||
++texture.storage.index;
|
||||
}
|
||||
auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas->getAtlas());
|
||||
if ( graph.metadata["flags"]["ATLAS"].as<bool>() && graph.atlas.generated() ) {
|
||||
// for ( auto& texture : graph.textures ) if ( 0 <= texture.storage.index ) ++texture.storage.index;
|
||||
|
||||
auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas.getAtlas());
|
||||
auto& texture = *graph.textures.emplace(graph.textures.begin());
|
||||
texture.name = "atlas";
|
||||
texture.bind = true;
|
||||
texture.storage.index = 0;
|
||||
texture.storage.sampler = 0;
|
||||
texture.storage.remap = 0;
|
||||
texture.storage.remap = -1;
|
||||
texture.storage.blend = 0;
|
||||
|
||||
if ( graph.metadata["filter"].is<std::string>() ) {
|
||||
@ -188,12 +187,19 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
if ( 0 <= material.storage.indexLightmap ) ++material.storage.indexLightmap;
|
||||
}
|
||||
texture.texture.loadFromImage( image );
|
||||
|
||||
// remap texture slots
|
||||
size_t textureSlot = 0;
|
||||
for ( auto& texture : graph.textures ) {
|
||||
texture.storage.index = -1;
|
||||
if ( !texture.bind ) continue;
|
||||
texture.storage.index = textureSlot++;
|
||||
}
|
||||
} else {
|
||||
for ( size_t i = 0; i < graph.textures.size() && i < graph.images.size(); ++i ) {
|
||||
auto& image = graph.images[i];
|
||||
auto& texture = graph.textures[i];
|
||||
texture.bind = true;
|
||||
texture.storage.index = i;
|
||||
if ( graph.metadata["filter"].is<std::string>() ) {
|
||||
std::string filter = graph.metadata["filter"].as<std::string>();
|
||||
if ( filter == "NEAREST" ) {
|
||||
@ -207,6 +213,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
texture.texture.loadFromImage( image );
|
||||
}
|
||||
}
|
||||
/*
|
||||
{
|
||||
size_t textureSlot = 0;
|
||||
for ( auto& texture : graph.textures ) {
|
||||
@ -215,6 +222,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
texture.storage.index = textureSlot++;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if ( !graph.root.entity ) graph.root.entity = new uf::Object;
|
||||
for ( auto index : graph.root.children ) process( graph, index, *graph.root.entity );
|
||||
@ -318,8 +326,22 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
if ( entity->hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
||||
graphic.initialize();
|
||||
graphic.initializeMesh( mesh, 0 );
|
||||
#if 1
|
||||
if ( entity->getName() == "worldspawn_20" && ext::json::isObject( graph.metadata["grid"] ) ) {
|
||||
auto sliced = mesh;
|
||||
auto& grid = entity->getComponent<uf::MeshGrid>();
|
||||
grid.initialize( sliced, uf::vector::decode( graph.metadata["grid"]["size"], pod::Vector3ui{1,1,1} ) );
|
||||
grid.analyze();
|
||||
|
||||
auto center = uf::vector::decode( graph.metadata["grid"]["center"], grid.center() );
|
||||
sliced.indices = grid.get<>( center );
|
||||
graphic.initializeMesh( sliced );
|
||||
} else {
|
||||
graphic.initializeMesh( mesh );
|
||||
}
|
||||
#else
|
||||
graphic.initialize();
|
||||
graphic.initializeMesh( mesh, 0 );
|
||||
if ( ext::json::isObject( graph.metadata["grid"] ) ) {
|
||||
auto& grid = entity->getComponent<uf::MeshGrid>();
|
||||
grid.initialize( mesh, uf::vector::decode( graph.metadata["grid"]["size"], pod::Vector3ui{1,1,1} ) );
|
||||
@ -442,7 +464,10 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
if ( graph.metadata["lightmapped"].as<bool>() && !(metadataLight["shadows"].as<bool>() || metadataLight["dynamic"].as<bool>()) ) continue;
|
||||
auto& metadataJson = entity.getComponent<uf::Serializer>();
|
||||
entity.load("/light.json");
|
||||
metadataJson["light"] = metadataLight;
|
||||
// copy
|
||||
ext::json::forEach( metadataLight, [&]( const std::string& key, ext::json::Value& value ) {
|
||||
metadataJson["light"][key] = value;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -490,14 +515,6 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
// preprocess mesh
|
||||
for ( auto& vertex : nodeMesh.vertices ) {
|
||||
vertex.id.x = node.index;
|
||||
// in almost-software mode, material ID is actually its albedo ID, as we can't use any other forms of mapping
|
||||
#if UF_USE_OPENGL_FIXED_FUNCTION
|
||||
if ( !(graph.metadata["flags"]["ATLAS"].as<bool>()) ) {
|
||||
auto& material = graph.materials[vertex.id.y];
|
||||
auto& texture = graph.textures[material.storage.indexAlbedo];
|
||||
vertex.id.y = texture.storage.index;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
auto& mesh = entity.getComponent<ext::gltf::mesh_t>();
|
||||
@ -548,9 +565,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
void uf::graph::cleanup( pod::Graph& graph ) {
|
||||
graph.images.clear();
|
||||
graph.meshes.clear();
|
||||
if ( graph.atlas ) {
|
||||
graph.atlas->getAtlas().clear();
|
||||
}
|
||||
graph.atlas.clear();
|
||||
}
|
||||
void uf::graph::override( pod::Graph& graph ) {
|
||||
graph.settings.animations.override.a = 0;
|
||||
@ -691,7 +706,6 @@ void uf::graph::destroy( pod::Graph& graph ) {
|
||||
for ( auto& t : graph.textures ) {
|
||||
t.texture.destroy();
|
||||
}
|
||||
delete graph.atlas;
|
||||
}
|
||||
|
||||
#include <uf/utils/string/base64.h>
|
||||
@ -905,6 +919,18 @@ pod::Graph uf::graph::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
return 0;
|
||||
});
|
||||
jobs.emplace_back([&]{
|
||||
if ( !ext::json::isNull( serializer["atlas"] ) ) {
|
||||
UF_DEBUG_TRACE_MSG("Reading atlas...");
|
||||
auto& image = graph.atlas.getAtlas();
|
||||
auto& value = serializer["atlas"];
|
||||
if ( value.is<std::string>() ) {
|
||||
std::string filename = directory + "/" + value.as<std::string>();
|
||||
UF_DEBUG_TRACE_MSG("Reading atlas " << filename);
|
||||
image.open(filename, false);
|
||||
} else {
|
||||
decode( value, image );
|
||||
}
|
||||
}
|
||||
// load images
|
||||
UF_DEBUG_TRACE_MSG("Reading images...");
|
||||
graph.images.reserve( serializer["images"].size() );
|
||||
@ -1010,6 +1036,18 @@ pod::Graph uf::graph::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
}
|
||||
});
|
||||
// load images
|
||||
if ( !ext::json::isNull( serializer["atlas"] ) ) {
|
||||
UF_DEBUG_TRACE_MSG("Reading atlas...");
|
||||
auto& image = graph.atlas.getAtlas();
|
||||
auto& value = serializer["atlas"];
|
||||
if ( value.is<std::string>() ) {
|
||||
std::string filename = directory + "/" + value.as<std::string>();
|
||||
UF_DEBUG_TRACE_MSG("Reading atlas " << filename);
|
||||
image.open(filename, false);
|
||||
} else {
|
||||
decode( value, image );
|
||||
}
|
||||
}
|
||||
UF_DEBUG_TRACE_MSG("Reading images...");
|
||||
graph.images.reserve( serializer["images"].size() );
|
||||
ext::json::forEach( serializer["images"], [&]( ext::json::Value& value ){
|
||||
@ -1074,12 +1112,14 @@ pod::Graph uf::graph::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
});
|
||||
decode(serializer["root"], graph.root);
|
||||
#endif
|
||||
#if 0
|
||||
// generate atlas
|
||||
if ( graph.metadata["flags"]["ATLAS"].as<bool>() ) { if ( graph.atlas ) delete graph.atlas; graph.atlas = new uf::Atlas;
|
||||
if ( graph.metadata["flags"]["ATLAS"].as<bool>() ) {
|
||||
UF_DEBUG_TRACE_MSG("Generating atlas...");
|
||||
auto& atlas = *graph.atlas;
|
||||
atlas.generate( graph.images );
|
||||
graph.atlas.generate( graph.images );
|
||||
graph.atlas.clear(false);
|
||||
}
|
||||
#endif
|
||||
// re-reference all transform parents
|
||||
for ( auto& node : graph.nodes ) {
|
||||
if ( 0 <= node.parent && node.parent < graph.nodes.size() && node.index != node.parent ) {
|
||||
@ -1244,6 +1284,17 @@ void uf::graph::save( const pod::Graph& graph, const std::string& filename ) {
|
||||
#if UF_GRAPH_LOAD_MULTITHREAD
|
||||
std::vector<std::function<int()>> jobs;
|
||||
jobs.emplace_back([&]{
|
||||
if ( graph.atlas.generated() ) {
|
||||
auto& image = graph.atlas.getAtlas();
|
||||
if ( saveSeparately ) {
|
||||
std::string f = "atlas";
|
||||
f += compression?".jpg":".png";
|
||||
image.save(directory + "/" + f);
|
||||
serializer["atlas"] = f;
|
||||
} else {
|
||||
serializer["atlas"] = encode(image, compression);
|
||||
}
|
||||
}
|
||||
ext::json::reserve( serializer["images"], graph.images.size() );
|
||||
if ( saveSeparately ) {
|
||||
for ( size_t i = 0; i < graph.images.size(); ++i ) {
|
||||
@ -1323,6 +1374,16 @@ void uf::graph::save( const pod::Graph& graph, const std::string& filename ) {
|
||||
});
|
||||
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
|
||||
#else
|
||||
if ( graph.atlas.generated() ) {
|
||||
auto& image = graph.atlas.getAtlas();
|
||||
if ( saveSeparately ) {
|
||||
std::string f = "atlas"+(compression?".jpg":".png");
|
||||
image.save(directory + "/" + f);
|
||||
serializer["atlas"] = f;
|
||||
} else {
|
||||
serializer["atlas"] = encode(image, compression);
|
||||
}
|
||||
}
|
||||
ext::json::reserve( serializer["images"], graph.images.size() );
|
||||
if ( saveSeparately ) {
|
||||
for ( size_t i = 0; i < graph.images.size(); ++i ) {
|
||||
|
||||
@ -55,6 +55,112 @@ void ext::lua::onInitialization( const std::function<void()>& function ) {
|
||||
functions.emplace_back(function);
|
||||
}
|
||||
|
||||
|
||||
namespace binds {
|
||||
namespace hook {
|
||||
void add( const std::string& name, const sol::function& function ) {
|
||||
uf::hooks.addHook( name, [function](ext::json::Value& json){
|
||||
sol::table table = ext::lua::state["json"]["decode"]( json.dump() );
|
||||
auto result = function( table );
|
||||
if ( !result.valid() ) {
|
||||
sol::error err = result;
|
||||
uf::iostream << err.what() << "\n";
|
||||
}
|
||||
});
|
||||
};
|
||||
void call( const std::string& name, sol::table table = ext::lua::createTable() ) {
|
||||
uf::Serializer payload = table;
|
||||
uf::hooks.call( name, (ext::json::Value&) payload );
|
||||
return;
|
||||
};
|
||||
}
|
||||
namespace entities {
|
||||
uf::Object& get(const uint& uid) {
|
||||
auto* p = uf::Entity::globalFindByUid(uid);
|
||||
if ( p ) return p->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
};
|
||||
uf::Object& currentScene() {
|
||||
return uf::scene::getCurrentScene().as<uf::Object>();
|
||||
};
|
||||
uf::Object& controller(){
|
||||
return uf::scene::getCurrentScene().getController().as<uf::Object>();
|
||||
};
|
||||
void destroy( uf::Object& object ) {
|
||||
object.getParent().removeChild(object);
|
||||
object.destroy();
|
||||
// delete &object;
|
||||
};
|
||||
}
|
||||
namespace string {
|
||||
std::string extension( const std::string& filename ) {
|
||||
return uf::io::extension( filename );
|
||||
};
|
||||
std::string resolveURI( const std::string& filename, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
std::string root = it != va.end() ? *(it++) : std::string("");
|
||||
return uf::io::resolveURI( filename, root );
|
||||
};
|
||||
std::string si( sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
double value = *(it++);
|
||||
std::string unit = *(it++);
|
||||
size_t precision = va.size() > 2 ? *(it++) : 3;
|
||||
return uf::string::si( value, unit, precision );
|
||||
};
|
||||
}
|
||||
namespace io {
|
||||
void print( sol::variadic_args va ) {
|
||||
size_t count = va.size();
|
||||
for ( auto value : va ) {
|
||||
std::string str = ext::lua::state["tostring"]( value );
|
||||
uf::iostream << str;
|
||||
if ( --count != 0 ) uf::iostream << "\t";
|
||||
}
|
||||
uf::iostream << "\n";
|
||||
};
|
||||
}
|
||||
namespace math {
|
||||
double clamp( double value, double min, double max ) {
|
||||
return std::clamp( value, min, max );
|
||||
};
|
||||
}
|
||||
namespace time {
|
||||
double current(){ return uf::physics::time::current; };
|
||||
double previous(){ return uf::physics::time::previous; };
|
||||
double delta(){ return uf::physics::time::delta; };
|
||||
}
|
||||
namespace json {
|
||||
std::string pretty( const std::string& json ){
|
||||
uf::Serializer serializer = json;
|
||||
return serializer.serialize();
|
||||
};
|
||||
sol::table readFromFile( const std::string& filename ){
|
||||
uf::Serializer serializer;
|
||||
serializer.readFromFile( filename );
|
||||
std::string string = serializer.serialize(false);
|
||||
auto decoded = ext::lua::decode( string );
|
||||
return decoded ? decoded.value() : ext::lua::createTable();
|
||||
};
|
||||
bool writeToFile( sol::table table, const std::string& path ) {
|
||||
if ( uf::io::extension(path) != "json" ) return false;
|
||||
auto encoded = ext::lua::encode( table );
|
||||
if ( encoded ) {
|
||||
uf::Serializer json = encoded.value();
|
||||
json.writeToFile( path );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
namespace os {
|
||||
std::string arch() {
|
||||
return UF_ENV;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ext::lua::initialize() {
|
||||
state.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table, sol::lib::math, sol::lib::string, sol::lib::ffi, sol::lib::jit);
|
||||
|
||||
@ -79,118 +185,56 @@ void ext::lua::initialize() {
|
||||
{
|
||||
|
||||
auto hooks = state["hooks"].get_or_create<sol::table>();
|
||||
hooks["add"] = []( const std::string& name, const sol::function& function ) {
|
||||
uf::hooks.addHook( name, [function](ext::json::Value& json){
|
||||
sol::table table = ext::lua::state["json"]["decode"]( json.dump() );
|
||||
auto result = function( table );
|
||||
if ( !result.valid() ) {
|
||||
sol::error err = result;
|
||||
uf::iostream << err.what() << "\n";
|
||||
}
|
||||
});
|
||||
};
|
||||
hooks["call"] = []( const std::string& name, sol::table table = createTable() ) {
|
||||
uf::Serializer payload = table;
|
||||
return uf::hooks.call( name, (ext::json::Value&) payload );
|
||||
};
|
||||
hooks["add"] = UF_LUA_C_FUN(::binds::hook::add);
|
||||
hooks["call"] = UF_LUA_C_FUN(::binds::hook::call);
|
||||
}
|
||||
// `entities` table
|
||||
{
|
||||
auto entities = state["entities"].get_or_create<sol::table>();
|
||||
entities["get"] = [](const uint& uid)->uf::Object&{
|
||||
auto* p = uf::Entity::globalFindByUid(uid);
|
||||
if ( p ) return p->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
};
|
||||
entities["currentScene"] = []()->uf::Object&{
|
||||
return uf::scene::getCurrentScene().as<uf::Object>();
|
||||
};
|
||||
entities["controller"] = []()->uf::Object&{
|
||||
return uf::scene::getCurrentScene().getController().as<uf::Object>();
|
||||
};
|
||||
entities["destroy"] = []( uf::Object& object ){
|
||||
object.getParent().removeChild(object);
|
||||
object.destroy();
|
||||
// delete &object;
|
||||
};
|
||||
entities["get"] = UF_LUA_C_FUN(::binds::entities::get);
|
||||
entities["currentScene"] = UF_LUA_C_FUN(::binds::entities::currentScene);
|
||||
entities["controller"] = UF_LUA_C_FUN(::binds::entities::controller);
|
||||
entities["destroy"] = UF_LUA_C_FUN(::binds::entities::destroy);
|
||||
}
|
||||
// `string` table
|
||||
{
|
||||
auto string = state["string"].get_or_create<sol::table>();
|
||||
string["extension"] = []( const std::string& filename ) {
|
||||
return uf::io::extension( filename );
|
||||
};
|
||||
string["resolveURI"] = []( const std::string& filename, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
std::string root = it != va.end() ? *(it++) : std::string("");
|
||||
return uf::io::resolveURI( filename, root );
|
||||
};
|
||||
string["si"] = []( sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
double value = *(it++);
|
||||
std::string unit = *(it++);
|
||||
size_t precision = va.size() > 2 ? *(it++) : 3;
|
||||
return uf::string::si( value, unit, precision );
|
||||
};
|
||||
string["extension"] = UF_LUA_C_FUN(::binds::string::extension);
|
||||
string["resolveURI"] = UF_LUA_C_FUN(::binds::string::resolveURI);
|
||||
string["si"] = UF_LUA_C_FUN(::binds::string::si);
|
||||
}
|
||||
// `io` table
|
||||
{
|
||||
auto io = state["io"].get_or_create<sol::table>();
|
||||
io["print"] = []( sol::variadic_args va ) {
|
||||
size_t count = va.size();
|
||||
for ( auto value : va ) {
|
||||
std::string str = ext::lua::state["tostring"]( value );
|
||||
uf::iostream << str;
|
||||
if ( --count != 0 ) uf::iostream << "\t";
|
||||
}
|
||||
uf::iostream << "\n";
|
||||
};
|
||||
io["print"] = UF_LUA_C_FUN(::binds::io::print);
|
||||
}
|
||||
// `math` table
|
||||
{
|
||||
auto math = state["math"].get_or_create<sol::table>();
|
||||
math["clamp"] = []( double value, double min, double max ) {
|
||||
return std::clamp( value, min, max );
|
||||
};
|
||||
math["clamp"] = UF_LUA_C_FUN(::binds::math::clamp);
|
||||
}
|
||||
// `time` table
|
||||
{
|
||||
auto time = state["time"].get_or_create<sol::table>();
|
||||
time["current"] = []()->double{ return uf::physics::time::current; };
|
||||
time["previous"] = []()->double{ return uf::physics::time::previous; };
|
||||
time["delta"] = []()->double{ return uf::physics::time::delta; };
|
||||
time.set("current", UF_LUA_C_FUN(::binds::time::current));
|
||||
time.set("previous", UF_LUA_C_FUN(::binds::time::previous));
|
||||
time.set("delta", UF_LUA_C_FUN(::binds::time::delta));
|
||||
}
|
||||
// `json` table
|
||||
{
|
||||
state["json"]["pretty"] = []( const std::string& json )->std::string{
|
||||
uf::Serializer serializer = json;
|
||||
return serializer.serialize();
|
||||
};
|
||||
state["json"]["readFromFile"] = []( const std::string& filename ){
|
||||
uf::Serializer serializer;
|
||||
serializer.readFromFile( filename );
|
||||
std::string string = serializer.serialize(false);
|
||||
auto decoded = decode( string );
|
||||
return decoded ? decoded.value() : ext::lua::createTable();
|
||||
};
|
||||
state["json"]["writeToFile"] = []( sol::table table, const std::string& path ) {
|
||||
if ( uf::io::extension(path) != "json" ) return false;
|
||||
auto encoded = encode( table );
|
||||
if ( encoded ) {
|
||||
uf::Serializer json = encoded.value();
|
||||
json.writeToFile( path );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
state["json"]["pretty"] = UF_LUA_C_FUN(::binds::json::pretty);
|
||||
state["json"]["readFromFile"] = UF_LUA_C_FUN(::binds::json::readFromFile);
|
||||
state["json"]["writeToFile"] = UF_LUA_C_FUN(::binds::json::writeToFile);
|
||||
}
|
||||
// `window` table
|
||||
{
|
||||
auto window = state["window"].get_or_create<sol::table>();
|
||||
window["keyPressed"] = [](const std::string& name)->bool{
|
||||
return uf::Window::isKeyPressed(name);
|
||||
};
|
||||
window["keyPressed"] = UF_LUA_C_FUN(uf::Window::isKeyPressed);
|
||||
}
|
||||
// `os` table
|
||||
{
|
||||
auto os = state["os"].get_or_create<sol::table>();
|
||||
os["arch"] = UF_LUA_C_FUN(::binds::os::arch);
|
||||
}
|
||||
run(main);
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
#include <uf/ext/lua/lua.h>
|
||||
#if UF_USE_LUA
|
||||
#include <uf/engine/asset/asset.h>
|
||||
UF_LUA_REGISTER_USERTYPE(uf::Asset,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( load, []( uf::Asset& asset, sol::variadic_args va ) {
|
||||
|
||||
namespace binds {
|
||||
void load( uf::Asset& asset, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
std::string callback = "";
|
||||
std::string uri = "";
|
||||
@ -12,12 +13,10 @@ UF_LUA_REGISTER_USERTYPE(uf::Asset,
|
||||
if ( it != va.end() ) uri = *(it++);
|
||||
if ( it != va.end() ) hash = *(it++);
|
||||
if ( it != va.end() ) category = *(it++);
|
||||
if ( callback == "" )
|
||||
asset.load( uri, hash, category );
|
||||
else
|
||||
asset.load( callback, uri, hash, category );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( cache, []( uf::Asset& asset, sol::variadic_args va ) {
|
||||
if ( callback == "" ) asset.load( uri, hash, category );
|
||||
else asset.load( callback, uri, hash, category );
|
||||
}
|
||||
void cache( uf::Asset& asset, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
std::string callback = "";
|
||||
std::string uri = "";
|
||||
@ -31,7 +30,15 @@ UF_LUA_REGISTER_USERTYPE(uf::Asset,
|
||||
asset.cache( uri, hash, category );
|
||||
else
|
||||
asset.cache( callback, uri, hash, category );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Asset::getOriginal )
|
||||
)
|
||||
}
|
||||
std::string getOriginal( uf::Asset& asset, const std::string& n ) {
|
||||
return asset.getOriginal( n );
|
||||
}
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(uf::Asset,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( load, UF_LUA_C_FUN(::binds::load) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( cache, UF_LUA_C_FUN(::binds::cache) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getOriginal, UF_LUA_C_FUN(::binds::getOriginal) )
|
||||
)
|
||||
#endif
|
||||
@ -7,27 +7,27 @@ UF_LUA_REGISTER_USERTYPE(uf::Audio,
|
||||
if ( filename != "" ) self.load(filename);
|
||||
self.setVolume(volume);
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::initialized ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::playing ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::destroy ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::load ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::play ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::stop ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getTime ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setTime ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getDuration ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setPosition ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setOrientation ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setVolume ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getPitch ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setPitch ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getGain ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setGain ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getRolloffFactor ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setRolloffFactor ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getMaxDistance ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setMaxDistance ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getVolume ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getFilename )
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::initialized ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::playing ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::destroy ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::load ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::play ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::stop ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getTime ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setTime ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getDuration ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setPosition ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setOrientation ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setVolume ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getPitch ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setPitch ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getGain ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setGain ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getRolloffFactor ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setRolloffFactor ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getMaxDistance ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setMaxDistance ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getVolume ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getFilename )
|
||||
)
|
||||
#endif
|
||||
@ -1,42 +1,56 @@
|
||||
#include <uf/ext/lua/lua.h>
|
||||
#if UF_USE_LUA
|
||||
#include <uf/utils/camera/camera.h>
|
||||
UF_LUA_REGISTER_USERTYPE(uf::Camera,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getTransform, []( uf::Camera& self ) {
|
||||
|
||||
namespace binds {
|
||||
pod::Transform<>& getTransform( uf::Camera& self ) {
|
||||
return self.getTransform();
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getView, []( const uf::Camera& self, sol::variadic_args va ) {
|
||||
}
|
||||
pod::Matrix4f getView( const uf::Camera& self, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
if ( va.size() > 0 ) {
|
||||
size_t i = *it++;
|
||||
return self.getView(i);
|
||||
}
|
||||
return self.getView();
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getProjection, []( const uf::Camera& self, sol::variadic_args va ) {
|
||||
}
|
||||
pod::Matrix4f getProjection( const uf::Camera& self, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
if ( va.size() > 0 ) {
|
||||
size_t i = *it++;
|
||||
return self.getProjection(i);
|
||||
}
|
||||
return self.getProjection();
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( setView, []( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) {
|
||||
}
|
||||
void setView( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
if ( va.size() > 0 ) {
|
||||
size_t i = *it++;
|
||||
return self.setView(matrix, i);
|
||||
self.setView(matrix, i);
|
||||
} else {
|
||||
self.setView(matrix);
|
||||
}
|
||||
return self.setView(matrix);
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( setProjection, []( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) {
|
||||
}
|
||||
void setProjection( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
if ( va.size() > 0 ) {
|
||||
size_t i = *it++;
|
||||
return self.setProjection(matrix, i);
|
||||
self.setProjection(matrix, i);
|
||||
} else {
|
||||
self.setProjection(matrix);
|
||||
}
|
||||
return self.setProjection(matrix);
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Camera::update )
|
||||
}
|
||||
void update( uf::Camera& self, bool force = true ) {
|
||||
self.update(force);
|
||||
}
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(uf::Camera,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getTransform, UF_LUA_C_FUN(::binds::getTransform) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getView, UF_LUA_C_FUN(::binds::getView) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( setView, UF_LUA_C_FUN(::binds::setView) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getProjection, UF_LUA_C_FUN(::binds::getProjection) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( setProjection, UF_LUA_C_FUN(::binds::setProjection) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( update, UF_LUA_C_FUN(::binds::update) )
|
||||
)
|
||||
#endif
|
||||
@ -2,6 +2,27 @@
|
||||
#if UF_USE_LUA
|
||||
#include <uf/utils/math/matrix.h>
|
||||
|
||||
namespace binds {
|
||||
float index( const pod::Matrix4f& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}
|
||||
pod::Matrix4f translate( const pod::Vector3f& v ) {
|
||||
return uf::matrix::translate( uf::matrix::identity(), v );
|
||||
}
|
||||
pod::Matrix4f scale( const pod::Vector3f& v ) {
|
||||
return uf::matrix::scale( uf::matrix::identity(), v );
|
||||
}
|
||||
pod::Matrix4f multiply( const pod::Matrix4f& left, const pod::Matrix4f& right ) {
|
||||
return uf::matrix::multiply( left, right );
|
||||
}
|
||||
pod::Matrix4f inverse( const pod::Matrix4f& m ) {
|
||||
return uf::matrix::inverse( m );
|
||||
}
|
||||
pod::Matrix4f identity( const pod::Matrix4f& ) {
|
||||
return uf::matrix::identity();
|
||||
}
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(pod::Matrix4f,
|
||||
sol::call_constructor, sol::initializers(
|
||||
[]( pod::Matrix4f& self ) {
|
||||
@ -11,26 +32,12 @@ UF_LUA_REGISTER_USERTYPE(pod::Matrix4f,
|
||||
return self = copy;
|
||||
}
|
||||
),
|
||||
sol::meta_function::multiplication, []( const pod::Matrix4f& left, const pod::Matrix4f& right ) {
|
||||
return uf::matrix::multiply( left, right );
|
||||
},
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( m, []( pod::Matrix4f& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, []( const pod::Matrix4f& left, const pod::Matrix4f& right ) {
|
||||
return uf::matrix::multiply( left, right );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, []( const pod::Matrix4f& m ) {
|
||||
return uf::matrix::inverse( m );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( translate, []( const pod::Vector3f& v ) {
|
||||
return uf::matrix::translate( uf::matrix::identity(), v );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( scale, []( const pod::Vector3f& v ) {
|
||||
return uf::matrix::scale( uf::matrix::identity(), v );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( identity, []( ) {
|
||||
return uf::matrix::identity();
|
||||
})
|
||||
sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::multiply ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( m, UF_LUA_C_FUN( ::binds::index ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, UF_LUA_C_FUN( ::binds::multiply ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, UF_LUA_C_FUN( ::binds::inverse ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( translate, UF_LUA_C_FUN( ::binds::translate ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( scale, UF_LUA_C_FUN( ::binds::scale ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( identity, UF_LUA_C_FUN(uf::matrix::identity<float>) )
|
||||
)
|
||||
#endif
|
||||
@ -7,6 +7,177 @@
|
||||
#include <uf/engine/asset/asset.h>
|
||||
#include <uf/engine/object/behaviors/lua.h>
|
||||
|
||||
namespace binds {
|
||||
std::string formatHookName(uf::Object& self, const std::string n ){
|
||||
return self.formatHookName(n);
|
||||
}
|
||||
sol::object getComponent( uf::Object& self, const std::string& type ) {
|
||||
#define UF_LUA_RETRIEVE_COMPONENT( T )\
|
||||
else if ( type == UF_NS_GET_LAST(T) ) return sol::make_object( ext::lua::state, std::ref(self.getComponent<T>()) );
|
||||
|
||||
if ( type == "Metadata" ) {
|
||||
auto& metadata = self.getComponent<uf::Serializer>();
|
||||
auto decoded = ext::lua::decode( metadata );
|
||||
if ( decoded ) {
|
||||
sol::table table = decoded.value();
|
||||
return sol::make_object( ext::lua::state, table );
|
||||
}
|
||||
}
|
||||
UF_LUA_RETRIEVE_COMPONENT(pod::Transform<>)
|
||||
UF_LUA_RETRIEVE_COMPONENT(uf::Audio)
|
||||
UF_LUA_RETRIEVE_COMPONENT(uf::Asset)
|
||||
UF_LUA_RETRIEVE_COMPONENT(uf::Camera)
|
||||
return sol::make_object( ext::lua::state, sol::lua_nil );
|
||||
}
|
||||
void setComponent(uf::Object& self, const std::string& type, sol::object value ) {
|
||||
#define UF_LUA_UPDATE_COMPONENT( T )\
|
||||
else if ( type == UF_NS_GET_LAST(T) ) self.getComponent<T>() = std::move(value.as<T>());
|
||||
|
||||
if ( type == "Metadata" ) {
|
||||
auto encoded = ext::lua::encode( value.as<sol::table>() );
|
||||
if ( encoded ) {
|
||||
auto& metadata = self.getComponent<uf::Serializer>();
|
||||
std::string str = encoded.value();
|
||||
uf::Serializer hooks = metadata["system"]["hooks"];
|
||||
metadata.merge( str, false );
|
||||
metadata["system"]["hooks"] = hooks;
|
||||
}
|
||||
}
|
||||
UF_LUA_UPDATE_COMPONENT(pod::Transform<>)
|
||||
UF_LUA_UPDATE_COMPONENT(uf::Audio)
|
||||
UF_LUA_UPDATE_COMPONENT(uf::Asset)
|
||||
UF_LUA_UPDATE_COMPONENT(uf::Camera)
|
||||
}
|
||||
bool bind(uf::Object& self, const std::string& type, sol::protected_function fun ) {
|
||||
if ( !self.hasBehavior({.type = uf::LuaBehavior::type}) ) uf::instantiator::bind( "LuaBehavior", self );
|
||||
pod::Behavior* behaviorPointer = NULL;
|
||||
auto& behaviors = self.getBehaviors();
|
||||
for ( auto& b : behaviors ) {
|
||||
if ( b.type != uf::LuaBehavior::type ) continue;
|
||||
behaviorPointer = &b;
|
||||
break;
|
||||
}
|
||||
if ( !behaviorPointer ) return false;
|
||||
pod::Behavior& behavior = *behaviorPointer;
|
||||
|
||||
pod::Behavior::function_t* functionPointer = NULL;
|
||||
if ( type == "initialize" ) functionPointer = &behavior.initialize;
|
||||
else if ( type == "tick" ) functionPointer = &behavior.tick;
|
||||
else if ( type == "render" ) functionPointer = &behavior.render;
|
||||
else if ( type == "destroy" ) functionPointer = &behavior.destroy;
|
||||
|
||||
if ( !functionPointer ) return false;
|
||||
pod::Behavior::function_t& function = *functionPointer;
|
||||
|
||||
function = [fun]( uf::Object& s ) {
|
||||
auto result = fun(s);
|
||||
if ( !result.valid() ) {
|
||||
sol::error err = result;
|
||||
uf::iostream << err.what() << "\n";
|
||||
}
|
||||
};
|
||||
return true;
|
||||
}
|
||||
uf::Object& findByUid( uf::Object& self, const size_t& index ) {
|
||||
auto* pointer = self.findByUid( index );
|
||||
if ( pointer ) return pointer->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
}
|
||||
uf::Object& findByName( uf::Object& self, const std::string& index ){
|
||||
auto* pointer = self.findByName( index );
|
||||
if ( pointer ) return pointer->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
}
|
||||
uf::Object& addChild( uf::Object& self, uf::Object& child ) {
|
||||
self.addChild( child );
|
||||
return self;
|
||||
}
|
||||
uf::Object& removeChild( uf::Object& self, uf::Object& child ){
|
||||
self.removeChild( child );
|
||||
return self;
|
||||
}
|
||||
uf::Object& loadChild( uf::Object& self, const std::string& filename, bool init = true ) {
|
||||
auto* pointer = self.loadChildPointer( filename, init );
|
||||
if ( pointer ) return pointer->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
}
|
||||
sol::table getChildren( uf::Object& self ){
|
||||
sol::table table = ext::lua::createTable();
|
||||
for ( auto* child : self.getChildren() ) {
|
||||
table.add(&child->as<uf::Object>());
|
||||
}
|
||||
return table;
|
||||
}
|
||||
uf::Object& getParent( uf::Object& self ){
|
||||
return self.getParent().as<uf::Object>();
|
||||
}
|
||||
void addHook( uf::Object& self, const std::string& name, const sol::function& function ) {
|
||||
self.addHook( name, [function](ext::json::Value& json){
|
||||
std::string payload = json.dump();
|
||||
auto decoded = ext::lua::decode( payload );
|
||||
if ( !decoded ) return;
|
||||
sol::table table = decoded.value();
|
||||
auto result = function( table );
|
||||
if ( !result.valid() ) {
|
||||
sol::error err = result;
|
||||
uf::iostream << err.what() << "\n";
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
void callHook( uf::Object& self, const std::string& name, sol::table table = ext::lua::createTable() ) {
|
||||
uf::Serializer payload = table;
|
||||
self.callHook( name, (ext::json::Value&) payload );
|
||||
}
|
||||
void queueHook( uf::Object& self, const std::string& name, sol::table table, float delay = 0.0f ) {
|
||||
uf::Serializer payload = table;
|
||||
self.queueHook( name, (ext::json::Value&) payload, delay );
|
||||
}
|
||||
std::string toString( uf::Object& self ) {
|
||||
return self.getName() + ": " + std::to_string( self.getUid() );
|
||||
}
|
||||
|
||||
size_t getUid( const uf::Object& o ) { return o.getUid(); }
|
||||
std::string getName( const uf::Object& o ) { return o.getName(); }
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(uf::Object,
|
||||
sol::call_constructor, sol::initializers(
|
||||
[]( uf::Object& self, sol::object arg, bool init = true ){
|
||||
if ( arg.is<std::string>() ) {
|
||||
self.load( arg.as<std::string>() );
|
||||
} else if ( arg.is<sol::table>() ) {
|
||||
auto encoded = ext::lua::encode( arg.as<sol::table>() );
|
||||
if ( encoded ) {
|
||||
uf::Serializer json = encoded.value();
|
||||
self.load(json);
|
||||
}
|
||||
}
|
||||
if ( init ) self.initialize();
|
||||
}
|
||||
),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( uid, UF_LUA_C_FUN(::binds::getUid) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( name, UF_LUA_C_FUN(::binds::getName) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( formatHookName, UF_LUA_C_FUN(::binds::formatHookName) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponent) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( setComponent, UF_LUA_C_FUN(::binds::setComponent) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( bind, UF_LUA_C_FUN(::binds::bind) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( findByUid, UF_LUA_C_FUN(::binds::findByUid) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( findByName, UF_LUA_C_FUN(::binds::findByName) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( addChild, UF_LUA_C_FUN(::binds::addChild) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( removeChild, UF_LUA_C_FUN(::binds::removeChild) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( loadChild, UF_LUA_C_FUN(::binds::loadChild) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getChildren, UF_LUA_C_FUN(::binds::getChildren) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getParent, UF_LUA_C_FUN(::binds::getParent) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( addHook, UF_LUA_C_FUN(::binds::addHook) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( callHook, UF_LUA_C_FUN(::binds::callHook) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( queueHook, UF_LUA_C_FUN(::binds::queueHook) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::toString) )
|
||||
)
|
||||
/*
|
||||
namespace {
|
||||
static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{
|
||||
ext::lua::onInitialization( []{
|
||||
@ -21,145 +192,28 @@ namespace {
|
||||
self.load(json);
|
||||
}
|
||||
}
|
||||
if ( init ) {
|
||||
self.initialize();
|
||||
}
|
||||
if ( init ) self.initialize();
|
||||
}),
|
||||
"uid", &uf::Object::getUid ,
|
||||
"name", &uf::Object::getName ,
|
||||
"formatHookName", [](uf::Object& self, const std::string n ){
|
||||
return self.formatHookName(n);
|
||||
},
|
||||
"getComponent", [](uf::Object& self, const std::string& type )->sol::object{
|
||||
#define UF_LUA_RETRIEVE_COMPONENT( T )\
|
||||
if ( type == UF_NS_GET_LAST(T) ) return sol::make_object( ext::lua::state, std::ref(self.getComponent<T>()) );
|
||||
|
||||
if ( type == "Metadata" ) {
|
||||
auto& metadata = self.getComponent<uf::Serializer>();
|
||||
auto decoded = ext::lua::decode( metadata );
|
||||
if ( decoded ) {
|
||||
sol::table table = decoded.value();
|
||||
return sol::make_object( ext::lua::state, table );
|
||||
}
|
||||
}
|
||||
UF_LUA_RETRIEVE_COMPONENT(pod::Transform<>)
|
||||
UF_LUA_RETRIEVE_COMPONENT(uf::Audio)
|
||||
UF_LUA_RETRIEVE_COMPONENT(uf::Asset)
|
||||
UF_LUA_RETRIEVE_COMPONENT(uf::Camera)
|
||||
return sol::make_object( ext::lua::state, sol::lua_nil );
|
||||
},
|
||||
"setComponent", [](uf::Object& self, const std::string& type, sol::object value ) {
|
||||
#define UF_LUA_UPDATE_COMPONENT( T )\
|
||||
else if ( type == UF_NS_GET_LAST(T) ) self.getComponent<T>() = std::move(value.as<T>());
|
||||
|
||||
if ( type == "Metadata" ) {
|
||||
auto encoded = ext::lua::encode( value.as<sol::table>() );
|
||||
if ( encoded ) {
|
||||
auto& metadata = self.getComponent<uf::Serializer>();
|
||||
std::string str = encoded.value();
|
||||
uf::Serializer hooks = metadata["system"]["hooks"];
|
||||
metadata.merge( str, false );
|
||||
metadata["system"]["hooks"] = hooks;
|
||||
}
|
||||
}
|
||||
UF_LUA_UPDATE_COMPONENT(pod::Transform<>)
|
||||
UF_LUA_UPDATE_COMPONENT(uf::Audio)
|
||||
UF_LUA_UPDATE_COMPONENT(uf::Asset)
|
||||
UF_LUA_UPDATE_COMPONENT(uf::Camera)
|
||||
},
|
||||
"bind", [](uf::Object& self, const std::string& type, sol::protected_function fun ) {
|
||||
if ( !self.hasBehavior({.type = uf::LuaBehavior::type}) ) uf::instantiator::bind( "LuaBehavior", self );
|
||||
pod::Behavior* behaviorPointer = NULL;
|
||||
auto& behaviors = self.getBehaviors();
|
||||
for ( auto& b : behaviors ) {
|
||||
if ( b.type != uf::LuaBehavior::type ) continue;
|
||||
behaviorPointer = &b;
|
||||
break;
|
||||
}
|
||||
if ( !behaviorPointer ) return false;
|
||||
pod::Behavior& behavior = *behaviorPointer;
|
||||
|
||||
pod::Behavior::function_t* functionPointer = NULL;
|
||||
if ( type == "initialize" ) functionPointer = &behavior.initialize;
|
||||
else if ( type == "tick" ) functionPointer = &behavior.tick;
|
||||
else if ( type == "render" ) functionPointer = &behavior.render;
|
||||
else if ( type == "destroy" ) functionPointer = &behavior.destroy;
|
||||
|
||||
if ( !functionPointer ) return false;
|
||||
pod::Behavior::function_t& function = *functionPointer;
|
||||
|
||||
function = [fun]( uf::Object& s ) {
|
||||
auto result = fun(s);
|
||||
if ( !result.valid() ) {
|
||||
sol::error err = result;
|
||||
uf::iostream << err.what() << "\n";
|
||||
}
|
||||
};
|
||||
return true;
|
||||
},
|
||||
"findByUid", []( uf::Object& self, const size_t& index )->uf::Object&{
|
||||
auto* pointer = self.findByUid( index );
|
||||
if ( pointer ) return pointer->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
},
|
||||
"findByName", []( uf::Object& self, const std::string& index )->uf::Object&{
|
||||
auto* pointer = self.findByName( index );
|
||||
if ( pointer ) return pointer->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
},
|
||||
"addChild", []( uf::Object& self, uf::Object& child )->uf::Object&{
|
||||
self.addChild( child );
|
||||
return self;
|
||||
},
|
||||
"removeChild", []( uf::Object& self, uf::Object& child )->uf::Object&{
|
||||
self.removeChild( child );
|
||||
return self;
|
||||
},
|
||||
"loadChild", []( uf::Object& self, const std::string& filename, bool init = true )->uf::Object&{
|
||||
auto* pointer = self.loadChildPointer( filename, init );
|
||||
if ( pointer ) return pointer->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
},
|
||||
"getChildren", []( uf::Object& self )->sol::table{
|
||||
sol::table table = ext::lua::createTable();
|
||||
for ( auto* child : self.getChildren() ) {
|
||||
table.add(&child->as<uf::Object>());
|
||||
}
|
||||
return table;
|
||||
},
|
||||
"getParent", []( uf::Object& self )->uf::Object&{
|
||||
return self.getParent().as<uf::Object>();
|
||||
},
|
||||
"addHook", []( uf::Object& self, const std::string& name, const sol::function& function ) {
|
||||
self.addHook( name, [function](ext::json::Value& json){
|
||||
std::string payload = json.dump();
|
||||
auto decoded = ext::lua::decode( payload );
|
||||
if ( !decoded ) return;
|
||||
sol::table table = decoded.value();
|
||||
auto result = function( table );
|
||||
if ( !result.valid() ) {
|
||||
sol::error err = result;
|
||||
uf::iostream << err.what() << "\n";
|
||||
return;
|
||||
}
|
||||
});
|
||||
},
|
||||
"callHook", []( uf::Object& self, const std::string& name, sol::table table = ext::lua::createTable() ) {
|
||||
uf::Serializer payload = table;
|
||||
self.callHook( name, (ext::json::Value&) payload );
|
||||
},
|
||||
"queueHook", []( uf::Object& self, const std::string& name, sol::table table, float delay = 0.0f ) {
|
||||
uf::Serializer payload = table;
|
||||
self.queueHook( name, (ext::json::Value&) payload, delay );
|
||||
},
|
||||
"__tostring", []( uf::Object& self ) {
|
||||
return self.getName() + ": " + std::to_string( self.getUid() );
|
||||
}
|
||||
"uid", UF_LUA_C_FUN(::binds::getUid),
|
||||
"name", UF_LUA_C_FUN(::binds::getName),
|
||||
"formatHookName", UF_LUA_C_FUN(::binds::formatHookName),
|
||||
"getComponent", UF_LUA_C_FUN(::binds::getComponent),
|
||||
"setComponent", UF_LUA_C_FUN(::binds::setComponent),
|
||||
"bind", UF_LUA_C_FUN(::binds::bind),
|
||||
"findByUid", UF_LUA_C_FUN(::binds::findByUid),
|
||||
"findByName", UF_LUA_C_FUN(::binds::findByName),
|
||||
"addChild", UF_LUA_C_FUN(::binds::addChild),
|
||||
"removeChild", UF_LUA_C_FUN(::binds::removeChild),
|
||||
"loadChild", UF_LUA_C_FUN(::binds::loadChild),
|
||||
"getChildren", UF_LUA_C_FUN(::binds::getChildren),
|
||||
"getParent", UF_LUA_C_FUN(::binds::getParent),
|
||||
"addHook", UF_LUA_C_FUN(::binds::addHook),
|
||||
"callHook", UF_LUA_C_FUN(::binds::callHook),
|
||||
"queueHook", UF_LUA_C_FUN(::binds::queueHook),
|
||||
"__tostring", UF_LUA_C_FUN(::binds::toString)
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
@ -2,6 +2,60 @@
|
||||
#if UF_USE_LUA
|
||||
#include <uf/utils/math/quaternion.h>
|
||||
|
||||
namespace binds {
|
||||
float index( const pod::Quaternion<>& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}
|
||||
pod::Quaternion<> lookAt( const pod::Vector3f& at, const pod::Vector3f& up ) {
|
||||
return uf::quaternion::lookAt( at, up );
|
||||
}
|
||||
pod::Quaternion<> normalize( const pod::Quaternion<>& self ) {
|
||||
return uf::quaternion::normalize( self );
|
||||
}
|
||||
pod::Quaternion<> multiply( const pod::Quaternion<>& left, const pod::Quaternion<>& right ) {
|
||||
return uf::quaternion::multiply( left, right );
|
||||
}
|
||||
pod::Quaternion<> axisAngle( sol::object arg, float angle ){
|
||||
if ( arg.is<pod::Vector3f>() ) {
|
||||
return uf::quaternion::axisAngle( arg.as<pod::Vector3f>(), angle );
|
||||
} else if ( arg.is<sol::table>() ) {
|
||||
sol::table table = arg.as<sol::table>();
|
||||
return uf::quaternion::axisAngle( pod::Vector3f{ table[0], table[1], table[2] }, angle );
|
||||
}
|
||||
return pod::Quaternion<>{};
|
||||
}
|
||||
pod::Vector3f rotate( const pod::Quaternion<>& left, const pod::Vector3f& right ) {
|
||||
return uf::quaternion::rotate( left, right );
|
||||
}
|
||||
pod::Quaternion<> eulerAngles( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::eulerAngles( quaternion );
|
||||
}
|
||||
pod::Quaternion<> conjugate( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::conjugate( quaternion );
|
||||
}
|
||||
pod::Quaternion<> inverse( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::inverse( quaternion );
|
||||
}
|
||||
float pitch( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::pitch( quaternion );
|
||||
}
|
||||
float yaw( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::yaw( quaternion );
|
||||
}
|
||||
float roll( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::roll( quaternion );
|
||||
}
|
||||
pod::Quaternion<> slerp( const pod::Quaternion<>& left, const pod::Quaternion<>& right, float a ) {
|
||||
return uf::quaternion::slerp( left, right, a );
|
||||
}
|
||||
pod::Matrix4f matrix( const pod::Quaternion<>& q ) {
|
||||
return uf::quaternion::matrix( q );
|
||||
}
|
||||
std::string __tostring( const pod::Quaternion<>& self ) {
|
||||
return uf::string::toString( self );
|
||||
}
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(pod::Quaternion<>,
|
||||
sol::call_constructor, sol::initializers(
|
||||
[]( pod::Quaternion<>& self ) {
|
||||
@ -14,63 +68,27 @@ UF_LUA_REGISTER_USERTYPE(pod::Quaternion<>,
|
||||
return self = uf::vector::create(x, y, z, w);
|
||||
}
|
||||
),
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::x),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::y),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::z),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::w),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(v, []( pod::Quaternion<>& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( lookAt, []( const pod::Vector3f& source, const pod::Vector3f& destination ) {
|
||||
return uf::quaternion::lookAt( source, destination );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Quaternion<>& self ) {
|
||||
return uf::quaternion::normalize( self );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, []( const pod::Quaternion<>& left, const pod::Quaternion<>& right ) {
|
||||
return uf::quaternion::multiply( left, right );
|
||||
}),
|
||||
sol::meta_function::multiplication, []( const pod::Quaternion<>& left, const pod::Quaternion<>& right ) {
|
||||
return uf::quaternion::multiply( left, right );
|
||||
},
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(axisAngle, []( sol::object arg, float angle ){
|
||||
if ( arg.is<pod::Vector3f>() ) {
|
||||
return uf::quaternion::axisAngle( arg.as<pod::Vector3f>(), angle );
|
||||
} else if ( arg.is<sol::table>() ) {
|
||||
sol::table table = arg.as<sol::table>();
|
||||
return uf::quaternion::axisAngle( pod::Vector3f{ table[0], table[1], table[2] }, angle );
|
||||
}
|
||||
return pod::Quaternion<>{};
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( rotate, []( const pod::Quaternion<>& left, const pod::Vector3f& right ) {
|
||||
return uf::quaternion::rotate( left, right );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( eulerAngles, []( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::eulerAngles( quaternion );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( conjugate, []( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::conjugate( quaternion );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, []( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::inverse( quaternion );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( pitch, []( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::pitch( quaternion );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( yaw, []( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::yaw( quaternion );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( roll, []( const pod::Quaternion<>& quaternion ) {
|
||||
return uf::quaternion::roll( quaternion );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( slerp, []( const pod::Quaternion<>& left, const pod::Quaternion<>& right, float a ) {
|
||||
return uf::quaternion::slerp( left, right, a );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( matrix, []( const pod::Quaternion<>& q ) {
|
||||
return uf::quaternion::matrix( q );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( const pod::Quaternion<>& self ) {
|
||||
return uf::string::toString( self );
|
||||
})
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( v, UF_LUA_C_FUN(::binds::index) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( lookAt, UF_LUA_C_FUN(::binds::lookAt) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, UF_LUA_C_FUN(::binds::normalize) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, UF_LUA_C_FUN(::binds::multiply) ),
|
||||
sol::meta_function::multiplication, UF_LUA_C_FUN(::binds::multiply),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(axisAngle, UF_LUA_C_FUN(::binds::axisAngle) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( rotate, UF_LUA_C_FUN( ::binds::rotate ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( eulerAngles, UF_LUA_C_FUN( ::binds::eulerAngles ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( conjugate, UF_LUA_C_FUN( ::binds::conjugate ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, UF_LUA_C_FUN( ::binds::inverse ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( pitch, UF_LUA_C_FUN( ::binds::pitch ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( yaw, UF_LUA_C_FUN( ::binds::yaw ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( roll, UF_LUA_C_FUN( ::binds::roll ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( slerp, UF_LUA_C_FUN( ::binds::slerp ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( matrix, UF_LUA_C_FUN( ::binds::matrix ) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN( ::binds::__tostring ) )
|
||||
)
|
||||
#endif
|
||||
@ -2,14 +2,21 @@
|
||||
#if UF_USE_LUA
|
||||
#include <uf/utils/math/physics.h>
|
||||
|
||||
namespace binds {
|
||||
double elapsed( uf::Timer<>& self ) { return self.elapsed().asDouble(); }
|
||||
void start( uf::Timer<>& self ) { return self.start(); }
|
||||
void stop( uf::Timer<>& self ) { return self.stop(); }
|
||||
void reset( uf::Timer<>& self ) { return self.reset(); }
|
||||
void update( uf::Timer<>& self ) { return self.update(); }
|
||||
bool running( uf::Timer<>& self ) { return self.running(); }
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(uf::Timer<>,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( elapsed, []( uf::Timer<>& self ) {
|
||||
return self.elapsed().asDouble();
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::start ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::stop ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::reset ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::update ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::running )
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( elapsed, UF_LUA_C_FUN(::binds::elapsed) ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::start ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::stop ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::reset ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::update ),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::running )
|
||||
)
|
||||
#endif
|
||||
@ -2,15 +2,8 @@
|
||||
#if UF_USE_LUA
|
||||
#include <uf/utils/math/transform.h>
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(pod::Transform<>,
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::up),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::right),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::forward),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::orientation),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::model),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(move, []( pod::Transform<>& self, sol::variadic_args va ) {
|
||||
namespace binds {
|
||||
void move( pod::Transform<>& self, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
if ( va.size() == 1 ) {
|
||||
pod::Vector3f delta = *it++;
|
||||
@ -20,8 +13,8 @@ UF_LUA_REGISTER_USERTYPE(pod::Transform<>,
|
||||
double delta = *it++;
|
||||
self = uf::transform::move( self, axis, delta );
|
||||
}
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(rotate, []( pod::Transform<>& self, sol::variadic_args va ) {
|
||||
}
|
||||
void rotate( pod::Transform<>& self, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
if ( va.size() == 1 ) {
|
||||
pod::Quaternion<> delta = *it++;
|
||||
@ -31,22 +24,40 @@ UF_LUA_REGISTER_USERTYPE(pod::Transform<>,
|
||||
double delta = *it++;
|
||||
self = uf::transform::rotate( self, axis, delta );
|
||||
}
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(flatten, []( const pod::Transform<>& t ) {
|
||||
return uf::transform::flatten(t);
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(reorient, []( const pod::Transform<>& t ) {
|
||||
}
|
||||
pod::Transform<> flatten( const pod::Transform<>& t ) {
|
||||
return uf::transform::flatten( t );
|
||||
}
|
||||
pod::Transform<> reorient( const pod::Transform<>& t ) {
|
||||
return uf::transform::reorient( t );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(getReference, []( pod::Transform<>& t ) {
|
||||
}
|
||||
pod::Transform<> getReference( pod::Transform<>& t ) {
|
||||
return t.reference ? *t.reference : t;
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(lookAt, []( const pod::Transform<>& t, pod::Vector3f& at ) {
|
||||
}
|
||||
pod::Transform<> lookAt( const pod::Transform<>& t, pod::Vector3f& at ) {
|
||||
auto transform = t;
|
||||
return uf::transform::lookAt( transform, at );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(getModel, []( const pod::Transform<>& t ) {
|
||||
}
|
||||
pod::Matrix4f getModel( const pod::Transform<>& t ) {
|
||||
return uf::transform::model( t );
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(pod::Transform<>,
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::up),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::right),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::forward),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::orientation),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::model),
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(move, UF_LUA_C_FUN(::binds::move) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(rotate, UF_LUA_C_FUN(::binds::rotate)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(flatten, UF_LUA_C_FUN(::binds::flatten)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(reorient, UF_LUA_C_FUN(::binds::reorient)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(getReference, UF_LUA_C_FUN(::binds::getReference)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(lookAt, UF_LUA_C_FUN(::binds::lookAt)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(getModel, UF_LUA_C_FUN(::binds::getModel))
|
||||
)
|
||||
#endif
|
||||
@ -2,6 +2,91 @@
|
||||
#if UF_USE_LUA
|
||||
#include <uf/utils/math/vector.h>
|
||||
|
||||
namespace binds {
|
||||
namespace v3f {
|
||||
float index( const pod::Vector3f& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}
|
||||
float distance( pod::Vector3f& self, const pod::Vector3f& other ) {
|
||||
return uf::vector::distance( self, other );
|
||||
}
|
||||
pod::Vector3f add( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::add( left, right );
|
||||
}
|
||||
pod::Vector3f sub( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::subtract( left, right );
|
||||
}
|
||||
pod::Vector3f mul( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
}
|
||||
pod::Vector3f div( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
}
|
||||
pod::Vector3f mulS( const pod::Vector3f& left, float right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
}
|
||||
pod::Vector3f divS( const pod::Vector3f& left, float right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
}
|
||||
pod::Vector3f lerp( const pod::Vector3f& start, const pod::Vector3f& end, double delta ) {
|
||||
return uf::vector::lerp( start, end, delta );
|
||||
}
|
||||
pod::Vector3f normalize( const pod::Vector3f& self ) {
|
||||
return uf::vector::normalize( self );
|
||||
}
|
||||
float magnitude( const pod::Vector3f& self ) {
|
||||
return uf::vector::magnitude( self );
|
||||
}
|
||||
float dot( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::dot( left, right );
|
||||
}
|
||||
std::string toString( pod::Vector3f& self ) {
|
||||
return uf::string::toString( self );
|
||||
}
|
||||
}
|
||||
namespace v4f {
|
||||
float index( const pod::Vector4f& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}
|
||||
float distance( pod::Vector4f& self, const pod::Vector4f& other ) {
|
||||
return uf::vector::distance( self, other );
|
||||
}
|
||||
pod::Vector4f add( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::add( left, right );
|
||||
}
|
||||
pod::Vector4f sub( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::subtract( left, right );
|
||||
}
|
||||
pod::Vector4f mul( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
}
|
||||
pod::Vector4f div( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
}
|
||||
pod::Vector4f mulS( const pod::Vector4f& left, float right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
}
|
||||
pod::Vector4f divS( const pod::Vector4f& left, float right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
}
|
||||
pod::Vector4f lerp( const pod::Vector4f& start, const pod::Vector4f& end, double delta ) {
|
||||
return uf::vector::lerp( start, end, delta );
|
||||
}
|
||||
pod::Vector4f normalize( const pod::Vector4f& self ) {
|
||||
return uf::vector::normalize( self );
|
||||
}
|
||||
float magnitude( const pod::Vector4f& self ) {
|
||||
return uf::vector::magnitude( self );
|
||||
}
|
||||
float dot( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::dot( left, right );
|
||||
}
|
||||
std::string toString( pod::Vector4f& self ) {
|
||||
return uf::string::toString( self );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(pod::Vector3f,
|
||||
sol::call_constructor, sol::initializers(
|
||||
[]( pod::Vector3f& self ) {
|
||||
@ -17,45 +102,20 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector3f,
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector3f::x),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector3f::y),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector3f::z),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( v, []( pod::Vector3f& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( distance, []( pod::Vector3f& self, const pod::Vector3f& other ) {
|
||||
return uf::vector::distance( self, other );
|
||||
}),
|
||||
sol::meta_function::addition, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::add( left, right );
|
||||
},
|
||||
sol::meta_function::subtraction, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::subtract( left, right );
|
||||
},
|
||||
sol::meta_function::multiplication, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
},
|
||||
sol::meta_function::multiplication, []( const pod::Vector3f& left, double right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
},
|
||||
sol::meta_function::division, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
},
|
||||
sol::meta_function::division, []( const pod::Vector3f& left, double right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
},
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, []( const pod::Vector3f& start, const pod::Vector3f& end, double delta ) {
|
||||
return uf::vector::lerp( start, end, delta );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Vector3f& self ) {
|
||||
return uf::vector::normalize( self );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) {
|
||||
return uf::vector::magnitude( self );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::dot( left, right );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector3f& self ) {
|
||||
return uf::string::toString( self );
|
||||
})
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( v, UF_LUA_C_FUN( ::binds::v3f::index )),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( distance, UF_LUA_C_FUN( ::binds::v3f::distance )),
|
||||
sol::meta_function::addition, UF_LUA_C_FUN( ::binds::v3f::add ),
|
||||
sol::meta_function::subtraction, UF_LUA_C_FUN( ::binds::v3f::sub ),
|
||||
sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v3f::mul ),
|
||||
sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v3f::mulS ),
|
||||
sol::meta_function::division, UF_LUA_C_FUN( ::binds::v3f::div ),
|
||||
sol::meta_function::division, UF_LUA_C_FUN( ::binds::v3f::divS ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, UF_LUA_C_FUN(::binds::v3f::lerp) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, UF_LUA_C_FUN(::binds::v3f::normalize) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, UF_LUA_C_FUN(::binds::v3f::magnitude) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, UF_LUA_C_FUN(::binds::v3f::dot) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::v3f::toString) )
|
||||
)
|
||||
UF_LUA_REGISTER_USERTYPE(pod::Vector4f,
|
||||
sol::call_constructor, sol::initializers(
|
||||
@ -73,47 +133,19 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector4f,
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector4f::y),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector4f::z),
|
||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector4f::w),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( v, []( pod::Vector4f& self, const size_t& index ) {
|
||||
return self[index];
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( distance, []( pod::Vector4f& self, const pod::Vector4f& other ) {
|
||||
return uf::vector::distance( self, other );
|
||||
}),
|
||||
sol::meta_function::addition, []( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::add( left, right );
|
||||
},
|
||||
sol::meta_function::subtraction, []( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::subtract( left, right );
|
||||
},
|
||||
sol::meta_function::multiplication, []( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
},
|
||||
sol::meta_function::multiplication, []( const pod::Vector4f& left, double right ) {
|
||||
return uf::vector::multiply( left, right );
|
||||
},
|
||||
sol::meta_function::division, []( const pod::Vector4f& left, const pod::Vector4f& right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
},
|
||||
sol::meta_function::division, []( const pod::Vector4f& left, double right ) {
|
||||
return uf::vector::divide( left, right );
|
||||
},
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, []( const pod::Vector4f& start, const pod::Vector4f& end, double delta ) {
|
||||
return uf::vector::lerp( start, end, delta );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( slerp, []( const pod::Vector4f& start, const pod::Vector4f& end, double delta ) {
|
||||
return uf::vector::slerp( start, end, delta );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Vector3f& self ) {
|
||||
return uf::vector::normalize( self );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) {
|
||||
return uf::vector::magnitude( self );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, []( const pod::Vector3f& left, const pod::Vector3f& right ) {
|
||||
return uf::vector::dot( left, right );
|
||||
}),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector4f& self ) {
|
||||
return uf::string::toString( self );
|
||||
})
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( v, UF_LUA_C_FUN( ::binds::v4f::index )),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( distance, UF_LUA_C_FUN( ::binds::v4f::distance )),
|
||||
sol::meta_function::addition, UF_LUA_C_FUN( ::binds::v4f::add ),
|
||||
sol::meta_function::subtraction, UF_LUA_C_FUN( ::binds::v4f::sub ),
|
||||
sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v4f::mul ),
|
||||
sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v4f::mulS ),
|
||||
sol::meta_function::division, UF_LUA_C_FUN( ::binds::v4f::div ),
|
||||
sol::meta_function::division, UF_LUA_C_FUN( ::binds::v4f::divS ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, UF_LUA_C_FUN(::binds::v4f::lerp) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, UF_LUA_C_FUN(::binds::v4f::normalize) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, UF_LUA_C_FUN(::binds::v4f::magnitude) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, UF_LUA_C_FUN(::binds::v4f::dot) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::v4f::toString) )
|
||||
)
|
||||
#endif
|
||||
@ -359,7 +359,7 @@ size_t ext::opengl::CommandBuffer::size() const {
|
||||
return infos.size();
|
||||
}
|
||||
|
||||
void ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer::Descriptor& descriptor ) {
|
||||
pod::Matrix4f ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer::Descriptor& descriptor ) {
|
||||
#if UF_USE_OPENGL_FIXED_FUNCTION
|
||||
pod::Uniform* uniform = (pod::Uniform*) (device->getBuffer( descriptor.buffer ) + descriptor.offset);
|
||||
|
||||
@ -368,6 +368,8 @@ void ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer::Descrip
|
||||
|
||||
GL_ERROR_CHECK(glMatrixMode(GL_MODELVIEW));
|
||||
GL_ERROR_CHECK(glLoadMatrixf( &uniform->modelView[0] ));
|
||||
|
||||
return uniform->projection * uniform->modelView;
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
@ -529,7 +531,7 @@ void ext::opengl::CommandBuffer::draw( const ext::opengl::CommandBuffer::InfoDra
|
||||
}
|
||||
#endif
|
||||
void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::InfoDraw& drawInfo ) {
|
||||
bindUniform( drawInfo.uniformBuffer );
|
||||
auto projectionViewMatrix = bindUniform( drawInfo.uniformBuffer );
|
||||
|
||||
size_t indices = drawInfo.descriptor.indices;
|
||||
size_t indicesStride = drawInfo.descriptor.geometry.attributes.index.size;
|
||||
@ -543,6 +545,12 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
|
||||
GL_ERROR_CHECK(glFrontFace(drawInfo.descriptor.frontFace));
|
||||
GL_ERROR_CHECK(glCullFace(drawInfo.descriptor.cullMode));
|
||||
}
|
||||
if ( drawInfo.descriptor.depth.test ) {
|
||||
GL_ERROR_CHECK(glEnable(GL_DEPTH_TEST));
|
||||
} else {
|
||||
GL_ERROR_CHECK(glDisable(GL_DEPTH_TEST));
|
||||
}
|
||||
GL_ERROR_CHECK(glDepthMask(drawInfo.descriptor.depth.write ? GL_TRUE : GL_FALSE));
|
||||
|
||||
// CPU-buffer based command dispatching
|
||||
void* vertexPointer = (void*) ( device->getBuffer( drawInfo.vertexBuffer.buffer ) + drawInfo.vertexBuffer.offset );
|
||||
@ -586,7 +594,47 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
|
||||
if ( drawInfo.attributes.color ) GL_ERROR_CHECK(glColorPointer(3, GL_FLOAT, vertexStride, vertexPointer + drawInfo.attributes.color));
|
||||
GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, vertexStride, vertexPointer + drawInfo.attributes.position));
|
||||
|
||||
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, indices, indicesType, indicesPointer));
|
||||
// frustrum culling
|
||||
if ( ext::opengl::settings::experimental::frustrumCull ) {
|
||||
std::vector<uf::renderer::index_t> unculled;
|
||||
unculled.reserve(indices);
|
||||
for ( size_t currentIndex = 0; currentIndex < indices; currentIndex += 3 ) {
|
||||
const pod::Vector3f& positionA = *((pod::Vector3f*) ((vertexPointer + (indicesPointer[currentIndex+0] * vertexStride)) + drawInfo.attributes.position));
|
||||
const pod::Vector3f& positionB = *((pod::Vector3f*) ((vertexPointer + (indicesPointer[currentIndex+2] * vertexStride)) + drawInfo.attributes.position));
|
||||
const pod::Vector3f& positionC = *((pod::Vector3f*) ((vertexPointer + (indicesPointer[currentIndex+1] * vertexStride)) + drawInfo.attributes.position));
|
||||
|
||||
bool inside = false;
|
||||
pod::Vector3f translated = uf::matrix::multiply<float>( projectionViewMatrix, positionA, 1, true );
|
||||
static constexpr pod::Vector3f min{-1.5,-1.5,-1.5};
|
||||
static constexpr pod::Vector3f max{ 1.5, 1.5, 1.5};
|
||||
if ( min.x <= translated.x && min.y <= translated.y && min.z <= translated.z && translated.x <= max.x && translated.y <= max.y && translated.z <= max.z ) inside = true;
|
||||
// if ( min <= translated && translated <= max ) inside = true;
|
||||
else {
|
||||
pod::Vector3f translated = uf::matrix::multiply<float>( projectionViewMatrix, positionB, 1, true );
|
||||
if ( min.x <= translated.x && min.y <= translated.y && min.z <= translated.z && translated.x <= max.x && translated.y <= max.y && translated.z <= max.z ) inside = true;
|
||||
// if ( min <= translated && translated <= max ) inside = true;
|
||||
else {
|
||||
pod::Vector3f translated = uf::matrix::multiply<float>( projectionViewMatrix, positionC, 1, true );
|
||||
if ( min.x <= translated.x && min.y <= translated.y && min.z <= translated.z && translated.x <= max.x && translated.y <= max.y && translated.z <= max.z ) inside = true;
|
||||
// if ( min <= translated && translated <= max ) inside = true;
|
||||
}
|
||||
}
|
||||
if ( inside ) {
|
||||
unculled.emplace_back(indicesPointer[currentIndex+0]);
|
||||
unculled.emplace_back(indicesPointer[currentIndex+1]);
|
||||
unculled.emplace_back(indicesPointer[currentIndex+2]);
|
||||
}
|
||||
}
|
||||
GLenum indicesType = GL_UNSIGNED_INT;
|
||||
switch ( sizeof(uf::renderer::index_t) ) {
|
||||
case sizeof(uint32_t): indicesType = GL_UNSIGNED_INT; break;
|
||||
case sizeof(uint16_t): indicesType = GL_UNSIGNED_SHORT; break;
|
||||
case sizeof(uint8_t): indicesType = GL_UNSIGNED_BYTE; break;
|
||||
}
|
||||
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, unculled.size(), indicesType, &unculled[0]));
|
||||
} else {
|
||||
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, indices, indicesType, indicesPointer));
|
||||
}
|
||||
|
||||
if ( drawInfo.auxTexture.image ) {
|
||||
#if UF_ENV_DREAMCAST
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include <uf/ext/opengl/opengl.h>
|
||||
#include <uf/ext/opengl/commands.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
|
||||
#if 0
|
||||
#include <spirv_cross/spirv_cross.hpp>
|
||||
@ -1362,7 +1363,6 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, size_t pass, si
|
||||
return this->record( commandBuffer, descriptor, pass, draw );
|
||||
}
|
||||
|
||||
#include <uf/ext/gltf/mesh.h>
|
||||
void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescriptor& descriptor, size_t pass, size_t draw ) {
|
||||
if ( !process ) return;
|
||||
#if 0
|
||||
@ -1376,20 +1376,17 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript
|
||||
return;
|
||||
}
|
||||
pipeline.record(*this, commandBuffer, pass, draw);
|
||||
#endif
|
||||
int32_t vertexBufferIndex = -1;
|
||||
int32_t uniformBufferIndex = -1;
|
||||
int32_t storageBufferIndex = -1;
|
||||
#endif
|
||||
Buffer::Descriptor vertexBuffer = {};
|
||||
Buffer::Descriptor indexBuffer = {};
|
||||
Buffer::Descriptor uniformBuffer = {};
|
||||
size_t vertexBufferSize = {};
|
||||
size_t indexBufferSize = {};
|
||||
size_t uniformBufferSize = {};
|
||||
std::vector<Buffer::Descriptor> storageBuffers;
|
||||
|
||||
for ( auto& buffer : buffers ) {
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::VERTEX ) { vertexBuffer = buffer.descriptor; vertexBufferSize = buffer.size; }
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::INDEX ) { indexBuffer = buffer.descriptor; indexBufferSize = buffer.size; }
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) { uniformBuffer = buffer.descriptor; uniformBufferSize = buffer.size; }
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::VERTEX ) { vertexBuffer = buffer.descriptor; }
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::INDEX ) { indexBuffer = buffer.descriptor; }
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) { uniformBuffer = buffer.descriptor; }
|
||||
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) { storageBuffers.emplace_back(buffer.descriptor); }
|
||||
}
|
||||
if ( !vertexBuffer.buffer || !indexBuffer.buffer ) return;
|
||||
|
||||
@ -1403,7 +1400,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript
|
||||
for ( auto& attribute : descriptor.geometry.attributes.descriptor ) {
|
||||
if ( attribute.name == "position" ) vertexAttributePosition = attribute;
|
||||
// else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute;
|
||||
else if ( attribute.name == "color" ) vertexAttributeColor = attribute;
|
||||
// else if ( attribute.name == "color" ) vertexAttributeColor = attribute;
|
||||
else if ( attribute.name == "uv" ) vertexAttributeUv = attribute;
|
||||
else if ( attribute.name == "st" ) vertexAttributeSt = attribute;
|
||||
else if ( attribute.name == "id" ) vertexAttributeId = attribute;
|
||||
@ -1431,6 +1428,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript
|
||||
if ( vertexAttributeNormal.name != "" ) drawCommandInfo.attributes.normal = vertexAttributeNormal.offset;
|
||||
if ( vertexAttributeColor.name != "" ) drawCommandInfo.attributes.color = vertexAttributeColor.offset;
|
||||
|
||||
|
||||
// split up our mesh by textures, if the right attribute exists
|
||||
if ( vertexAttributeId.name != "" ) {
|
||||
struct TextureMapping {
|
||||
@ -1440,6 +1438,22 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript
|
||||
};
|
||||
std::vector<TextureMapping> mappings;
|
||||
TextureMapping currentMapping;
|
||||
|
||||
pod::Texture::Storage* storageBufferTextures = NULL;
|
||||
pod::Material::Storage* storageBufferMaterials = NULL;
|
||||
size_t storageBufferTexturesSize = 0;
|
||||
size_t storageBufferMaterialsSize = 0;
|
||||
|
||||
if ( storageBuffers.size() >= 2 ) {
|
||||
Buffer::Descriptor storageBufferTexturesDescriptor = storageBuffers[storageBuffers.size() - 1];
|
||||
Buffer::Descriptor storageBufferMaterialsDescriptor = storageBuffers[storageBuffers.size() - 2];
|
||||
|
||||
storageBufferTextures = (pod::Texture::Storage*) ( device->getBuffer( storageBufferTexturesDescriptor.buffer ) + storageBufferTexturesDescriptor.offset );
|
||||
storageBufferMaterials = (pod::Material::Storage*) ( device->getBuffer( storageBufferMaterialsDescriptor.buffer ) + storageBufferMaterialsDescriptor.offset );
|
||||
|
||||
storageBufferTexturesSize = storageBufferTexturesDescriptor.range / sizeof(pod::Texture::Storage);
|
||||
storageBufferMaterialsSize = storageBufferMaterialsDescriptor.range / sizeof(pod::Material::Storage);
|
||||
}
|
||||
|
||||
bool useLightmap = false;
|
||||
for ( size_t currentIndex = 0; currentIndex < indices; ++currentIndex ) {
|
||||
@ -1451,8 +1465,18 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript
|
||||
const pod::Vector2f& st = *((pod::Vector2f*) (vertices + vertexAttributeSt.offset));
|
||||
if ( st > pod::Vector2f{0,0} ) useLightmap = true;
|
||||
}
|
||||
|
||||
size_t materialId = id.y;
|
||||
size_t textureId = id.y;
|
||||
if ( storageBufferMaterials && 0 <= materialId && materialId < storageBufferMaterialsSize ) {
|
||||
auto& material = storageBufferMaterials[materialId];
|
||||
size_t textureIndex = material.indexAlbedo;
|
||||
if ( 0 <= textureIndex && textureIndex < storageBufferTexturesSize ) {
|
||||
auto& texture = storageBufferTextures[textureIndex];
|
||||
if ( 0 <= texture.index && texture.index < this->material.textures.size() ) {
|
||||
textureId = texture.index;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( currentMapping.texture != textureId ) {
|
||||
if ( currentMapping.range > 0 ) mappings.emplace_back(currentMapping);
|
||||
currentMapping.offset += currentMapping.range;
|
||||
@ -1467,7 +1491,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript
|
||||
drawCommandInfo.auxTexture = material.textures.back().descriptor;
|
||||
}
|
||||
for ( auto& mapping : mappings ) {
|
||||
if ( mapping.range == 0 || mapping.texture >= material.textures.size() ) continue;
|
||||
if ( mapping.range == 0 || !( 0 <= mapping.texture && mapping.texture < material.textures.size()) ) continue;
|
||||
drawCommandInfo.texture = material.textures[mapping.texture].descriptor;
|
||||
drawCommandInfo.descriptor.indices = mapping.range;
|
||||
drawCommandInfo.indexBuffer.offset = indexBuffer.offset + sizeof(uf::renderer::index_t) * mapping.offset;
|
||||
@ -1621,6 +1645,12 @@ void ext::opengl::GraphicDescriptor::parse( ext::json::Value& metadata ) {
|
||||
cullMode = uf::renderer::enums::CullMode::BOTH;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ext::json::isObject(metadata["depth test"]) ) {
|
||||
if ( metadata["depth test"]["test"].is<bool>() ) depth.test = metadata["depth test"]["test"].as<bool>();
|
||||
if ( metadata["depth test"]["write"].is<bool>() ) depth.write = metadata["depth test"]["write"].as<bool>();
|
||||
}
|
||||
|
||||
if ( metadata["indices"].is<size_t>() ) {
|
||||
indices = metadata["indices"].as<size_t>();
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ bool ext::opengl::settings::experimental::deferredAliasOutputToSwapchain = true;
|
||||
bool ext::opengl::settings::experimental::multiview = true;
|
||||
bool ext::opengl::settings::experimental::vsync = true;
|
||||
bool ext::opengl::settings::experimental::hdr = true;
|
||||
bool ext::opengl::settings::experimental::frustrumCull = false;
|
||||
|
||||
GLhandle(VkColorSpaceKHR) ext::opengl::settings::formats::colorSpace;
|
||||
ext::opengl::enums::Format::type_t ext::opengl::settings::formats::color = ext::opengl::enums::Format::R8G8B8A8_UNORM;
|
||||
@ -347,6 +348,7 @@ void UF_API ext::opengl::tick(){
|
||||
void UF_API ext::opengl::render(){
|
||||
ext::opengl::mutex.lock();
|
||||
#if !UF_ENV_DREAMCAST
|
||||
#if 0
|
||||
if ( hasRenderMode("Gui", true) ) {
|
||||
RenderMode& primary = getRenderMode("Gui", true);
|
||||
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
|
||||
@ -361,6 +363,7 @@ void UF_API ext::opengl::render(){
|
||||
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
|
||||
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
|
||||
}
|
||||
#endif
|
||||
ext::opengl::device.activateContext();
|
||||
#endif
|
||||
for ( auto& renderMode : renderModes ) {
|
||||
|
||||
@ -45,7 +45,7 @@ std::vector<ext::opengl::Graphic*> ext::opengl::RenderMode::getBlitters() {
|
||||
|
||||
ext::opengl::GraphicDescriptor ext::opengl::RenderMode::bindGraphicDescriptor( const ext::opengl::GraphicDescriptor& reference, size_t pass ) {
|
||||
ext::opengl::GraphicDescriptor descriptor = reference;
|
||||
descriptor.renderMode = this->getName();
|
||||
// descriptor.renderMode = this->getName();
|
||||
descriptor.subpass = pass;
|
||||
descriptor.parse( metadata );
|
||||
return descriptor;
|
||||
@ -57,7 +57,6 @@ void ext::opengl::RenderMode::createCommandBuffers() {
|
||||
this->execute = true;
|
||||
|
||||
std::vector<ext::opengl::Graphic*> graphics;
|
||||
if ( uf::scene::useGraph ) {
|
||||
auto graph = uf::scene::generateGraph();
|
||||
for ( auto entity : graph ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) continue;
|
||||
@ -65,17 +64,6 @@ if ( uf::scene::useGraph ) {
|
||||
if ( !graphic.initialized || !graphic.process ) continue;
|
||||
graphics.push_back(&graphic);
|
||||
}
|
||||
} else {
|
||||
for ( uf::Scene* scene : uf::scene::scenes ) {
|
||||
if ( !scene ) continue;
|
||||
scene->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
ext::opengl::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !graphic.initialized || !graphic.process ) return;
|
||||
graphics.push_back(&graphic);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this->synchronize();
|
||||
// bindPipelines( graphics );
|
||||
@ -101,7 +89,6 @@ void ext::opengl::RenderMode::bindPipelines() {
|
||||
this->execute = true;
|
||||
|
||||
std::vector<ext::opengl::Graphic*> graphics;
|
||||
if ( uf::scene::useGraph ) {
|
||||
auto graph = uf::scene::generateGraph();
|
||||
for ( auto entity : graph ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) continue;
|
||||
@ -109,18 +96,6 @@ if ( uf::scene::useGraph ) {
|
||||
if ( !graphic.initialized || !graphic.process ) continue;
|
||||
graphics.push_back(&graphic);
|
||||
}
|
||||
} else {
|
||||
for ( uf::Scene* scene : uf::scene::scenes ) {
|
||||
if ( !scene ) continue;
|
||||
scene->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
ext::opengl::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !graphic.initialized ) return;
|
||||
if ( !graphic.process ) return;
|
||||
graphics.push_back(&graphic);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this->synchronize();
|
||||
this->bindPipelines( graphics );
|
||||
@ -133,6 +108,8 @@ void ext::opengl::RenderMode::bindPipelines( const std::vector<ext::opengl::Grap
|
||||
if ( !subpass.autoBuildPipeline ) continue;
|
||||
// bind to this render mode
|
||||
ext::opengl::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic.descriptor, currentPass);
|
||||
// ignore invalidated descriptors
|
||||
if ( descriptor.invalidated ) continue;
|
||||
// ignore if pipeline exists for this render mode
|
||||
if ( graphic.hasPipeline( descriptor ) ) continue;
|
||||
graphic.initializePipeline( descriptor );
|
||||
@ -143,20 +120,39 @@ void ext::opengl::RenderMode::bindPipelines( const std::vector<ext::opengl::Grap
|
||||
void ext::opengl::RenderMode::render() {
|
||||
auto& commands = getCommands(this->mostRecentCommandPoolId);
|
||||
commands.submit();
|
||||
|
||||
if ( ext::opengl::renderModes.back() != this ) return;
|
||||
|
||||
#if UF_ENV_DREAMCAST
|
||||
//UF_TIMER_TRACE_INIT();
|
||||
#if UF_USE_OPENGL_GLDC
|
||||
glKosSwapBuffers();
|
||||
// profiler_print_stats();
|
||||
#else
|
||||
glutSwapBuffers();
|
||||
#endif
|
||||
//UF_TIMER_TRACE("==== SWAP BUFFER TIME ==== ");
|
||||
#else
|
||||
if ( device ) {
|
||||
device->activateContext().display();
|
||||
}
|
||||
if ( device ) device->activateContext().display();
|
||||
#endif
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadata = scene.getComponent<uf::Serializer>();
|
||||
|
||||
CommandBuffer::InfoClear clearCommandInfo = {};
|
||||
clearCommandInfo.type = enums::Command::CLEAR;
|
||||
clearCommandInfo.color = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
clearCommandInfo.depth = uf::Camera::USE_REVERSE_INFINITE_PROJECTION ? 0.0f : 1.0f;
|
||||
clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
||||
if ( !ext::json::isNull( sceneMetadata["system"]["renderer"]["clear values"][0] ) ) {
|
||||
clearCommandInfo.color = uf::vector::decode( sceneMetadata["system"]["renderer"]["clear values"][0], pod::Vector4f{0,0,0,0} );
|
||||
}
|
||||
if ( !ext::json::isNull( sceneMetadata["light"]["ambient"] ) ) {
|
||||
clearCommandInfo.color = uf::vector::decode( sceneMetadata["light"]["ambient"], pod::Vector4f{0,0,0,0} );
|
||||
// auto ambient = uf::vector::decode( sceneMetadata["light"]["ambient"], pod::Vector4f{1,1,1,1} );
|
||||
// GL_ERROR_CHECK(glLightfv(GL_LIGHT0, GL_AMBIENT, &ambient[0]));
|
||||
}
|
||||
|
||||
GL_ERROR_CHECK(glClearColor(clearCommandInfo.color[0], clearCommandInfo.color[1], clearCommandInfo.color[2], clearCommandInfo.color[3]));
|
||||
GL_ERROR_CHECK(glClearDepth(clearCommandInfo.depth));
|
||||
GL_ERROR_CHECK(glClear(clearCommandInfo.bits));
|
||||
|
||||
}
|
||||
|
||||
void ext::opengl::RenderMode::initialize( Device& device ) {
|
||||
|
||||
@ -24,6 +24,7 @@ void ext::opengl::BaseRenderMode::createCommandBuffers( const std::vector<ext::o
|
||||
size_t currentDraw = 0;
|
||||
auto& commands = getCommands();
|
||||
commands.start(); {
|
||||
#if 0
|
||||
CommandBuffer::InfoClear clearCommandInfo = {};
|
||||
clearCommandInfo.type = enums::Command::CLEAR;
|
||||
clearCommandInfo.color = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
@ -38,8 +39,8 @@ void ext::opengl::BaseRenderMode::createCommandBuffers( const std::vector<ext::o
|
||||
// auto ambient = uf::vector::decode( sceneMetadata["light"]["ambient"], pod::Vector4f{1,1,1,1} );
|
||||
// GL_ERROR_CHECK(glLightfv(GL_LIGHT0, GL_AMBIENT, &ambient[0]));
|
||||
}
|
||||
|
||||
commands.record(clearCommandInfo);
|
||||
#endif
|
||||
|
||||
CommandBuffer::InfoViewport viewportCommandInfo = {};
|
||||
viewportCommandInfo.type = enums::Command::VIEWPORT;
|
||||
@ -102,7 +103,7 @@ void ext::opengl::BaseRenderMode::tick() {
|
||||
}
|
||||
void ext::opengl::BaseRenderMode::render() {
|
||||
// if ( ext::opengl::renderModes.size() > 1 ) return;
|
||||
if ( ext::opengl::renderModes.back() != this ) return;
|
||||
// if ( ext::opengl::renderModes.back() != this ) return;
|
||||
ext::opengl::RenderMode::render();
|
||||
}
|
||||
|
||||
|
||||
@ -43,13 +43,14 @@ void ext::opengl::DeferredRenderMode::createCommandBuffers( const std::vector<ex
|
||||
|
||||
auto& commands = getCommands();
|
||||
commands.start(); {
|
||||
#if 0
|
||||
CommandBuffer::InfoClear clearCommandInfo = {};
|
||||
clearCommandInfo.type = enums::Command::CLEAR;
|
||||
clearCommandInfo.color = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
clearCommandInfo.depth = uf::Camera::USE_REVERSE_INFINITE_PROJECTION ? 0.0f : 1.0f;
|
||||
clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
||||
commands.record(clearCommandInfo);
|
||||
|
||||
#endif
|
||||
CommandBuffer::InfoViewport viewportCommandInfo = {};
|
||||
viewportCommandInfo.type = enums::Command::VIEWPORT;
|
||||
viewportCommandInfo.corner = pod::Vector2ui{0, 0};
|
||||
|
||||
@ -34,11 +34,22 @@ ext::opengl::GraphicDescriptor ext::opengl::RenderTargetRenderMode::bindGraphicD
|
||||
ext::opengl::GraphicDescriptor descriptor = ext::opengl::RenderMode::bindGraphicDescriptor(reference, pass);
|
||||
descriptor.parse(metadata["descriptor"]);
|
||||
std::string type = metadata["type"].as<std::string>();
|
||||
std::string target = metadata["target"].as<std::string>();
|
||||
if ( type == "depth" ) {
|
||||
// descriptor.cullMode = VK_CULL_MODE_NONE;
|
||||
}
|
||||
// invalidate
|
||||
if ( target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != target ) {
|
||||
descriptor.invalidated = true;
|
||||
} else {
|
||||
descriptor.renderMode = this->getName();
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
void ext::opengl::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
ext::opengl::RenderMode::initialize( device );
|
||||
this->setTarget( this->getName() );
|
||||
}
|
||||
|
||||
void ext::opengl::RenderTargetRenderMode::tick() {
|
||||
@ -46,10 +57,9 @@ void ext::opengl::RenderTargetRenderMode::tick() {
|
||||
}
|
||||
void ext::opengl::RenderTargetRenderMode::destroy() {
|
||||
ext::opengl::RenderMode::destroy();
|
||||
blitter.destroy();
|
||||
}
|
||||
void ext::opengl::RenderTargetRenderMode::render() {
|
||||
auto& commands = getCommands( this->mostRecentCommandPoolId );
|
||||
ext::opengl::RenderMode::render();
|
||||
}
|
||||
void ext::opengl::RenderTargetRenderMode::pipelineBarrier( GLhandle(VkCommandBuffer) commandBuffer, uint8_t state ) {
|
||||
}
|
||||
@ -59,25 +69,29 @@ void ext::opengl::RenderTargetRenderMode::createCommandBuffers( const std::vecto
|
||||
|
||||
auto& commands = getCommands();
|
||||
commands.start(); {
|
||||
#if 0
|
||||
CommandBuffer::InfoClear clearCommandInfo = {};
|
||||
clearCommandInfo.type = enums::Command::CLEAR;
|
||||
clearCommandInfo.color = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
clearCommandInfo.depth = uf::Camera::USE_REVERSE_INFINITE_PROJECTION ? 0.0f : 1.0f;
|
||||
clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
||||
commands.record(clearCommandInfo);
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
CommandBuffer::InfoViewport viewportCommandInfo = {};
|
||||
viewportCommandInfo.type = enums::Command::VIEWPORT;
|
||||
viewportCommandInfo.corner = pod::Vector2ui{0, 0};
|
||||
viewportCommandInfo.size = pod::Vector2ui{width, height};
|
||||
commands.record(viewportCommandInfo);
|
||||
#endif
|
||||
|
||||
size_t currentSubpass = 0;
|
||||
size_t currentPass = 0;
|
||||
size_t currentDraw = 0;
|
||||
for ( auto graphic : graphics ) {
|
||||
if ( graphic->descriptor.renderMode != this->getName() ) continue;
|
||||
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
|
||||
GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
|
||||
if ( descriptor.invalidated ) continue;
|
||||
graphic->record( commands, descriptor, currentPass, currentDraw++ );
|
||||
}
|
||||
} commands.end();
|
||||
|
||||
@ -81,7 +81,7 @@ void ext::opengl::Texture::loadFromFile(
|
||||
return loadFromFile( filename, ext::opengl::device, format );
|
||||
}
|
||||
void ext::opengl::Texture::loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
enums::Format::type_t format
|
||||
) {
|
||||
return loadFromImage( image, ext::opengl::device, format );
|
||||
@ -96,13 +96,14 @@ void ext::opengl::Texture::loadFromFile(
|
||||
return loadFromImage( image, device, format );
|
||||
}
|
||||
void ext::opengl::Texture::loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
Device& device,
|
||||
enums::Format::type_t format
|
||||
) {
|
||||
if ( image.getFormat() > 0 ) {
|
||||
// UF_DEBUG_MSG( image.getFilename() << " | " << std::bitset<32>(image.getFormat()) );
|
||||
if ( image.getFormat() != 0 ) {
|
||||
internalFormat = image.getFormat();
|
||||
} else
|
||||
} else {
|
||||
switch ( image.getChannels() ) {
|
||||
// R
|
||||
case 1:
|
||||
@ -155,7 +156,7 @@ void ext::opengl::Texture::loadFromImage(
|
||||
UF_EXCEPTION("unsupported channels of " + std::to_string(image.getChannels()));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
// convert to power of two
|
||||
//image.padToPowerOfTwo();
|
||||
|
||||
@ -195,6 +196,7 @@ void ext::opengl::Texture::fromBuffers(
|
||||
Device& device
|
||||
) {
|
||||
this->initialize(device, viewType, texWidth, texHeight, texDepth, layers);
|
||||
this->format = format;
|
||||
|
||||
#if !UF_ENV_DREAMCAST
|
||||
if ( this->mips == 0 ) {
|
||||
@ -261,16 +263,12 @@ void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer
|
||||
GLenum format = GL_RGBA;
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
switch ( this->format ) {
|
||||
#if !UF_ENV_DREAMCAST
|
||||
case enums::Format::R8_UNORM:
|
||||
format = GL_RED;
|
||||
format = GL_LUMINANCE;
|
||||
break;
|
||||
#endif
|
||||
#if !UF_ENV_DREAMCAST
|
||||
case enums::Format::R8G8_UNORM:
|
||||
format = GL_RG;
|
||||
format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
#endif
|
||||
case enums::Format::R8G8B8_UNORM:
|
||||
format = GL_RGB;
|
||||
break;
|
||||
|
||||
@ -190,7 +190,6 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
|
||||
this->execute = true;
|
||||
|
||||
std::vector<ext::vulkan::Graphic*> graphics;
|
||||
if ( uf::scene::useGraph ) {
|
||||
auto graph = uf::scene::generateGraph();
|
||||
for ( auto entity : graph ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) continue;
|
||||
@ -198,17 +197,6 @@ if ( uf::scene::useGraph ) {
|
||||
if ( !graphic.initialized || !graphic.process ) continue;
|
||||
graphics.push_back(&graphic);
|
||||
}
|
||||
} else {
|
||||
for ( uf::Scene* scene : uf::scene::scenes ) {
|
||||
if ( !scene ) continue;
|
||||
scene->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !graphic.initialized || !graphic.process ) return;
|
||||
graphics.push_back(&graphic);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this->synchronize();
|
||||
// bindPipelines( graphics );
|
||||
@ -242,7 +230,6 @@ void ext::vulkan::RenderMode::bindPipelines() {
|
||||
this->execute = true;
|
||||
|
||||
std::vector<ext::vulkan::Graphic*> graphics;
|
||||
if ( uf::scene::useGraph ) {
|
||||
auto graph = uf::scene::generateGraph();
|
||||
for ( auto entity : graph ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) continue;
|
||||
@ -251,19 +238,6 @@ if ( uf::scene::useGraph ) {
|
||||
// if ( graphic.descriptor.renderMode != "" && graphic.descriptor.renderMode != this->getName() ) continue;
|
||||
graphics.push_back(&graphic);
|
||||
}
|
||||
} else {
|
||||
for ( uf::Scene* scene : uf::scene::scenes ) {
|
||||
if ( !scene ) continue;
|
||||
scene->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !graphic.initialized ) return;
|
||||
if ( !graphic.process ) return;
|
||||
// if ( graphic.descriptor.renderMode != "" && graphic.descriptor.renderMode != this->getName() ) return;
|
||||
graphics.push_back(&graphic);
|
||||
});
|
||||
}
|
||||
}
|
||||
this->synchronize();
|
||||
this->bindPipelines( graphics );
|
||||
}
|
||||
|
||||
@ -32,27 +32,16 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD
|
||||
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
|
||||
descriptor.parse(metadata["descriptor"]);
|
||||
std::string type = metadata["type"].as<std::string>();
|
||||
std::string target = metadata["target"].as<std::string>();
|
||||
if ( type == "depth" ) {
|
||||
descriptor.cullMode = VK_CULL_MODE_NONE;
|
||||
}
|
||||
std::string target = metadata["target"].as<std::string>();
|
||||
// invalidate
|
||||
// if ( ( target == "" && descriptor.renderMode != this->getName() ) || ( target != "" && descriptor.renderMode != target ) ) {
|
||||
if ( target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != target ) {
|
||||
descriptor.invalidated = true;
|
||||
} else {
|
||||
descriptor.renderMode = this->getName();
|
||||
}
|
||||
/*
|
||||
// allows for "easy" remapping for indices ranges
|
||||
if ( ext::json::isObject( metadata["renderMode"]["target"][std::to_string(descriptor.indices)] ) ) {
|
||||
auto& map = metadata["renderMode"]["target"][std::to_string(descriptor.indices)];
|
||||
std::cout << "Replacing " << descriptor.indices;
|
||||
descriptor.indices = map["size"].as<size_t>();
|
||||
descriptor.offsets.index = map["offset"].as<size_t>();
|
||||
std::cout << " with " << descriptor.offsets.index << " + " << descriptor.indices << std::endl;
|
||||
}
|
||||
*/
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
||||
@ -268,75 +268,10 @@ void ext::vulkan::Texture::loadFromFile(
|
||||
) {
|
||||
uf::Image image;
|
||||
image.open( filename );
|
||||
switch ( image.getChannels() ) {
|
||||
// R
|
||||
case 1:
|
||||
switch ( image.getBpp() ) {
|
||||
case 8:
|
||||
format = VK_FORMAT_R8_UNORM;
|
||||
break;
|
||||
default:
|
||||
UF_EXCEPTION("unsupported BPP of " + std::to_string(image.getBpp()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// RGB
|
||||
case 3:
|
||||
switch ( image.getBpp() ) {
|
||||
case 24:
|
||||
format = VK_FORMAT_R8G8B8_UNORM;
|
||||
break;
|
||||
default:
|
||||
UF_EXCEPTION("unsupported BPP of " + std::to_string(image.getBpp()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// RGBA
|
||||
case 4:
|
||||
switch ( image.getBpp() ) {
|
||||
case 32:
|
||||
format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
UF_EXCEPTION("unsupported BPP of " + std::to_string(image.getBpp()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UF_EXCEPTION("unsupported channels of " + std::to_string(image.getChannels()));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
if (device.features.textureCompressionBC) {
|
||||
format = VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
}
|
||||
else if (device.features.textureCompressionASTC_LDR) {
|
||||
format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
|
||||
}
|
||||
else if (device.features.textureCompressionETC2) {
|
||||
format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
|
||||
}
|
||||
else {
|
||||
UF_EXCEPTION("VK_ERROR_FEATURE_NOT_PRESENT");
|
||||
}
|
||||
*/
|
||||
|
||||
// convert to power of two
|
||||
//image.padToPowerOfTwo();
|
||||
|
||||
this->fromBuffers(
|
||||
(void*) image.getPixelsPtr(),
|
||||
image.getPixels().size(),
|
||||
format,
|
||||
image.getDimensions()[0],
|
||||
image.getDimensions()[1],
|
||||
device,
|
||||
imageUsageFlags,
|
||||
imageLayout
|
||||
);
|
||||
return loadFromImage( image, device, format, imageUsageFlags, imageLayout );
|
||||
}
|
||||
void ext::vulkan::Texture::loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsageFlags,
|
||||
VkImageLayout imageLayout
|
||||
@ -344,7 +279,7 @@ void ext::vulkan::Texture::loadFromImage(
|
||||
return loadFromImage( image, ext::vulkan::device, format, imageUsageFlags, imageLayout );
|
||||
}
|
||||
void ext::vulkan::Texture::loadFromImage(
|
||||
uf::Image& image,
|
||||
const uf::Image& image,
|
||||
Device& device,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsageFlags,
|
||||
|
||||
@ -36,6 +36,7 @@ bool ext::vulkan::settings::experimental::deferredAliasOutputToSwapchain = true;
|
||||
bool ext::vulkan::settings::experimental::multiview = true;
|
||||
bool ext::vulkan::settings::experimental::vsync = true;
|
||||
bool ext::vulkan::settings::experimental::hdr = true;
|
||||
bool ext::vulkan::settings::experimental::frustrumCull = false;
|
||||
|
||||
VkColorSpaceKHR ext::vulkan::settings::formats::colorSpace;
|
||||
ext::vulkan::enums::Format::type_t ext::vulkan::settings::formats::color = ext::vulkan::enums::Format::R8G8B8A8_UNORM;
|
||||
|
||||
@ -44,13 +44,13 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
|
||||
}
|
||||
|
||||
::xatlas::ChartOptions chartOptions{};
|
||||
chartOptions.useInputMeshUvs = true;
|
||||
// chartOptions.useInputMeshUvs = true;
|
||||
::xatlas::PackOptions packOptions{};
|
||||
// packOptions.bruteForce = true;
|
||||
// packOptions.resolution = resolution;
|
||||
// packOptions.texelsPerUnit = 64.0f;
|
||||
// packOptions.blockAlign = true;
|
||||
packOptions.bilinear = true;
|
||||
// packOptions.bilinear = true;
|
||||
|
||||
::xatlas::Generate(atlas, chartOptions, packOptions);
|
||||
auto oldMeshes = std::move( graph.meshes );
|
||||
|
||||
@ -1,36 +1,55 @@
|
||||
#include <uf/utils/image/atlas.h>
|
||||
#include <binpack2d/binpack2d.hpp>
|
||||
#include <iostream>
|
||||
|
||||
void uf::Atlas::addImage( const uf::Image& _image, bool regenerate ) {
|
||||
auto& image = this->m_images.emplace_back( _image );
|
||||
if ( regenerate ) this->generate();
|
||||
}
|
||||
void uf::Atlas::addImage( uf::Image&& _image, bool regenerate ) {
|
||||
auto& image = this->m_images.emplace_back( _image );
|
||||
if ( regenerate ) this->generate();
|
||||
}
|
||||
void uf::Atlas::addImage( const uint8_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip, bool regenerate ) {
|
||||
auto& image = this->m_images.emplace_back();
|
||||
image.loadFromBuffer( pointer, size, bpp, channels, flip );
|
||||
if ( regenerate ) this->generate();
|
||||
uf::Atlas::hash_t uf::Atlas::addImage( const uf::Image& _image, bool regenerate ) {
|
||||
size_t index = this->m_tiles.size();
|
||||
auto hash = _image.getHash();
|
||||
if ( this->m_tiles.count( hash ) > 0 ) return hash;
|
||||
|
||||
auto& tile = this->m_tiles[hash];
|
||||
tile.image = _image;
|
||||
tile.identifier.hash = hash;
|
||||
tile.identifier.index = index;
|
||||
if ( regenerate ) this->generate();
|
||||
return hash;
|
||||
}
|
||||
void uf::Atlas::generate( float padding ) {
|
||||
return generate( this->m_images, padding );
|
||||
uf::Atlas::hash_t uf::Atlas::addImage( uf::Image&& _image, bool regenerate ) {
|
||||
size_t index = this->m_tiles.size();
|
||||
auto hash = _image.getHash();
|
||||
if ( this->m_tiles.count( hash ) > 0 ) return hash;
|
||||
|
||||
auto& tile = this->m_tiles[hash];
|
||||
tile.image = _image;
|
||||
tile.identifier.hash = hash;
|
||||
tile.identifier.index = index;
|
||||
if ( regenerate ) this->generate();
|
||||
return hash;
|
||||
}
|
||||
uf::Atlas::hash_t uf::Atlas::addImage( const uint8_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip, bool regenerate ) {
|
||||
uf::Image image;
|
||||
image.loadFromBuffer( pointer, size, bpp, channels, flip );
|
||||
return this->addImage( std::move( image ), regenerate );
|
||||
}
|
||||
void uf::Atlas::generate( const uf::Atlas::images_t& images, float padding ) {
|
||||
if ( images.empty() ) return;
|
||||
// destroy atlas
|
||||
this->m_image.clear();
|
||||
for ( auto& image : images ) this->addImage( image, false );
|
||||
generate( padding );
|
||||
}
|
||||
void uf::Atlas::generate( float padding ) {
|
||||
if ( this->m_tiles.empty() ) return;
|
||||
|
||||
BinPack2D::ContentAccumulator<uf::Atlas::identifier_t> queue;
|
||||
BinPack2D::CanvasArray<Identifier> internalAtlas;
|
||||
BinPack2D::ContentAccumulator<uf::Atlas::Identifier> queue, stored, remainder;
|
||||
pod::Vector2ui size = {0,0};
|
||||
pod::Vector3ui largest = {0,0,0};
|
||||
size_t index = 0;
|
||||
size_t area = 0;
|
||||
for ( auto& image : images ) {
|
||||
auto& dim = image.getDimensions();
|
||||
queue += BinPack2D::Content<uf::Atlas::identifier_t>({index++}, BinPack2D::Coord(), BinPack2D::Size(dim.x, dim.y), false );
|
||||
size_t channels = 1;
|
||||
for ( auto pair : this->m_tiles ) {
|
||||
auto& tile = pair.second;
|
||||
auto& dim = tile.image.getDimensions();
|
||||
channels = std::max( channels, tile.image.getChannels() );
|
||||
queue += BinPack2D::Content<uf::Atlas::Identifier>(tile.identifier, BinPack2D::Coord(), BinPack2D::Size(dim.x, dim.y), false );
|
||||
size += dim;
|
||||
area += dim.x * dim.y;
|
||||
if ( area >= largest.z ) {
|
||||
@ -39,10 +58,9 @@ void uf::Atlas::generate( const uf::Atlas::images_t& images, float padding ) {
|
||||
}
|
||||
}
|
||||
size_t tries = 16;
|
||||
BinPack2D::ContentAccumulator<uf::Atlas::identifier_t> stored, remainder;
|
||||
do {
|
||||
{
|
||||
// size_t area = largest.x * largest.y * images.size();
|
||||
// size_t area = largest.x * largest.y * this->m_tiles.size();
|
||||
size_t side = std::sqrt( area ) * padding;
|
||||
size = { side, side };
|
||||
{
|
||||
@ -63,64 +81,70 @@ void uf::Atlas::generate( const uf::Atlas::images_t& images, float padding ) {
|
||||
}
|
||||
}
|
||||
queue.Sort();
|
||||
this->m_atlas = BinPack2D::UniformCanvasArrayBuilder<uf::Atlas::identifier_t>(size.x, size.y, 1).Build();
|
||||
bool success = this->m_atlas.Place( queue, remainder );
|
||||
internalAtlas = BinPack2D::UniformCanvasArrayBuilder<uf::Atlas::Identifier>(size.x, size.y, 1).Build();
|
||||
bool success = internalAtlas.Place( queue, remainder );
|
||||
if ( success && remainder.Get().empty() ) break;
|
||||
// increase padding
|
||||
padding += 0.10f;
|
||||
} while ( --tries );
|
||||
this->m_image.loadFromBuffer( NULL, size, 8, 4 );
|
||||
this->m_atlas.CollectContent( stored );
|
||||
|
||||
auto& dstBuffer = this->m_image.getPixels();
|
||||
|
||||
for ( size_t i = 0; i < size.x * size.y * 4; i+=4 ) {
|
||||
dstBuffer[i+0] = 0;
|
||||
dstBuffer[i+1] = 0;
|
||||
dstBuffer[i+2] = 0;
|
||||
dstBuffer[i+3] = 0;
|
||||
}
|
||||
internalAtlas.CollectContent( stored );
|
||||
|
||||
this->m_atlas.loadFromBuffer( NULL, size, 8, channels );
|
||||
auto& dstBuffer = this->m_atlas.getPixels();
|
||||
for ( size_t i = 0; i < size.x * size.y * channels; ++i ) dstBuffer[i] = 0;
|
||||
for ( auto& it : stored.Get() ) {
|
||||
size_t index = it.content.index;
|
||||
auto& image = images[index];
|
||||
auto& dim = image.getDimensions();
|
||||
auto channels = image.getChannels();
|
||||
auto& tile = this->m_tiles[it.content.hash];
|
||||
tile.coord = { it.coord.x, it.coord.y };
|
||||
tile.size = { it.size.w, it.size.h };
|
||||
/*
|
||||
}
|
||||
for ( auto pair : this->m_tiles ) {
|
||||
auto& tile = pair.second;
|
||||
*/
|
||||
auto& image = tile.image;
|
||||
auto& srcBuffer = image.getPixels();
|
||||
auto srcChannels = image.getChannels();
|
||||
|
||||
for ( size_t y = 0; y < dim.y; ++y ) {
|
||||
for ( size_t x = 0; x < dim.x; ++x ) {
|
||||
size_t src = (y * dim.x * channels) + (x * channels);
|
||||
size_t dst = ((y + it.coord.y) * size.x * 4) + ((x + it.coord.x) * 4);
|
||||
for ( size_t i = 0; i < channels; ++i ) {
|
||||
for ( size_t y = 0; y < tile.size.y; ++y ) {
|
||||
for ( size_t x = 0; x < tile.size.x; ++x ) {
|
||||
size_t src = (y * tile.size.x * srcChannels) + (x * srcChannels);
|
||||
size_t dst = ((y + tile.coord.y) * size.x * channels) + ((x + tile.coord.x) * channels);
|
||||
for ( size_t i = 0; i < srcChannels; ++i ) {
|
||||
dstBuffer[dst+i] = srcBuffer[src+i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void uf::Atlas::clear() {
|
||||
this->m_images.clear();
|
||||
this->m_image.clear();
|
||||
this->m_atlas = uf::Atlas::atlas_t{};
|
||||
bool uf::Atlas::generated() const {
|
||||
return !this->m_atlas.getPixels().empty();
|
||||
}
|
||||
void uf::Atlas::clear( bool full ) {
|
||||
if ( !full ) {
|
||||
for ( auto pair : this->m_tiles ) pair.second.image.clear();
|
||||
return;
|
||||
}
|
||||
this->m_tiles.clear();
|
||||
this->m_atlas.clear();
|
||||
}
|
||||
pod::Vector2f uf::Atlas::mapUv( const pod::Vector2f& uv, const uf::Atlas::hash_t& hash ) {
|
||||
auto& size = this->m_atlas.getDimensions();
|
||||
for ( auto pair : this->m_tiles ) {
|
||||
auto& tile = pair.second;
|
||||
if ( tile.identifier.hash != hash ) continue;
|
||||
pod::Vector2ui coord = { uv.x * tile.size.x + tile.coord.x, uv.y * tile.size.y + tile.coord.y };
|
||||
return pod::Vector2f{ (float) coord.x / (float) size.x, (float) coord.y / (float) size.y };
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
pod::Vector2f uf::Atlas::mapUv( const pod::Vector2f& uv, size_t index ) {
|
||||
BinPack2D::ContentAccumulator<uf::Atlas::identifier_t> stored;
|
||||
this->m_atlas.CollectContent( stored );
|
||||
auto& size = this->m_image.getDimensions();
|
||||
for ( auto& it : stored.Get() ) {
|
||||
if ( it.content.index != index ) continue;
|
||||
pod::Vector2ui dim = { it.size.w, it.size.h };
|
||||
pod::Vector2f nuv = uv;
|
||||
if ( nuv.x > 1.0f ) nuv.x = std::fmod( nuv.x, 1.0f );
|
||||
if ( nuv.y > 1.0f ) nuv.y = std::fmod( nuv.y, 1.0f );
|
||||
|
||||
pod::Vector2ui coord = { uv.x * dim.x + it.coord.x, uv.y * dim.y + it.coord.y };
|
||||
nuv = { (float) coord.x / (float) size.x, (float) coord.y / (float) size.y };
|
||||
// nuv.y = 1.0f - nuv.y;
|
||||
return nuv;
|
||||
auto& size = this->m_atlas.getDimensions();
|
||||
for ( auto pair : this->m_tiles ) {
|
||||
auto& tile = pair.second;
|
||||
if ( tile.identifier.index != index ) continue;
|
||||
pod::Vector2ui coord = { uv.x * tile.size.x + tile.coord.x, uv.y * tile.size.y + tile.coord.y };
|
||||
return pod::Vector2f{ (float) coord.x / (float) size.x, (float) coord.y / (float) size.y };
|
||||
}
|
||||
// std::cout << "Could not find requested index of " << index << std::endl;
|
||||
return uv;
|
||||
}
|
||||
pod::Vector3f uf::Atlas::mapUv( const pod::Vector3f& uv ) {
|
||||
@ -128,174 +152,14 @@ pod::Vector3f uf::Atlas::mapUv( const pod::Vector3f& uv ) {
|
||||
return { nuv.x, nuv.y, uv.z };
|
||||
}
|
||||
uf::Image& uf::Atlas::getAtlas() {
|
||||
return this->m_image;
|
||||
return this->m_atlas;
|
||||
}
|
||||
uf::Atlas::images_t& uf::Atlas::getImages() {
|
||||
return this->m_images;
|
||||
const uf::Image& uf::Atlas::getAtlas() const {
|
||||
return this->m_atlas;
|
||||
}
|
||||
const uf::Atlas::images_t& uf::Atlas::getImages() const {
|
||||
return this->m_images;
|
||||
uf::Atlas::atlas_t& uf::Atlas::getImages() {
|
||||
return this->m_tiles;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <uf/utils/image/atlas.h>
|
||||
#include <iostream>
|
||||
|
||||
uf::HashAtlas::hash_t uf::HashAtlas::addImage( const uf::Image& _image, bool regenerate ) {
|
||||
auto hash = _image.getHash();
|
||||
if ( this->has( hash ) ) return hash;
|
||||
|
||||
auto& image = *(this->m_images.emplace(hash, _image)).first;
|
||||
if ( regenerate ) this->generate();
|
||||
|
||||
return hash;
|
||||
}
|
||||
uf::HashAtlas::hash_t uf::HashAtlas::addImage( uf::Image&& _image, bool regenerate ) {
|
||||
auto hash = _image.getHash();
|
||||
if ( this->has( hash ) ) return hash;
|
||||
|
||||
auto& image = *(this->m_images.emplace(hash, _image)).first;
|
||||
if ( regenerate ) this->generate();
|
||||
|
||||
return hash;
|
||||
}
|
||||
uf::HashAtlas::hash_t uf::HashAtlas::addImage( const uint8_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip, bool regenerate ) {
|
||||
uf::Image image;
|
||||
image.loadFromBuffer( pointer, size, bpp, channels, flip );
|
||||
std::string hash = image.getHash();
|
||||
if ( this->has( hash ) ) return hash;
|
||||
this->m_images.emplace( hash, std::move(image) );
|
||||
if ( regenerate ) this->generate();
|
||||
return hash;
|
||||
|
||||
}
|
||||
bool uf::HashAtlas::has( const uf::Image& image ) const {
|
||||
return this->has( image.getHash() );
|
||||
}
|
||||
bool uf::HashAtlas::has( const std::string& hash ) const {
|
||||
return this->m_images.count(hash) > 0;
|
||||
}
|
||||
void uf::HashAtlas::generate( float padding ) {
|
||||
return generate( this->m_images, padding );
|
||||
}
|
||||
void uf::HashAtlas::generate( const uf::HashAtlas::images_t& images, float padding ) {
|
||||
if ( images.empty() ) return;
|
||||
// destroy atlas
|
||||
this->m_image.clear();
|
||||
|
||||
BinPack2D::ContentAccumulator<uf::HashAtlas::identifier_t> queue;
|
||||
pod::Vector2ui size = {0,0};
|
||||
pod::Vector3ui largest = {0,0,0};
|
||||
size_t index = 0;
|
||||
size_t area = 0;
|
||||
for ( auto& pair : images ) {
|
||||
auto hash = pair.first;
|
||||
auto& dim = pair.second.getDimensions();
|
||||
queue += BinPack2D::Content<uf::HashAtlas::identifier_t>({hash}, BinPack2D::Coord(), BinPack2D::Size(dim.x, dim.y), false );
|
||||
size += dim;
|
||||
area += dim.x * dim.y;
|
||||
if ( area >= largest.z ) {
|
||||
largest.x = dim.x;
|
||||
largest.y = dim.y;
|
||||
}
|
||||
}
|
||||
size_t tries = 16;
|
||||
BinPack2D::ContentAccumulator<uf::HashAtlas::identifier_t> stored, remainder;
|
||||
do {
|
||||
{
|
||||
// size_t area = largest.x * largest.y * images.size();
|
||||
size_t side = std::sqrt( area ) * padding;
|
||||
size = { side, side };
|
||||
{
|
||||
size.x--;
|
||||
size.x |= size.x >> 1;
|
||||
size.x |= size.x >> 2;
|
||||
size.x |= size.x >> 4;
|
||||
size.x |= size.x >> 8;
|
||||
size.x |= size.x >> 16;
|
||||
size.x++;
|
||||
size.y--;
|
||||
size.y |= size.y >> 1;
|
||||
size.y |= size.y >> 2;
|
||||
size.y |= size.y >> 4;
|
||||
size.y |= size.y >> 8;
|
||||
size.y |= size.y >> 16;
|
||||
size.y++;
|
||||
}
|
||||
}
|
||||
queue.Sort();
|
||||
this->m_atlas = BinPack2D::UniformCanvasArrayBuilder<uf::HashAtlas::identifier_t>(size.x, size.y ,1).Build();
|
||||
bool success = this->m_atlas.Place( queue, remainder );
|
||||
if ( success && remainder.Get().empty() ) break;
|
||||
// increase padding
|
||||
padding += 0.10f;
|
||||
} while ( --tries );
|
||||
this->m_image.loadFromBuffer( NULL, size, 8, 4 );
|
||||
this->m_atlas.CollectContent( stored );
|
||||
|
||||
auto& dstBuffer = this->m_image.getPixels();
|
||||
|
||||
for ( size_t i = 0; i < size.x * size.y * 4; i+=4 ) {
|
||||
dstBuffer[i+0] = 0;
|
||||
dstBuffer[i+1] = 0;
|
||||
dstBuffer[i+2] = 0;
|
||||
dstBuffer[i+3] = 0;
|
||||
}
|
||||
|
||||
for ( auto& it : stored.Get() ) {
|
||||
auto& hash = it.content.hash;
|
||||
auto& image = images.at(hash);
|
||||
auto& dim = image.getDimensions();
|
||||
auto channels = image.getChannels();
|
||||
auto& srcBuffer = image.getPixels();
|
||||
|
||||
for ( size_t y = 0; y < dim.y; ++y ) {
|
||||
for ( size_t x = 0; x < dim.x; ++x ) {
|
||||
size_t src = (y * dim.x * channels) + (x * channels);
|
||||
size_t dst = ((y + it.coord.y) * size.x * 4) + ((x + it.coord.x) * 4);
|
||||
for ( size_t i = 0; i < channels; ++i ) {
|
||||
dstBuffer[dst+i] = srcBuffer[src+i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void uf::HashAtlas::clear() {
|
||||
this->m_images.clear();
|
||||
this->m_image.clear();
|
||||
this->m_atlas = uf::HashAtlas::atlas_t{};
|
||||
}
|
||||
pod::Vector2f uf::HashAtlas::mapUv( const pod::Vector2f& uv, const uf::HashAtlas::hash_t& hash ) {
|
||||
BinPack2D::ContentAccumulator<uf::HashAtlas::identifier_t> stored;
|
||||
this->m_atlas.CollectContent( stored );
|
||||
auto& size = this->m_image.getDimensions();
|
||||
for ( auto& it : stored.Get() ) {
|
||||
if ( it.content.hash != hash ) continue;
|
||||
pod::Vector2ui dim = { it.size.w, it.size.h };
|
||||
pod::Vector2f nuv = uv;
|
||||
if ( nuv.x > 1.0f ) nuv.x = std::fmod( nuv.x, 1.0f );
|
||||
if ( nuv.y > 1.0f ) nuv.y = std::fmod( nuv.y, 1.0f );
|
||||
|
||||
pod::Vector2ui coord = { uv.x * dim.x + it.coord.x, uv.y * dim.y + it.coord.y };
|
||||
nuv = { (float) coord.x / (float) size.x, (float) coord.y / (float) size.y };
|
||||
nuv.y = 1.0f - nuv.y;
|
||||
return nuv;
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
uf::Image& uf::HashAtlas::getAtlas() {
|
||||
return this->m_image;
|
||||
}
|
||||
uf::HashAtlas::images_t& uf::HashAtlas::getImages() {
|
||||
return this->m_images;
|
||||
}
|
||||
const uf::HashAtlas::images_t& uf::HashAtlas::getImages() const {
|
||||
return this->m_images;
|
||||
const uf::Atlas::atlas_t& uf::Atlas::getImages() const {
|
||||
return this->m_tiles;
|
||||
}
|
||||
@ -91,6 +91,7 @@ bool uf::Image::open( const std::string& _filename, bool flip ) {
|
||||
#if UF_ENV_DREAMCAST
|
||||
std::string dtex = uf::string::replace( filename, ".png", ".dtex" );
|
||||
if ( uf::io::exists(dtex) ) {
|
||||
UF_DEBUG_MSG("Loading dtex instead for: " << filename);
|
||||
filename = dtex;
|
||||
}
|
||||
#endif
|
||||
@ -127,23 +128,36 @@ bool uf::Image::open( const std::string& _filename, bool flip ) {
|
||||
uint32_t expected = 2 * header.width * header.height;
|
||||
uint32_t ratio = (uint32_t) (((float) expected) / ((float) header.size));
|
||||
bit_depth = 4;
|
||||
this->m_format = format;
|
||||
if ( compressed ) {
|
||||
if ( twiddled ) {
|
||||
switch ( format ) {
|
||||
case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS; break;
|
||||
case 1: this->m_format = mipmapped ? GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_RGB_565_VQ_TWID_KOS; channels = 3; break;
|
||||
case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS; break;
|
||||
case 2: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS; break;
|
||||
default: UF_EXCEPTION(filename << ": invalid texture format"); return false;
|
||||
}
|
||||
} else {
|
||||
switch ( format ) {
|
||||
case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS : GL_COMPRESSED_ARGB_1555_VQ_KOS; break;
|
||||
case 1: this->m_format = mipmapped ? GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS : GL_COMPRESSED_RGB_565_VQ_KOS; channels = 3; break;
|
||||
case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS : GL_COMPRESSED_ARGB_1555_VQ_KOS; break;
|
||||
case 2: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS : GL_COMPRESSED_ARGB_4444_VQ_KOS; break;
|
||||
default: UF_EXCEPTION(filename << ": invalid texture format"); return false;
|
||||
}
|
||||
}
|
||||
} else { UF_EXCEPTION(filename << ": not a compressed texture"); return false; }
|
||||
/*
|
||||
UF_DEBUG_MSG("DTEX Header: " << header.id[0] << header.id[1] << header.id[2] << header.id[3] << " | "
|
||||
<< header.width << " x " << header.height << " | "
|
||||
<< twiddled << " | "
|
||||
<< compressed << " | "
|
||||
<< mipmapped << " | "
|
||||
<< strided << " | "
|
||||
<< header.size << " | "
|
||||
<< std::bitset<32>(format) << " | "
|
||||
<< std::bitset<32>(this->m_format)
|
||||
);
|
||||
*/
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -261,6 +275,7 @@ void uf::Image::copy( const uf::Image& copy ) {
|
||||
this->m_bpp = copy.m_bpp;
|
||||
this->m_channels = copy.m_channels;
|
||||
this->m_filename = copy.m_filename;
|
||||
this->m_format = copy.m_format;
|
||||
}
|
||||
// D-tor
|
||||
uf::Image::~Image() {
|
||||
@ -426,5 +441,6 @@ uf::Image& uf::Image::operator=( const uf::Image& copy ) {
|
||||
this->m_bpp = copy.m_bpp;
|
||||
this->m_channels = copy.m_channels;
|
||||
this->m_filename = copy.m_filename;
|
||||
this->m_format = copy.m_format;
|
||||
return *this;
|
||||
}
|
||||
@ -93,7 +93,7 @@ const pod::Vector3f& uf::MeshGrid::center() const { return this->m_center; }
|
||||
const pod::Vector3f& uf::MeshGrid::extent() const { return this->m_extent; }
|
||||
|
||||
void uf::MeshGrid::insert( uint32_t i1, uint32_t i2, uint32_t i3, const pod::Vector3f& v1, const pod::Vector3f& v2, const pod::Vector3f& v3 ) {
|
||||
#if 1
|
||||
#if 0
|
||||
bool useStrongest = false;
|
||||
int32_t strongestNode = -1;
|
||||
pod::Collider::Manifold strongestManifold = {};
|
||||
@ -125,7 +125,7 @@ void uf::MeshGrid::insert( uint32_t i1, uint32_t i2, uint32_t i3, const pod::Vec
|
||||
node.indices.emplace_back(i3);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
#if 1
|
||||
auto center = centroid( v1, v2, v3 );
|
||||
for ( size_t i = 0; i < this->m_nodes.size(); ++i ) {
|
||||
auto& node = this->m_nodes[i];
|
||||
|
||||
@ -44,11 +44,11 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
graphic.process = false;
|
||||
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
|
||||
|
||||
if ( graph.atlas ) {
|
||||
if ( graph.atlas.generated() ) {
|
||||
for ( auto& texture : graph.textures ) {
|
||||
++texture.storage.index;
|
||||
}
|
||||
auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas->getAtlas());
|
||||
auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas.getAtlas());
|
||||
auto& texture = *graph.textures.emplace(graph.textures.begin());
|
||||
texture.name = "atlas";
|
||||
texture.bind = true;
|
||||
|
||||
@ -30,10 +30,17 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
if ( ++::roundRobin.current >= ::roundRobin.lights.size() ) ::roundRobin.current = 0;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
if ( !metadataJson["light"]["bias"]["shader"].is<float>() ) {
|
||||
metadataJson["light"]["bias"]["shader"] = 0.000000005f;
|
||||
}
|
||||
*/
|
||||
if ( !metadataJson["light"]["bias"]["constant"].is<float>() ) {
|
||||
metadataJson["light"]["bias"]["constant"] = 0.00005f;
|
||||
}
|
||||
if ( !metadataJson["light"]["type"].is<std::string>() ) {
|
||||
metadataJson["light"]["type"] = "point";
|
||||
}
|
||||
if ( !ext::json::isArray( metadataJson["light"]["color"] ) ) {
|
||||
metadataJson["light"]["color"][0] = 1; //metadataJson["light"]["color"]["random"].as<bool>() ? (rand() % 100) / 100.0 : 1;
|
||||
metadataJson["light"]["color"][1] = 1; //metadataJson["light"]["color"]["random"].as<bool>() ? (rand() % 100) / 100.0 : 1;
|
||||
@ -70,7 +77,6 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.metadata["type"] = "depth";
|
||||
renderMode.metadata["depth bias"] = metadataJson["light"]["bias"];
|
||||
renderMode.metadata["renderMode"] = metadataJson["renderMode"];
|
||||
// std::cout << this->getName() << ": " << renderMode.metadata["renderMode"] << std::endl;
|
||||
|
||||
if ( metadataJson["light"]["type"].as<std::string>() == "point" ) {
|
||||
metadataJson["light"]["fov"] = 90.0f;
|
||||
@ -88,7 +94,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
auto& cameraSize = camera.getSize();
|
||||
renderMode.width = cameraSize.x;
|
||||
renderMode.height = cameraSize.y;
|
||||
|
||||
// UF_DEBUG_MSG(this->getName() << ": " << renderMode.metadata << " | " << metadataJson["light"]);
|
||||
}
|
||||
|
||||
metadata.serialize = [&](){
|
||||
@ -100,8 +106,8 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
metadataJson["light"]["external update"] = metadata.renderer.external;
|
||||
metadataJson["system"]["renderer"]["timer"] = metadata.renderer.limiter;
|
||||
switch ( metadata.type ) {
|
||||
case 0: metadataJson["light"]["type"] = ""; break;
|
||||
case 1: metadataJson["light"]["type"] = "point"; break;
|
||||
case 0: metadataJson["light"]["type"] = "point"; break;
|
||||
case 1: metadataJson["light"]["type"] = "spot"; break;
|
||||
case 2: metadataJson["light"]["type"] = "spot"; break;
|
||||
}
|
||||
};
|
||||
@ -118,8 +124,8 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
metadata.type = metadataJson["light"]["type"].as<size_t>();
|
||||
} else if ( metadataJson["light"]["type"].is<std::string>() ) {
|
||||
std::string lightType = metadataJson["light"]["type"].as<std::string>();
|
||||
if ( lightType == "point" ) metadata.type = 1;
|
||||
else if ( lightType == "spot" ) metadata.type = 2;
|
||||
if ( lightType == "point" ) metadata.type = 0;
|
||||
else if ( lightType == "spot" ) metadata.type = 1;
|
||||
}
|
||||
};
|
||||
this->addHook( "object:UpdateMetadata.%UID%", metadata.deserialize);
|
||||
@ -148,8 +154,8 @@ void ext::LightBehavior::tick( uf::Object& self ) {
|
||||
metadata.type = metadataJson["light"]["type"].as<size_t>();
|
||||
} else if ( metadataJson["light"]["type"].is<std::string>() ) {
|
||||
std::string lightType = metadataJson["light"]["type"].as<std::string>();
|
||||
if ( lightType == "point" ) metadata.type = 1;
|
||||
else if ( lightType == "spot" ) metadata.type = 2;
|
||||
if ( lightType == "point" ) metadata.type = 0;
|
||||
else if ( lightType == "spot" ) metadata.type = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -217,7 +223,7 @@ void ext::LightBehavior::tick( uf::Object& self ) {
|
||||
if ( !metadata.renderer.external ) {
|
||||
auto& camera = this->getComponent<uf::Camera>();
|
||||
// omni light
|
||||
if ( metadata.shadows && metadata.type == 1 ) {
|
||||
if ( metadata.shadows && metadata.type == 0 ) {
|
||||
auto transform = camera.getTransform();
|
||||
std::vector<pod::Quaternion<>> rotations = {
|
||||
uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 ),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
||||
#include <uf/ext/ext.h>
|
||||
#include <uf/engine/entity/entity.h>
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/utils/math/vector.h>
|
||||
|
||||
namespace ext {
|
||||
namespace GuiBehavior {
|
||||
@ -13,5 +14,46 @@ namespace ext {
|
||||
void tick( uf::Object& );
|
||||
void render( uf::Object& );
|
||||
void destroy( uf::Object& );
|
||||
struct Metadata {
|
||||
pod::Vector4f color = {1,1,1,1};
|
||||
bool world = false;
|
||||
pod::Vector2f size = {0,0};
|
||||
size_t mode = 0;
|
||||
struct {
|
||||
pod::Vector2f min = { 1, 1 };
|
||||
pod::Vector2f max = { -1, -1 };
|
||||
} box;
|
||||
bool clicked = false;
|
||||
bool hovered = false;
|
||||
|
||||
pod::Vector4f uv = {0, 0, 1, 1};
|
||||
size_t shader = 0;
|
||||
float depth = 0;
|
||||
float alpha = -1;
|
||||
|
||||
std::function<void()> serialize;
|
||||
std::function<void()> deserialize;
|
||||
};
|
||||
struct GlyphMetadata {
|
||||
std::string font = "";
|
||||
std::string string = "";
|
||||
|
||||
float scale = 0;
|
||||
pod::Vector2f padding = {0,0};
|
||||
|
||||
float spread = 0;
|
||||
float size = 0;
|
||||
float weight = 0;
|
||||
bool sdf = false;
|
||||
bool shadowbox = false;
|
||||
pod::Vector4f stroke = {0,0,0,0};
|
||||
|
||||
std::string origin = "";
|
||||
std::string align = "";
|
||||
std::string direction = "";
|
||||
|
||||
std::function<void()> serialize;
|
||||
std::function<void()> deserialize;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,7 @@ namespace pod {
|
||||
namespace ext {
|
||||
class EXT_API Gui : public uf::Object {
|
||||
public:
|
||||
typedef uf::BaseMesh<pod::Vertex_3F2F3F> mesh_t;
|
||||
typedef uf::BaseMesh<pod::Vertex_3F2F3F> glyph_mesh_t;
|
||||
// Gui();
|
||||
std::vector<pod::GlyphBox> generateGlyphs( const std::string& = "" );
|
||||
|
||||
@ -35,10 +35,11 @@ ext::gui::Size ext::gui::size = {
|
||||
0,
|
||||
0,
|
||||
},
|
||||
.reference = {
|
||||
1920,
|
||||
1080
|
||||
},
|
||||
#if UF_ENV_DREAMCAST
|
||||
.reference = { 960, 720 },
|
||||
#else
|
||||
.reference = { 1920, 1080 },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -46,21 +47,16 @@ UF_BEHAVIOR_REGISTER_CPP(ext::GuiManagerBehavior)
|
||||
UF_BEHAVIOR_REGISTER_AS_OBJECT(ext::GuiManagerBehavior, ext::GuiManager)
|
||||
#define this (&self)
|
||||
void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
{
|
||||
// ext::gui::size.current.x = uf::renderer::settings::width;
|
||||
// ext::gui::size.current.y = uf::renderer::settings::height;
|
||||
}
|
||||
// add gui render mode
|
||||
#if UF_USE_VULKAN
|
||||
if ( !uf::renderer::hasRenderMode( "Gui", true ) ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
std::string name = "Gui";
|
||||
uf::renderer::addRenderMode( &renderMode, name );
|
||||
renderMode.blitter.descriptor.subpass = 1;
|
||||
}
|
||||
#endif
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
uf::Asset& assetLoader = this->getComponent<uf::Asset>();
|
||||
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
auto& assetLoader = this->getComponent<uf::Asset>();
|
||||
|
||||
this->addHook( "window:Resized", [&](ext::json::Value& json){
|
||||
|
||||
@ -91,11 +87,11 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
{
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = scene.getController();
|
||||
auto& metadata = controller.getComponent<uf::Serializer>();
|
||||
|
||||
if ( metadata["overlay"]["cursor"]["type"].as<std::string>() == "mouse" ) {
|
||||
metadata["overlay"]["cursor"]["position"][0] = click.x;
|
||||
metadata["overlay"]["cursor"]["position"][1] = click.y;
|
||||
auto& metadata = controller.getComponent<ext::GuiManagerBehavior::Metadata>();
|
||||
auto& metadataJson = controller.getComponent<uf::Serializer>();
|
||||
// if ( metadata.cursor.type == "mouse" ) metadata.cursor.position = click;
|
||||
if ( metadataJson["overlay"]["cursor"]["type"].as<std::string>() == "mouse" ) {
|
||||
metadataJson["overlay"]["cursor"]["position"] = uf::vector::encode( click );
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -103,11 +99,11 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
void ext::GuiManagerBehavior::tick( uf::Object& self ) {
|
||||
}
|
||||
void ext::GuiManagerBehavior::render( uf::Object& self ){
|
||||
#if UF_USE_VULKAN
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
auto& metadata = controller.getComponent<uf::Serializer>();
|
||||
|
||||
auto& metadataJson = controller.getComponent<uf::Serializer>();
|
||||
|
||||
uf::renderer::RenderTargetRenderMode* renderModePointer = NULL;
|
||||
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
@ -119,7 +115,6 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){
|
||||
auto& blitter = renderMode.blitter;
|
||||
|
||||
if ( !blitter.initialized ) return;
|
||||
#if UF_USE_VULKAN
|
||||
if ( !blitter.material.hasShader("fragment") ) return;
|
||||
|
||||
struct UniformDescriptor {
|
||||
@ -140,28 +135,12 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){
|
||||
|
||||
for ( size_t i = 0; i < 2; ++i ) {
|
||||
pod::Transform<> transform;
|
||||
if ( ext::json::isArray( metadata["overlay"]["position"] ) )
|
||||
transform.position = {
|
||||
metadata["overlay"]["position"][0].as<float>(),
|
||||
metadata["overlay"]["position"][1].as<float>(),
|
||||
metadata["overlay"]["position"][2].as<float>(),
|
||||
};
|
||||
if ( ext::json::isArray( metadata["overlay"]["scale"] ) )
|
||||
transform.scale = {
|
||||
metadata["overlay"]["scale"][0].as<float>(),
|
||||
metadata["overlay"]["scale"][1].as<float>(),
|
||||
metadata["overlay"]["scale"][2].as<float>(),
|
||||
};
|
||||
if ( ext::json::isArray( metadata["overlay"]["orientation"] ) )
|
||||
transform.orientation = {
|
||||
metadata["overlay"]["orientation"][0].as<float>(),
|
||||
metadata["overlay"]["orientation"][1].as<float>(),
|
||||
metadata["overlay"]["orientation"][2].as<float>(),
|
||||
metadata["overlay"]["orientation"][3].as<float>(),
|
||||
};
|
||||
transform.position = uf::vector::decode( metadataJson["overlay"]["position"], transform.position );
|
||||
transform.scale = uf::vector::decode( metadataJson["overlay"]["scale"], transform.scale );
|
||||
transform.orientation = uf::vector::decode( metadataJson["overlay"]["orientation"], transform.orientation );
|
||||
#if UF_USE_OPENVR
|
||||
if ( ext::openvr::enabled && (metadata["overlay"]["enabled"].as<bool>() || uf::renderer::getRenderMode("Stereoscopic Deferred", true).getType() == "Stereoscopic Deferred" )) {
|
||||
if ( metadata["overlay"]["floating"].as<bool>() ) {
|
||||
if ( ext::openvr::enabled && metadataJson["overlay"]["enabled"].as<bool>() ) {
|
||||
if ( metadataJson["overlay"]["floating"].as<bool>() ) {
|
||||
pod::Matrix4f model = uf::transform::model( transform );
|
||||
uniforms.matrices.models[i] = camera.getProjection(i) * ext::openvr::hmdEyePositionMatrix( i == 0 ? vr::Eye_Left : vr::Eye_Right ) * model;
|
||||
} else {
|
||||
@ -181,12 +160,12 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){
|
||||
|
||||
|
||||
pod::Vector3f cursorSize = { 0, 0 };
|
||||
if ( metadata["overlay"]["cursor"]["enabled"].as<bool>() ) {
|
||||
uniforms.cursor.position.x = (metadata["overlay"]["cursor"]["position"][0].as<float>() + 1.0f) * 0.5f; //(::mouse.position.x + 1.0f) * 0.5f;
|
||||
uniforms.cursor.position.y = (metadata["overlay"]["cursor"]["position"][1].as<float>() + 1.0f) * 0.5f; //(::mouse.position.y + 1.0f) * 0.5f;
|
||||
if ( metadataJson["overlay"]["cursor"]["enabled"].as<bool>() ) {
|
||||
uniforms.cursor.position.x = (metadataJson["overlay"]["cursor"]["position"][0].as<float>() + 1.0f) * 0.5f; //(::mouse.position.x + 1.0f) * 0.5f;
|
||||
uniforms.cursor.position.y = (metadataJson["overlay"]["cursor"]["position"][1].as<float>() + 1.0f) * 0.5f; //(::mouse.position.y + 1.0f) * 0.5f;
|
||||
|
||||
cursorSize.x = metadata["overlay"]["cursor"]["radius"].as<float>();
|
||||
cursorSize.y = metadata["overlay"]["cursor"]["radius"].as<float>();
|
||||
cursorSize.x = metadataJson["overlay"]["cursor"]["radius"].as<float>();
|
||||
cursorSize.y = metadataJson["overlay"]["cursor"]["radius"].as<float>();
|
||||
|
||||
cursorSize = uf::matrix::multiply<float>( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity() , transform.scale) ), cursorSize );
|
||||
|
||||
@ -194,10 +173,7 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){
|
||||
uniforms.cursor.radius.y = cursorSize.y;
|
||||
}
|
||||
|
||||
uniforms.cursor.color.x = metadata["overlay"]["cursor"]["color"][0].as<float>();
|
||||
uniforms.cursor.color.y = metadata["overlay"]["cursor"]["color"][1].as<float>();
|
||||
uniforms.cursor.color.z = metadata["overlay"]["cursor"]["color"][2].as<float>();
|
||||
uniforms.cursor.color.w = metadata["overlay"]["cursor"]["color"][3].as<float>();
|
||||
uniforms.cursor.color = uf::vector::decode( metadataJson["overlay"]["cursor"]["color"], pod::Vector4f{0,0,0,0} );
|
||||
}
|
||||
|
||||
shader.updateUniform( "UBO", uniform );
|
||||
|
||||
@ -13,5 +13,8 @@ namespace ext {
|
||||
void tick( uf::Object& );
|
||||
void render( uf::Object& );
|
||||
void destroy( uf::Object& );
|
||||
struct Metadata {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -706,14 +706,7 @@ void EXT_API ext::tick() {
|
||||
++::times.frames;
|
||||
double every = fps["every"].as<double>();
|
||||
TIMER( every ) {
|
||||
// UF_DEBUG_MSG("Framerate: " << (1.0/times.deltaTime) << " FPS | Frametime: " << (times.deltaTime * 1000) << "ms");
|
||||
UF_DEBUG_MSG("System: " << (every * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time);
|
||||
#if UF_ENV_DREAMCAST
|
||||
// pvr_stats_t stats;
|
||||
// pvr_get_stats(&stats);
|
||||
// UF_DEBUG_MSG("PVR stats: " << stats.frame_last_time << " ms | " << stats.frame_rate << " fps | " << stats.reg_last_time << " ms | " << stats.rnd_last_time << " ms | " << stats.vtx_buffer_used << " bytes | " << stats.vtx_buffer_used_max << " bytes | " << stats.buf_last_time << " ms" );
|
||||
#endif
|
||||
|
||||
::times.frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
ARCH = win64
|
||||
PREFIX = gcc
|
||||
CC = /opt/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++
|
||||
FLAGS += -Wno-unknown-pragmas -std=c++17 -O2 -g -fdiagnostics-color=always -Wall -Wno-conversion-null -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-unused-but-set-variable -Wno-ignored-attributes -Wno-narrowing -Wno-misleading-indentation
|
||||
FLAGS += -Wno-unknown-pragmas -std=c++17 -Og -g -fdiagnostics-color=always -Wall -Wno-conversion-null -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-unused-but-set-variable -Wno-ignored-attributes -Wno-narrowing -Wno-misleading-indentation
|
||||
Loading…
Reference in New Issue
Block a user