Commit for 2022.03.27 22-01-29.7z

This commit is contained in:
mrq 2022-03-27 22:01:00 -05:00
parent 4a96f148ad
commit b904c7f280
37 changed files with 799 additions and 574 deletions

View File

@ -3,7 +3,7 @@ CC = $(shell cat "./bin/exe/default.config")
TARGET_NAME = program
TARGET_EXTENSION = exe
TARGET_LIB_EXTENSION = dll
RENDERER = opengl
RENDERER = vulkan
include makefiles/$(ARCH).$(CC).make
@ -32,9 +32,10 @@ EXT_LIB_NAME += ext
#VULKAN_SDK_PATH += /c/VulkanSDK/1.2.176.1/
#VULKAN_SDK_PATH += /c/VulkanSDK/1.2.182.0/
VULKAN_SDK_PATH += /c/VulkanSDK/1.2.198.1/
#VULKAN_SDK_PATH += /c/VulkanSDK/1.3.204.1/
#GLSL_VALIDATOR += $(VULKAN_SDK_PATH)/Bin/glslangValidator
GLSL_VALIDATOR += $(VULKAN_SDK_PATH)/Bin/glslc
#GLSLC += $(VULKAN_SDK_PATH)/Bin/glslangValidator
GLSLC += $(VULKAN_SDK_PATH)/Bin/glslc
SPV_OPTIMIZER += $(VULKAN_SDK_PATH)/Bin/spirv-opt
# Base Engine's DLL
INC_DIR += $(ENGINE_INC_DIR)/$(ARCH)/$(CC)
@ -282,7 +283,7 @@ $(TARGET): $(OBJS)
endif
%.spv: %.glsl
$(GLSL_VALIDATOR) -std=450 -o $@ $<
$(GLSLC) -std=450 -o $@ $<
$(SPV_OPTIMIZER) --preserve-bindings --preserve-spec-constants -O $@ -o $@
ifneq (,$(findstring dreamcast,$(ARCH)))

View File

@ -2,7 +2,7 @@
"engine": {
"scenes": {
"start": "SS2",
"meshes": { "interleaved": true },
"meshes": { "interleave": false },
"matrix": { "reverseInfinite": true },
"lights": {
"max": 24,
@ -46,8 +46,11 @@
"ext": {
"vulkan": {
"validation": {
"enabled": false,
"enabled": true,
"filters": [
"MessageID = 0x124ffb34", // VUID-VkImageMemoryBarrier-oldLayout-01197
"MessageID = 0x8ab1932c", // VUID-VkImageViewCreateInfo-imageViewType-04973
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
// "MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
@ -71,11 +74,11 @@
"deferred reconstruct position": true,
"deferred alias output to swapchain": false,
"vsync": true,
"hdr": false,
"hdr": true,
"vxgi": true,
"deferred sampling": false,
"culling": true,
"bloom": true
"bloom": false
},
"formats": {
"depth": "D32_SFLOAT",
@ -143,10 +146,11 @@
},
"reactphysics": {
"timescale": 0.01666666666,
"interpolate": false,
"debug draw": {
"enabled": false,
// "layer": "Gui",
"rate": 0.06666666666
"rate": 0.0125
}
},
"bullet": {
@ -201,11 +205,11 @@
},
"render modes": { "gui": true, "deferred": true },
"limiters": {
"deltaTime": 10,
"deltaTime": 5,
"framerate": "auto"
},
"threads": {
"workers" : "async", // "auto"
"workers" : "auto", // "async"
"frame limiter": "auto"
},
"debug": {
@ -241,9 +245,9 @@
"mode" : "windowed", // fullscreen, borderless, windowed
"icon" : "./data/textures/icon.png",
// "size" : [ 1920, 1080 ],
// "size" : [ 1280, 720 ],
"size" : [ 1280, 720 ],
// "size" : [ 960, 540 ],
"size" : [ 640, 480 ],
// "size" : [ 640, 480 ],
// "size" : [ 256, 224 ],
"title" : "Grimgram",
"visible" : true

View File

@ -15,8 +15,8 @@
"print tree": false,
"print stats": false
},
"export": {
"should": true,
"exporter": {
"enabled": true,
"pretty": false,
"compress": true,
"quantize": false,
@ -26,7 +26,7 @@
"unwrap": true
},
"baking": {
"enabled": true,
"enabled": false,
"resolution": 8192,
"shadows": 1024,
"trigger": { "mode": "rendered" },

View File

@ -1,9 +1,9 @@
{
"import": "/model.json",
"assets": [
// { "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" }
{ "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/tiny_msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
{ "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
@ -20,6 +20,14 @@
],
"metadata": {
"model": {
"chunk": {
"enabled": true,
"size": 3, // [3,3,3],
"target": "worldspawn"
},
"exporter": {
"enabled": false
},
"baking": {
"enabled": false,
"resolution": 8192,

View File

@ -65,6 +65,7 @@
},
"reactphysics": {
"timescale": 0.03333333333,
"interpolate": false,
"debug draw": {
"enabled": false,
// "layer": "Gui",
@ -75,8 +76,8 @@
"audio": {
"mute": false,
"buffers": {
"size": 4096,
"count": 2
"size": 16384,
"count": 3
},
"volumes": {
"sfx": 1.0,

View File

@ -1,5 +1,6 @@
#include "../main.h"
#include <uf/utils/io/inputs.h>
#include <uf/utils/window/window.h>
#include <uf/utils/io/iostream.h>
#include <uf/utils/image/image.h>
@ -102,8 +103,8 @@ void client::initialize() {
} );
}
#if !UF_ENV_DREAMCAST
if ( client::config["window"]["mode"].as<std::string>() == "fullscreen" ) client::window.switchToFullscreen();
else if ( client::config["window"]["mode"].as<std::string>() == "borderless" ) client::window.switchToFullscreen( true );
if ( client::config["window"]["mode"].as<std::string>() == "fullscreen" ) client::window.toggleFullscreen();
else if ( client::config["window"]["mode"].as<std::string>() == "borderless" ) client::window.toggleFullscreen( true );
#endif
client::ready = true;
@ -116,28 +117,37 @@ void client::tick() {
client::window.bufferInputs();
client::window.pollEvents();
if ( client::window.hasFocus() && client::config["window"]["mouse"]["center"].as<bool>() ) {
auto previous = client::window.getMousePosition();
client::window.setMousePosition(client::window.getSize()/2);
auto current = client::window.getMousePosition();
auto size = client::window.getSize();
if ( client::window.hasFocus() ) {
// fullscreener
TIMER(1, (uf::inputs::kbm::states::LAlt || uf::inputs::kbm::states::RAlt) && uf::inputs::kbm::states::Enter && ) {
UF_MSG_DEBUG("mpoop fullscreen");
client::window.toggleFullscreen( false );
uf::renderer::states::resized = true;
}
// mouse move
if ( client::config["window"]["mouse"]["center"].as<bool>() ) {
auto previous = client::window.getMousePosition();
client::window.setMousePosition(client::window.getSize()/2);
auto current = client::window.getMousePosition();
auto size = client::window.getSize();
uf::hooks.call("window:Mouse.Moved", pod::payloads::windowMouseMoved{
{
uf::hooks.call("window:Mouse.Moved", pod::payloads::windowMouseMoved{
{
"window:Mouse.Moved",
"client",
{
"window:Mouse.Moved",
"client",
},
{
pod::Vector2ui{ size.x, size.y },
},
},
{
pod::Vector2ui{ size.x, size.y },
},
},
{
current,
previous - current,
0
}
});
current,
previous - current,
0
}
});
}
}
}

View File

@ -56,10 +56,12 @@ namespace ext {
extern UF_API size_t defaultMaxCollisionAlgorithmPoolSize;
extern UF_API size_t defaultMaxPersistentManifoldPoolSize;
extern UF_API bool debugDrawEnabled;
extern UF_API float debugDrawRate;
extern UF_API uf::stl::string debugDrawLayer;
extern UF_API float debugDrawLineWidth;
namespace debugDraw {
extern UF_API bool enabled;
extern UF_API float rate;
extern UF_API uf::stl::string layer;
extern UF_API float lineWidth;
}
void UF_API initialize();
void UF_API tick( float = 0 );
@ -78,14 +80,13 @@ namespace ext {
pod::PhysicsState& create( uf::Object&, const uf::Mesh&, bool );
// collider for boundingbox
pod::PhysicsState& UF_API create( uf::Object&, const pod::Vector3f& );
uf::stl::vector<pod::PhysicsState>& UF_API create( uf::Object&, const uf::stl::vector<pod::Instance::Bounds>& );
// collider for capsule
pod::PhysicsState& UF_API create( uf::Object&, float, float );
// synchronize engine transforms to bullet transforms
void UF_API syncTo();
// synchronize bullet transforms to engine transforms
void UF_API syncFrom();
void UF_API syncFrom( float = 1 );
// apply impulse
void UF_API applyImpulse( pod::PhysicsState&, const pod::Vector3f& );
// directly move a transform
@ -104,9 +105,6 @@ namespace ext {
// allows noclip
void UF_API activateCollision( pod::PhysicsState&, bool = true );
// allows showing collision models
void UF_API debugDraw( uf::Object& );
}
}
#endif

View File

@ -22,18 +22,25 @@ namespace pod {
rp3d::CollisionShape* shape = NULL;
pod::Transform<> transform = {};
pod::Transform<> previous = {};
struct {
pod::Vector3 velocity;
pod::Vector3 acceleration;
struct Linear {
pod::Vector3f velocity;
pod::Vector3f acceleration;
} linear;
struct {
struct Angular {
pod::Quaternion<> velocity;
pod::Quaternion<> acceleration;
} rotational;
struct {
struct {
pod::Transform<> transform = {};
Linear linear;
Angular rotational;
} current, previous;
} internal;
struct {
uint32_t flags = 0;
float mass = 0.0f;
@ -54,10 +61,15 @@ namespace ext {
void UF_API terminate();
extern UF_API float timescale;
extern UF_API bool debugDrawEnabled;
extern UF_API float debugDrawRate;
extern UF_API uf::stl::string debugDrawLayer;
extern UF_API float debugDrawLineWidth;
extern UF_API bool interpolate;
extern UF_API bool shared;
namespace debugDraw {
extern UF_API bool enabled;
extern UF_API float rate;
extern UF_API uf::stl::string layer;
extern UF_API float lineWidth;
}
// base collider creation
pod::PhysicsState& UF_API create( uf::Object& );
@ -78,7 +90,7 @@ namespace ext {
// synchronize engine transforms to bullet transforms
void UF_API syncTo();
// synchronize bullet transforms to engine transforms
void UF_API syncFrom();
void UF_API syncFrom( float = 1 );
// apply impulse
void UF_API applyImpulse( pod::PhysicsState&, const pod::Vector3f& );
// directly move a transform
@ -97,9 +109,6 @@ namespace ext {
// allows noclip
void UF_API activateCollision( pod::PhysicsState&, bool = true );
// allows showing collision models
void UF_API debugDraw( uf::Object& );
}
}
#endif

View File

@ -24,7 +24,7 @@
#define TIMER_LAMBDA(x) []() {\
static uf::Timer<long long> timer(false);\
if ( !timer.running() ) timer.start(uf::Time<long long>(-1000000));\
uf::physics::num_t time = timer.elapsed();\
double time = timer.elapsed();\
if ( time >= every ) timer.reset();\
static bool first = true; if ( first ) { first = false; return every; }\
return time;\
@ -33,7 +33,7 @@
#define TIMER(x, ...)\
static uf::Timer<long long> timer(false);\
if ( !timer.running() ) timer.start(uf::Time<long long>(-1000000));\
uf::physics::num_t time = timer.elapsed();\
double time = timer.elapsed();\
if ( time >= x ) timer.reset();\
if ( __VA_ARGS__ time >= x )

View File

@ -64,7 +64,7 @@ namespace spec {
void UF_API setTracking(bool state);
static pod::Vector2ui UF_API getResolution();
void UF_API switchToFullscreen( bool borderless = false );
void UF_API toggleFullscreen( bool borderless = false );
};
}
typedef spec::dreamcast::Window Window;

View File

@ -71,7 +71,7 @@ namespace spec {
void UF_API_CALL setTracking(bool state);
static pod::Vector2ui UF_API_CALL getResolution();
void UF_API_CALL switchToFullscreen( bool borderless = false );
void UF_API_CALL toggleFullscreen( bool borderless = false );
#if defined(UF_USE_VULKAN) && UF_USE_VULKAN == 1
uf::stl::vector<uf::stl::string> UF_API_CALL getExtensions( bool validationEnabled );
void UF_API_CALL createSurface( VkInstance instance, VkSurfaceKHR& surface );

View File

@ -1,6 +1,6 @@
#include <iostream>
template<typename T> pod::Transform<T>& uf::physics::update( pod::Transform<T>& transform, pod::Physics& physics ) {
physics.previous = transform;
// physics.internal.previous = transform;
if ( physics.linear.acceleration != pod::Vector3t<T>{0,0,0} )
physics.linear.velocity += (physics.linear.acceleration * uf::physics::time::delta);

View File

@ -52,6 +52,7 @@ namespace uf {
template<typename T> pod::Matrix4t<T> /*UF_API*/ model( const pod::Transform<T>& transform, bool flatten = false, size_t depth = SIZE_MAX );
template<typename T> pod::Transform<T> /*UF_API*/ fromMatrix( const pod::Matrix4t<T>& matrix );
template<typename T> pod::Transform<T>& /*UF_API*/ reference( pod::Transform<T>& transform, const pod::Transform<T>& parent, bool reorient = true );
template<typename T> pod::Transform<T> /*UF_API*/ interpolate( const pod::Transform<T>& from, const pod::Transform<T>& to, float factor, bool reorient = true );
template<typename T> uf::stl::string /*UF_API*/ toString( const pod::Transform<T>&, bool flatten = true );
template<typename T> ext::json::Value /*UF_API*/ encode( const pod::Transform<T>&, bool flatten = true, const ext::json::EncodingSettings& = {} );

View File

@ -150,7 +150,12 @@ template<typename T> pod::Transform<T>& /*UF_API*/ uf::transform::reference( pod
transform.reference = const_cast<pod::Transform<T>*>(&parent);
return transform;
}
template<typename T> pod::Transform<T> /*UF_API*/ uf::transform::interpolate( const pod::Transform<T>& from, const pod::Transform<T>& to, float factor, bool reorient ) {
pod::Transform transform = to;
transform.position = uf::vector::lerp( from.position, to.position, factor );
transform.orientation = uf::quaternion::slerp( from.orientation, to.orientation, factor );
return reorient ? uf::transform::reorient( transform ) : transform;
}
template<typename T> // Normalizes a vector
uf::stl::string /*UF_API*/ uf::transform::toString( const pod::Transform<T>& t, bool flatten ) {
pod::Transform<T> transform = flatten ? uf::transform::flatten(t) : t;

View File

@ -172,10 +172,8 @@ T /*UF_API*/ uf::vector::negate( const T& vector ) {
}
template<typename T> //
T /*UF_API*/ uf::vector::abs( const T& vector ) {
ALIGN16 T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = abs(vector[i]);
T res;
for ( auto i = 0; i < T::size; ++i ) res[i] = std::abs( vector[i] );
return res;
}
// Writes to first value

View File

@ -1,10 +1,27 @@
#if 0
#pragma once
#include <uf/config.h>
#include <uf/utils/mesh/mesh.h>
#include <limits>
namespace uf {
namespace meshgrid {
struct UF_API Node {
struct {
pod::Vector3f min = {};
pod::Vector3f max = {};
} extents;
pod::Vector3ui id = {};
uf::stl::vector<uf::stl::vector<uint32_t>> indices;
};
uf::stl::vector<Node> UF_API partition( uf::Mesh&, int );
}
}
#if 0
namespace uf {
class UF_API MeshGrid {
protected:

View File

@ -1,3 +1,4 @@
#if 0
template<typename T, typename U>
void uf::MeshGrid::initialize( const uf::Mesh<T,U>& mesh, size_t divisions ) {
return initialize<T,U>( mesh, pod::Vector3ui{ divisions, divisions, divisions } );
@ -62,4 +63,5 @@ const uf::stl::vector<U>& uf::MeshGrid::get( const pod::Vector3f& point ) const
#else
return at( point ).indices;
#endif
}
}
#endif

View File

@ -124,6 +124,7 @@ namespace uf {
void generateIndirect();
bool isInterleaved() const;
bool isInterleaved( const uf::Mesh::Input& ) const;
bool isInterleaved( size_t ) const;
buffer_t& getBuffer( const uf::Mesh::Input&, size_t = 0 );
@ -132,6 +133,13 @@ namespace uf {
const buffer_t& getBuffer( const uf::Mesh::Input&, size_t = 0 ) const;
const buffer_t& getBuffer( const uf::Mesh::Input&, const uf::Mesh::Attribute& ) const;
void eraseAttribute( uf::Mesh::Input&, const uf::Mesh::Attribute& );
void eraseAttribute( uf::Mesh::Input&, size_t );
uf::Mesh::Input remapInput( const uf::Mesh::Input&, size_t i = 0 ) const;
uf::Mesh::Input remapVertexInput( size_t i = 0 ) const;
uf::Mesh::Input remapIndexInput( size_t i = 0 ) const;
void print( bool = true ) const;
std::string printVertices( bool = true ) const;
@ -139,10 +147,6 @@ namespace uf {
std::string printInstances( bool = true ) const;
std::string printIndirects( bool = true ) const;
uf::Mesh::Input remapInput( const uf::Mesh::Input&, size_t i = 0 ) const;
uf::Mesh::Input remapVertexInput( size_t i = 0 ) const;
uf::Mesh::Input remapIndexInput( size_t i = 0 ) const;
inline bool hasVertex( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) const { return _hasV( vertex, descriptors ); }
inline bool hasVertex( const uf::Mesh& mesh ) const { return _hasV( vertex, mesh.vertex ); }
inline void bindVertex( const uf::stl::vector<ext::RENDERER::AttributeDescriptor>& descriptors ) { return _bindV( vertex, descriptors ); }

View File

@ -40,7 +40,7 @@ namespace uf {
void UF_API_CALL requestFocus();
bool UF_API_CALL hasFocus() const;
static pod::Vector2ui UF_API_CALL getResolution();
void UF_API_CALL switchToFullscreen( bool borderless = false );
void UF_API_CALL toggleFullscreen( bool borderless = false );
#if defined(UF_USE_VULKAN) && UF_USE_VULKAN == 1
uf::stl::vector<uf::stl::string> getExtensions( bool validationEnabled = true );

View File

@ -292,12 +292,11 @@ uf::stl::string uf::Asset::load(const uf::Asset::Payload& payload ) {
UF_ASSET_REGISTER(pod::Graph)
auto& metadata = this->getComponent<uf::Serializer>();
#if UF_USE_OPENGL_FIXED_FUNCTION
#if UF_USE_OPENGL
// combining mesh is only really a (negligent) gain on Vulkan
// collision meshes still use separated meshes, so avoid having to duplicate a mesh for very little gains, if any
metadata[payload.filename]["flags"]["ATLAS"] = false;
// metadata[payload.filename]["flags"]["SEPARATE"] = true;
#elif UF_GRAPH_INDIRECT_DRAW
// metadata[payload.filename]["flags"]["ATLAS"] = false;
// metadata[payload.filename]["flags"]["SEPARATE"] = false;
metadata[payload.filename]["flags"]["SEPARATE"] = true;
#endif
asset = uf::graph::load( filename, metadata[payload.filename] );
uf::graph::process( asset );

View File

@ -222,10 +222,22 @@ namespace {
const uf::stl::string directory = uf::io::directory( graph.name );
auto& buffer = mesh.buffers.emplace_back(uf::io::readAsBuffer( directory + "/" + filename ));
});
// remove extraneous buffers
#if UF_USE_OPENGL
for ( auto& attribute : mesh.vertex.attributes ) {
if ( attribute.descriptor.name == "position" ) continue;
if ( attribute.descriptor.name == "color" ) continue;
if ( attribute.descriptor.name == "uv" ) continue;
if ( attribute.descriptor.name == "st" ) continue;
}
#endif
mesh.updateDescriptor();
// return mesh.expand();
// if ( mesh.isInterleaved() != uf::Mesh::defaultInterleaved ) return mesh.copy(true);
return mesh;
}

View File

@ -225,14 +225,14 @@ void uf::graph::save( const pod::Graph& graph, const uf::stl::string& filename )
const ::EncodingSettings settings = ::EncodingSettings{
{
/*.pretty = */graph.metadata["export"]["pretty"].as<bool>(),
/*.compress = */graph.metadata["export"]["compress"].as<bool>(),
/*.quantize = */graph.metadata["export"]["quantize"].as<bool>(),
/*.precision = */graph.metadata["export"]["precision"].as<uint8_t>(),
/*.pretty = */graph.metadata["exporter"]["pretty"].as<bool>(),
/*.compress = */graph.metadata["exporter"]["compress"].as<bool>(),
/*.quantize = */graph.metadata["exporter"]["quantize"].as<bool>(),
/*.precision = */graph.metadata["exporter"]["precision"].as<uint8_t>(),
},
/*.combined = */graph.metadata["export"]["combined"].as<bool>(),
/*.encodeBuffers = */graph.metadata["export"]["encode buffers"].as<bool>(true),
/*.unwrap = */graph.metadata["export"]["unwrap"].as<bool>(true),
/*.combined = */graph.metadata["exporter"]["combined"].as<bool>(),
/*.encodeBuffers = */graph.metadata["exporter"]["encode buffers"].as<bool>(true),
/*.unwrap = */graph.metadata["exporter"]["unwrap"].as<bool>(true),
/*.filename = */directory + "/graph.json",
};
if ( !settings.combined ) uf::io::mkdir(directory);

View File

@ -10,7 +10,7 @@
#include <uf/ext/xatlas/xatlas.h>
#if UF_ENV_DREAMCAST
#define UF_GRAPH_LOAD_MULTITHREAD 0
#define UF_GRAPH_LOAD_MULTITHREAD 1
#else
#define UF_GRAPH_LOAD_MULTITHREAD 1
#endif
@ -490,43 +490,32 @@ void uf::graph::process( pod::Graph& graph ) {
mesh.insertVertices( m );
mesh.insertIndices( m );
mesh.insertInstances( m );
// mesh.insertIndirects( m );
pod::DrawCommand* dc = (pod::DrawCommand*) m.getBuffer( m.indirect ).data();
for ( size_t i = 0; i < m.indirect.count; ++i ) drawCommands.emplace_back( dc[i] );
}
mesh.insertIndirects( drawCommands );
mesh = mesh.expand();
mesh = mesh.copy(true);
// fix up draw command for combined mesh
{
auto& attribute = mesh.indirect.attributes.front();
auto& buffer = mesh.getBuffer(mesh.indirect); // mesh.buffers[mesh.isInterleaved(mesh.indirect.interleaved) ? mesh.indirect.interleaved : attribute.buffer];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) buffer.data();
size_t totalIndices = 0;
size_t totalVertices = 0;
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
auto& drawCommand = drawCommands[i];
for ( auto& drawCommand : drawCommands ) {
drawCommand.indexID = totalIndices;
drawCommand.vertexID = totalVertices;
totalIndices += drawCommand.indices;
totalVertices += drawCommand.vertices;
}
/*
if ( totalIndices > mesh.index.count ) {
UF_MSG_ERROR("Calculated total indices exceed actual indices count: expecting " << mesh.index.count << ", got " << totalIndices);
UF_EXCEPTION("invalid drawCommand");
}
if ( totalVertices > mesh.vertex.count ) {
UF_MSG_ERROR("Calculated total vertices exceed actual vertices count: expecting " << mesh.vertex.count << ", got " << totalVertices);
UF_EXCEPTION("invalid drawCommand");
}
*/
mesh.insertIndirects( drawCommands );
}
// slice mesh
{
auto slices = uf::meshgrid::partition( mesh, 3 );
}
{
auto& graphic = graph.root.entity->getComponent<uf::Graphic>();
graphic.initialize();
@ -726,10 +715,10 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
auto max = uf::matrix::multiply<float>( model, bounds.max, 1.0f );
pod::Vector3f center = (max + min) * 0.5f;
pod::Vector3f corner = (max - min) * 0.5f;
corner.x = abs(corner.x);
corner.y = abs(corner.y);
corner.z = abs(corner.z);
pod::Vector3f corner = uf::vector::abs(max - min) * 0.5f;
// corner.x = abs(corner.x);
// corner.y = abs(corner.y);
// corner.z = abs(corner.z);
metadataJson["system"]["physics"]["center"] = uf::vector::encode( center );
metadataJson["system"]["physics"]["corner"] = uf::vector::encode( corner );

View File

@ -8,67 +8,102 @@
#include <uf/engine/graph/graph.h>
#include <BulletCollision/CollisionShapes/btTriangleShape.h>
struct VertexLine {
pod::Vector3f position;
pod::Vector3f color;
namespace {
struct VertexLine {
pod::Vector3f position;
pod::Vector3f color;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
UF_VERTEX_DESCRIPTOR(VertexLine,
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, color)
);
UF_VERTEX_DESCRIPTOR(VertexLine,
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, color)
);
class BulletDebugDrawer : public btIDebugDraw {
protected:
int m;
uf::Mesh mesh;
public:
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& color ) {
drawLine( from, to, color, color );
}
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor ) {
uf::stl::vector<VertexLine> vertices;
{
auto& vertex = vertices.emplace_back();
vertex.position = { from.getX(), from.getY(), from.getZ() };
vertex.color = { fromColor.getX(), fromColor.getY(), fromColor.getZ() };
class BulletDebugDrawer : public btIDebugDraw {
protected:
int m;
uf::Mesh mesh;
public:
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& color ) {
drawLine( from, to, color, color );
}
{
auto& vertex = vertices.emplace_back();
vertex.position = { to.getX(), to.getY(), to.getZ() };
vertex.color = { toColor.getX(), toColor.getY(), toColor.getZ() };
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor ) {
uf::stl::vector<VertexLine> vertices;
{
auto& vertex = vertices.emplace_back();
vertex.position = { from.getX(), from.getY(), from.getZ() };
vertex.color = { fromColor.getX(), fromColor.getY(), fromColor.getZ() };
}
{
auto& vertex = vertices.emplace_back();
vertex.position = { to.getX(), to.getY(), to.getZ() };
vertex.color = { toColor.getX(), toColor.getY(), toColor.getZ() };
}
if ( !mesh.hasVertex<VertexLine>() ) mesh.bind<VertexLine>();
mesh.insertVertices(vertices);
}
if ( !mesh.hasVertex<VertexLine>() ) mesh.bind<VertexLine>();
mesh.insertVertices(vertices);
}
virtual void drawContactPoint(const btVector3&, const btVector3&, btScalar, int, const btVector3&) {
virtual void drawContactPoint(const btVector3&, const btVector3&, btScalar, int, const btVector3&) {
}
virtual void reportErrorWarning(const char* str ) {
UF_MSG_WARNING("[Bullet] " << str);
}
virtual void draw3dText(const btVector3& , const char* str ) {
}
virtual void reportErrorWarning(const char* str ) {
UF_MSG_WARNING("[Bullet] " << str);
}
virtual void draw3dText(const btVector3& , const char* str ) {
}
virtual void setDebugMode(int p) {
m = p;
}
virtual void clearLines() {
for ( auto& buffer : mesh.buffers ) buffer.clear();
mesh.vertex.count = 0;
mesh.index.count = 0;
}
virtual void flushLines() {
auto& scene = uf::scene::getCurrentScene();
ext::bullet::debugDraw( scene );
}
int getDebugMode(void) const { return m; }
}
virtual void setDebugMode(int p) {
m = p;
}
virtual void clearLines() {
for ( auto& buffer : mesh.buffers ) buffer.clear();
mesh.vertex.count = 0;
mesh.index.count = 0;
}
virtual void flushLines() {
auto& scene = uf::scene::getCurrentScene();
ext::bullet::debugDraw( scene );
}
int getDebugMode(void) const { return m; }
uf::Mesh& getMesh() { return mesh; }
const uf::Mesh& getMesh() const { return mesh; }
};
uf::Mesh& getMesh() { return mesh; }
const uf::Mesh& getMesh() const { return mesh; }
};
void UF_API ext::bullet::debugDraw( uf::Object& object ) {
auto& mesh = ext::bullet::debugDrawer.getMesh();
if ( !mesh.vertex.count ) return;
bool create = !object.hasComponent<uf::Graphic>();
auto& graphic = object.getComponent<uf::Graphic>();
graphic.process = false;
if ( create ) {
graphic.device = &uf::renderer::device;
graphic.material.device = &uf::renderer::device;
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.getShader("vertex").buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
graphic.initialize(ext::bullet::debugDrawLayer);
graphic.initializeMesh( mesh );
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
graphic.descriptor.lineWidth = ext::bullet::debugDrawLineWidth;
} else {
if ( graphic.updateMesh( mesh ) ) {
graphic.getPipeline().update( graphic );
}
}
graphic.process = true;
}
}
size_t ext::bullet::iterations = 1;
size_t ext::bullet::substeps = 12;
@ -314,7 +349,7 @@ pod::PhysicsState& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh
auto& indexAttribute = mesh.index.attributes.front();
PHY_ScalarType indexType = PHY_INTEGER;
PHY_ScalarType vertexType = PHY_FLOAT;
switch ( mesh.index.stride ) {
switch ( mesh.index.size ) {
case sizeof(uint8_t): indexType = PHY_UCHAR; break;
case sizeof(uint16_t): indexType = PHY_SHORT; break;
case sizeof(uint32_t): indexType = PHY_INTEGER; break;
@ -323,18 +358,24 @@ pod::PhysicsState& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh
btIndexedMesh iMesh;
if ( mesh.indirect.count ) {
uf::Mesh::Attribute remappedVertexAttribute;
uf::Mesh::Attribute remappedIndexAttribute;
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
remappedVertexAttribute = mesh.remapVertexAttribute( vertexAttribute, i );
remappedIndexAttribute = mesh.remapIndexAttribute( indexAttribute, i );
uf::Mesh::Attribute remappedVertexAttribute = vertexAttribute;
uf::Mesh::Attribute remappedIndexAttribute = indexAttribute;
iMesh.m_numTriangles = remappedIndexAttribute.length / 3;
iMesh.m_triangleIndexBase = (const uint8_t*) remappedIndexAttribute.pointer;
uf::Mesh::Input remappedVertexInput;
uf::Mesh::Input remappedIndexInput;
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
remappedVertexInput = mesh.remapVertexInput( i );
remappedIndexInput = mesh.remapIndexInput( i );
// remappedVertexAttribute = mesh.remapVertexAttribute( vertexAttribute, i );
// remappedIndexAttribute = mesh.remapIndexAttribute( indexAttribute, i );
iMesh.m_numTriangles = remappedIndexInput.count / 3;
iMesh.m_triangleIndexBase = (const uint8_t*) remappedIndexAttribute.pointer + remappedIndexAttribute.stride * remappedIndexInput.first;
iMesh.m_triangleIndexStride = remappedIndexAttribute.stride * 3;
iMesh.m_numVertices = remappedVertexAttribute.length;
iMesh.m_vertexBase = (const uint8_t*) remappedVertexAttribute.pointer;
iMesh.m_numVertices = remappedVertexInput.count;
iMesh.m_vertexBase = (const uint8_t*) remappedVertexAttribute.pointer + remappedVertexAttribute.stride * remappedVertexInput.first;
iMesh.m_vertexStride = remappedVertexAttribute.stride;
iMesh.m_indexType = indexType;
iMesh.m_vertexType = vertexType;
@ -342,12 +383,12 @@ pod::PhysicsState& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh
bMesh->addIndexedMesh( iMesh, indexType );
}
} else {
iMesh.m_numTriangles = indexAttribute.length / 3;
iMesh.m_triangleIndexBase = (const uint8_t*) indexAttribute.pointer;
iMesh.m_numTriangles = mesh.index.count / 3;
iMesh.m_triangleIndexBase = (const uint8_t*) indexAttribute.pointer + indexAttribute.stride * mesh.index.count;
iMesh.m_triangleIndexStride = indexAttribute.stride * 3;
iMesh.m_numVertices = vertexAttribute.length;
iMesh.m_vertexBase = (const uint8_t*) vertexAttribute.pointer;
iMesh.m_numVertices = mesh.vertex.count;
iMesh.m_vertexBase = (const uint8_t*) vertexAttribute.pointer + vertexAttribute.stride * mesh.vertex.count;
iMesh.m_vertexStride = vertexAttribute.stride;
iMesh.m_indexType = indexType;
iMesh.m_vertexType = vertexType;
@ -544,37 +585,4 @@ float UF_API ext::bullet::rayCast( const pod::Vector3f& from, const pod::Vector3
uid = (uf::Object*) body->getUserPointer();
return pen;
}
void UF_API ext::bullet::debugDraw( uf::Object& object ) {
auto& mesh = ext::bullet::debugDrawer.getMesh();
if ( !mesh.vertex.count ) return;
bool create = !object.hasComponent<uf::Graphic>();
auto& graphic = object.getComponent<uf::Graphic>();
graphic.process = false;
if ( create ) {
graphic.device = &uf::renderer::device;
graphic.material.device = &uf::renderer::device;
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.getShader("vertex").buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
graphic.initialize(ext::bullet::debugDrawLayer);
graphic.initializeMesh( mesh );
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
graphic.descriptor.lineWidth = ext::bullet::debugDrawLineWidth;
} else {
if ( graphic.updateMesh( mesh ) ) {
graphic.getPipeline().update( graphic );
}
}
graphic.process = true;
}
#endif

View File

@ -406,6 +406,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
}
}
if ( graph.metadata["export"]["should"].as<bool>() ) uf::graph::save( graph, filename );
if ( graph.metadata["exporter"]["enabled"].as<bool>() ) uf::graph::save( graph, filename );
return graph;
}

View File

@ -411,23 +411,6 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
else if ( attribute.descriptor.name == "normal" ) drawCommandInfo.attributes.normal = attribute;
else if ( attribute.descriptor.name == "color" ) drawCommandInfo.attributes.color = attribute;
}
/*
{
float* p = (float*) (drawCommandInfo.attributes.position.pointer + drawCommandInfo.attributes.position.stride * drawCommandInfo.descriptor.inputs.vertex.first);
// float* p = (float*) drawCommandInfo.attributes.position.pointer;
UF_MSG_DEBUG( "[" << i << "] [" << drawCommandInfo.descriptor.inputs.vertex.first << "] (" << p[0] << ", " << p[1] << ", " << p[2] << ")" );
}
*/
/*
for ( size_t i = 0; i < drawCommand.vertices; ++i ) {
float* p = (float*) (drawCommandInfo.attributes.position.pointer + drawCommandInfo.attributes.position.stride * (i + drawCommand.vertexID));
float* uv = (float*) (drawCommandInfo.attributes.uv.pointer + drawCommandInfo.attributes.uv.stride * (i + drawCommand.vertexID));
std::cout << "(" << p[0] << ", " << p[1] << ", " << p[2] << "|" << uv[0] << ", " << uv[1] << ") ";
}
std::cout << std::endl;
*/
drawCommandInfo.attributes.instance.pointer = &instance;
drawCommandInfo.attributes.instance.length = sizeof(instance);

View File

@ -6,8 +6,6 @@
#include <uf/engine/scene/scene.h>
#include <uf/engine/graph/graph.h>
#define UF_PHYSICS_SHARED 1
namespace {
rp3d::PhysicsCommon common;
rp3d::PhysicsWorld* world;
@ -40,13 +38,158 @@ namespace {
rp3d::DefaultLogger* logger = NULL;
pod::Vector3f convert( const rp3d::Vector3& v ) { return pod::Vector3f{ v.x, v.y, v.z }; }
rp3d::Vector3 convert( const pod::Vector3f& v ) { return rp3d::Vector3( v.x, v.y, v.z ); }
pod::Quaternion<> convert( const rp3d::Quaternion& q ) { return pod::Quaternion<>{ q.x, q.y, q.z, q.w }; }
rp3d::Quaternion convert( const pod::Quaternion<>& q ) { return rp3d::Quaternion( q.x, q.y, q.z, q.w ); }
pod::Transform<> convert( const rp3d::Transform& t ) {
pod::Transform<> transform;
/*state.*/transform.position = ::convert(t.getPosition());
/*state.*/transform.orientation = ::convert(t.getOrientation());
return uf::transform::reorient(/*state.*/transform);
}
rp3d::Transform convert( const pod::Transform<>& t ) {
auto model = uf::transform::model( t );
rp3d::Transform transform;
transform.setFromOpenGL(&model[0]);
return transform;
}
pod::Quaternion<> convertQ( const rp3d::Vector3& _v ) {
pod::Quaternion<> q = uf::quaternion::identity();
pod::Vector3f v = ::convert( _v );
q.w = uf::vector::norm( v );
if ( q.w > 0 ) q = { v.x / q.w, v.y / q.w, v.z / q.w, q.w };
return q;
}
rp3d::Vector3 convertQ( const pod::Quaternion<>& q ) {
rp3d::Vector3 v;
v.x = q.x * q.w;
v.y = q.y * q.w;
v.z = q.z * q.w;
return v;
}
pod::Vector3f uintToVector( uint32_t u ) {
switch ( u ) {
case (uint) rp3d::DebugRenderer::DebugColor::RED: return pod::Vector3f{ 1.0f, 0.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::GREEN: return pod::Vector3f{ 0.0f, 1.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::BLUE: return pod::Vector3f{ 0.0f, 0.0f, 1.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::BLACK: return pod::Vector3f{ 0.0f, 0.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::WHITE: return pod::Vector3f{ 1.0f, 1.0f, 1.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::YELLOW: return pod::Vector3f{ 1.0f, 1.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::MAGENTA: return pod::Vector3f{ 1.0f, 0.0f, 1.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::CYAN: return pod::Vector3f{ 0.0f, 1.0f, 1.0f }; break;
default: return pod::Vector3f{};
}
}
struct VertexLine {
pod::Vector3f position;
pod::Vector3f color;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
UF_VERTEX_DESCRIPTOR(VertexLine,
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, color)
);
// allows showing collision models
void debugDraw( uf::Object& object ) {
static size_t oldCount = 0;
uf::Mesh mesh;
rp3d::DebugRenderer& debugRenderer = ::world->getDebugRenderer();
if ( !mesh.hasVertex<VertexLine>() ) mesh.bind<VertexLine>();
size_t lineCount = debugRenderer.getNbLines();
size_t triCount = debugRenderer.getNbTriangles();
if ( !lineCount || !triCount ) return;
if ( oldCount == lineCount * 2 + triCount * 3 ) return;
oldCount = lineCount * 2 + triCount * 3;
auto* lines = debugRenderer.getLinesArray();
auto* tris = debugRenderer.getTrianglesArray();
uf::stl::vector<VertexLine> vertices;
vertices.reserve( lineCount * 2 + triCount * 3 );
for ( size_t i = 0; i < lineCount; ++i ) {
auto& line = lines[i];
auto& vertex1 = vertices.emplace_back();
vertex1.position = ::convert( line.point1 );
vertex1.color = ::uintToVector( line.color1 );
auto& vertex2 = vertices.emplace_back();
vertex2.position = ::convert( line.point2 );
vertex2.color = ::uintToVector( line.color2 );
}
for ( size_t i = 0; i < triCount; ++i ) {
auto& tri = tris[i];
auto& vertex1 = vertices.emplace_back();
vertex1.position = ::convert( tri.point1 );
vertex1.color = ::uintToVector( tri.color1 );
auto& vertex2 = vertices.emplace_back();
vertex2.position = ::convert( tri.point2 );
vertex2.color = ::uintToVector( tri.color2 );
auto& vertex3 = vertices.emplace_back();
vertex3.position = ::convert( tri.point3 );
vertex3.color = ::uintToVector( tri.color3 );
}
mesh.insertVertices(vertices);
if ( !mesh.vertex.count ) return;
bool create = !object.hasComponent<uf::Graphic>();
auto& graphic = object.getComponent<uf::Graphic>();
graphic.process = false;
if ( create ) {
graphic.device = &uf::renderer::device;
graphic.material.device = &uf::renderer::device;
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.getShader("vertex").buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
graphic.initialize(ext::reactphysics::debugDraw::layer);
graphic.initializeMesh( mesh );
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
graphic.descriptor.lineWidth = ext::reactphysics::debugDraw::lineWidth;
} else {
if ( graphic.updateMesh( mesh ) ) {
graphic.getPipeline().update( graphic );
}
}
graphic.process = true;
}
}
float ext::reactphysics::timescale = 1.0f / 60.0f;
bool ext::reactphysics::debugDrawEnabled = false;
float ext::reactphysics::debugDrawRate = 1.0f;
uf::stl::string ext::reactphysics::debugDrawLayer = "";
float ext::reactphysics::debugDrawLineWidth = 1.0f;
bool ext::reactphysics::shared = true;
bool ext::reactphysics::interpolate = true;
bool ext::reactphysics::debugDraw::enabled = false;
float ext::reactphysics::debugDraw::rate = 1.0f;
uf::stl::string ext::reactphysics::debugDraw::layer = "";
float ext::reactphysics::debugDraw::lineWidth = 1.0f;
void ext::reactphysics::initialize() {
rp3d::PhysicsWorld::WorldSettings settings;
@ -60,7 +203,7 @@ void ext::reactphysics::initialize() {
::world = ::common.createPhysicsWorld(settings);
// ::world->setEventListener(&::listener);
if ( ext::reactphysics::debugDrawEnabled ) {
if ( ext::reactphysics::debugDraw::enabled ) {
::world->setIsDebugRenderingEnabled(true);
rp3d::DebugRenderer& debugRenderer = ::world->getDebugRenderer();
// Select the contact points and contact normals to be displayed
@ -71,9 +214,7 @@ void ext::reactphysics::initialize() {
}
}
void ext::reactphysics::tick( float delta ) {
#if UF_PHYSICS_SHARED
ext::reactphysics::syncTo();
#endif
static float accumulator = 0;
@ -84,12 +225,12 @@ void ext::reactphysics::tick( float delta ) {
accumulator -= ext::reactphysics::timescale;
}
TIMER(ext::reactphysics::debugDrawRate, ext::reactphysics::debugDrawEnabled && ) {
TIMER(ext::reactphysics::debugDraw::rate, ext::reactphysics::debugDraw::enabled && ) {
auto& scene = uf::scene::getCurrentScene();
ext::reactphysics::debugDraw( scene );
::debugDraw( scene );
}
ext::reactphysics::syncFrom();
ext::reactphysics::syncFrom( accumulator / ext::reactphysics::timescale );
}
void ext::reactphysics::terminate() {
::common.destroyPhysicsWorld(::world);
@ -103,11 +244,8 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object ) {
state.uid = object.getUid();
state.object = &object;
state.transform.reference = &object.getComponent<pod::Transform<>>();
#if UF_PHYSICS_SHARED
state.shared = true;
#else
state.shared = false;
#endif
state.shared = ext::reactphysics::shared;
return state;
}
@ -121,38 +259,21 @@ void ext::reactphysics::destroy( pod::PhysicsState& state ) {
void ext::reactphysics::attach( pod::PhysicsState& state ) {
if ( !state.shape ) return;
rp3d::Transform bodyTransform = rp3d::Transform::identity();
rp3d::Transform colliderTransform = rp3d::Transform::identity();
#if !UF_SPOOKY_JANK
colliderTransform.setPosition( rp3d::Vector3( state.transform.position.x, state.transform.position.y, state.transform.position.z ) );
colliderTransform.setOrientation( rp3d::Quaternion( state.transform.orientation.x, state.transform.orientation.y, state.transform.orientation.z, state.transform.orientation.w ) );
rp3d::Transform colliderTransform = rp3d::Transform::identity();
colliderTransform.setPosition( ::convert( state.transform.position ) );
colliderTransform.setOrientation( ::convert( state.transform.orientation ) );
state.transform.position = {};
state.transform.orientation = {};
auto model = uf::transform::model( *state.transform.reference );
bodyTransform.setFromOpenGL(&model[0]);
#else
// has a parent, separate main transform to collider, and parent transform to body
if ( state.transform.reference ) {
auto model = uf::transform::model( *state.transform.reference );
bodyTransform.setFromOpenGL(&model[0]);
colliderTransform.setPosition( rp3d::Vector3( state.transform.position.x, state.transform.position.y, state.transform.position.z ) );
colliderTransform.setOrientation( rp3d::Quaternion( state.transform.orientation.x, state.transform.orientation.y, state.transform.orientation.z, state.transform.orientation.w ) );
// no parent, use for both
} else {
auto model = uf::transform::model( state.transform );
bodyTransform.setFromOpenGL(&model[0]);
}
#endif
state.body = ::world->createRigidBody(bodyTransform);
state.body = ::world->createRigidBody( ::convert( *state.transform.reference ) );
auto* collider = state.body->addCollider(state.shape, colliderTransform);
state.body->setUserData(state.object);
state.body->setMass(state.stats.mass);
if ( state.stats.mass != 0.0f ) {
state.body->setType(rp3d::BodyType::DYNAMIC);
state.body->updateLocalCenterOfMassFromColliders();
@ -164,7 +285,7 @@ void ext::reactphysics::attach( pod::PhysicsState& state ) {
auto& material = collider->getMaterial();
material.setBounciness(0);
state.body->setLocalInertiaTensor( rp3d::Vector3( state.stats.inertia.x, state.stats.inertia.y, state.stats.inertia.z ) );
state.body->setLocalInertiaTensor( ::convert( state.stats.inertia ) );
}
void ext::reactphysics::detach( pod::PhysicsState& state ) {
if ( !state.body ) return;
@ -178,8 +299,6 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh
auto* rMesh = ::common.createTriangleMesh();
mesh.print( false );
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Input indexInput = mesh.index;
@ -229,62 +348,6 @@ pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh
indexType
));
}
/*
if ( mesh.index.count ) {
uf::Mesh::Attribute vertexAttribute;
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) { vertexAttribute = attribute; break; }
UF_ASSERT( vertexAttribute.descriptor.name == "position" );
auto& indexAttribute = mesh.index.attributes.front();
rp3d::TriangleVertexArray::IndexDataType indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE;
rp3d::TriangleVertexArray::VertexDataType vertexType = rp3d::TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE;
switch ( mesh.index.size ) {
case sizeof(uint16_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_SHORT_TYPE; break;
case sizeof(uint32_t): indexType = rp3d::TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE; break;
default: UF_EXCEPTION("unsupported index type"); break;
}
rp3d::TriangleVertexArray* vArray;
if ( mesh.indirect.count ) {
uf::Mesh::Attribute remappedVertexAttribute;
uf::Mesh::Attribute remappedIndexAttribute;
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
remappedVertexAttribute = mesh.remapVertexAttribute( vertexAttribute, i );
remappedIndexAttribute = mesh.remapIndexAttribute( indexAttribute, i );
vArray = new rp3d::TriangleVertexArray(
remappedVertexAttribute.length / mesh.vertex.size,
(const uint8_t*) remappedVertexAttribute.pointer,
remappedVertexAttribute.stride,
remappedIndexAttribute.length / mesh.index.size / 3,
(const uint8_t*) remappedIndexAttribute.pointer,
remappedIndexAttribute.stride * 3,
vertexType,
indexType
);
rMesh->addSubpart(vArray);
}
} else {
vArray = new rp3d::TriangleVertexArray(
mesh.vertex.count,
(const uint8_t*) vertexAttribute.pointer,
vertexAttribute.stride,
mesh.index.count / 3,
(const uint8_t*) indexAttribute.pointer,
indexAttribute.stride * 3,
vertexType,
indexType
);
rMesh->addSubpart(vArray);
}
} else UF_EXCEPTION("to-do: not require indices for meshes");
*/
auto& state = ext::reactphysics::create( object );
state.shape = ::common.createConcaveMeshShape( rMesh );
@ -316,56 +379,63 @@ void ext::reactphysics::syncTo() {
for ( size_t i = 0; i < count; ++i ) {
auto* body = ::world->getRigidBody(i); if ( !body ) continue;
uf::Object* object = (uf::Object*) body->getUserData(); if ( !object ) continue;
auto& state = object->getComponent<pod::PhysicsState>(); if ( !state.shared ) continue;
auto& state = object->getComponent<pod::PhysicsState>(); // if ( !state.shared ) continue;
auto model = uf::transform::model( state.transform );
rp3d::Transform transform;
transform.setFromOpenGL(&model[0]);
body->setTransform(transform);
body->setLinearVelocity( rp3d::Vector3( state.linear.velocity.x, state.linear.velocity.y, state.linear.velocity.z ) );
if ( state.shared ) {
if ( !ext::reactphysics::interpolate ) body->setTransform(::convert(state.transform));
// body->setTransform(::convert(state.transform));
body->setLinearVelocity( ::convert(state.linear.velocity) );
body->setAngularVelocity( ::convertQ(state.rotational.velocity) );
}
state.internal.previous = state.internal.current;
}
}
// synchronize bullet transforms to engine transforms
void ext::reactphysics::syncFrom() {
void ext::reactphysics::syncFrom( float interp ) {
size_t count = ::world->getNbRigidBodies();
for ( size_t i = 0; i < count; ++i ) {
auto* body = ::world->getRigidBody(i); if ( !body ) continue;
uf::Object* object = (uf::Object*) body->getUserData(); if ( !object ) continue;
auto position = body->getTransform().getPosition();
auto orientation = body->getTransform().getOrientation();
auto linearVelocity = body->getLinearVelocity();
auto rotationalVelocity = body->getAngularVelocity();
auto& state = object->getComponent<pod::PhysicsState>();;
auto& transform = state.object->getComponent<pod::Transform<>>();
auto& physics = state.object->getComponent<pod::Physics>();
/*state.*/transform.position.x = position.x;
/*state.*/transform.position.y = position.y;
/*state.*/transform.position.z = position.z;
/*
transform.position = ::convert( body->getTransform().getPosition() );
transform.orientation = ::convert( body->getTransform().getOrientation() );
// state transform is an offset, un-offset
if ( state.transform.reference ) {
transform.position -= state.transform.position;
if ( state.transform.reference ) transform.position -= state.transform.position;
// transform = uf::transform::reorient( transform );
*/
state.internal.current.transform = ::convert( body->getTransform() );
state.internal.current.linear.velocity = ::convert( body->getLinearVelocity() );
state.internal.current.rotational.velocity = ::convertQ( body->getAngularVelocity() );
physics.linear.velocity = state.internal.current.linear.velocity;
physics.rotational.velocity = state.internal.current.rotational.velocity;
if ( !ext::reactphysics::interpolate ) {
transform.position = state.internal.current.transform.position;
transform.orientation = state.internal.current.transform.orientation;
// state transform is an offset, un-offset
if ( state.transform.reference ) transform.position -= state.transform.position;
// transform = uf::transform::reorient( transform );
} else {
// transform = uf::transform::interpolate( state.internal.previous.transform, state.internal.current.transform, interp );
transform.position = state.internal.previous.transform.position * ( 1.0f - interp ) + state.internal.current.transform.position * interp;
transform.orientation = uf::quaternion::slerp( state.internal.previous.transform.orientation, state.internal.current.transform.orientation, interp);
if ( state.transform.reference ) transform.position -= state.transform.position;
// physics.linear.velocity = uf::vector::lerp( state.internal.previous.linear.velocity, state.internal.current.linear.velocity, interp );
// physics.rotational.velocity = uf::quaternion::slerp( state.internal.previous.rotational.velocity, state.internal.current.rotational.velocity, interp );
}
/*state.*/transform.orientation.x = orientation.x;
/*state.*/transform.orientation.y = orientation.y;
/*state.*/transform.orientation.z = orientation.z;
/*state.*/transform.orientation.w = orientation.w;
physics.linear.velocity.x = linearVelocity.x;
physics.linear.velocity.y = linearVelocity.y;
physics.linear.velocity.z = linearVelocity.z;
physics.rotational.velocity.x = rotationalVelocity.x;
physics.rotational.velocity.y = rotationalVelocity.y;
physics.rotational.velocity.z = rotationalVelocity.z;
transform = uf::transform::reorient( transform );
}
}
// apply impulse
@ -376,7 +446,7 @@ void ext::reactphysics::applyMovement( pod::PhysicsState& state, const pod::Vect
if ( !state.body ) return;
rp3d::Transform transform = state.body->getTransform();
transform.setPosition( transform.getPosition() + rp3d::Vector3( v.x, v.y, v.z ) * uf::physics::time::delta );
transform.setPosition( transform.getPosition() + ::convert(v) * uf::physics::time::delta );
state.body->setTransform(transform);
}
// directly apply a velocity
@ -385,9 +455,9 @@ void ext::reactphysics::setVelocity( pod::PhysicsState& state, const pod::Vector
if ( state.shared ) {
auto& physics = state.object->getComponent<pod::Physics>();
physics.linear.velocity = v;
} else {
state.body->setLinearVelocity( rp3d::Vector3( v.x, v.y, v.z ) );
// return;
}
state.body->setLinearVelocity( ::convert(v) );
}
void ext::reactphysics::applyVelocity( pod::PhysicsState& state, const pod::Vector3f& v ) {
if ( !state.body ) return;
@ -395,9 +465,9 @@ void ext::reactphysics::applyVelocity( pod::PhysicsState& state, const pod::Vect
if ( state.shared ) {
auto& physics = state.object->getComponent<pod::Physics>();
physics.linear.velocity += v;
} else {
state.body->setLinearVelocity( state.body->getLinearVelocity() + rp3d::Vector3( v.x, v.y, v.z ) );
// return;
}
state.body->setLinearVelocity( state.body->getLinearVelocity() + ::convert(v) );
}
// directly rotate a transform
void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Quaternion<>& q ) {
@ -406,14 +476,10 @@ void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Quat
if ( state.shared ) {
auto& transform = state.object->getComponent<pod::Transform<>>();
uf::transform::rotate( transform, q );
return;
// return;
}
auto transform = state.body->getTransform();
auto o = transform.getOrientation();
pod::Quaternion<> orientation = uf::vector::normalize(uf::quaternion::multiply({ o.x, o.y, o.z, o.w, }, q));
transform.setOrientation( rp3d::Quaternion( orientation.x, orientation.y, orientation.z, orientation.w ) );
transform.setOrientation( transform.getOrientation() * ::convert( q ) );
state.body->setTransform(transform);
}
void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Vector3f& axis, float delta ) {
@ -427,7 +493,7 @@ float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector
return -1;
::RaycastCallback callback;
::world->raycast( rp3d::Ray( rp3d::Vector3( center.x, center.y, center.z ), rp3d::Vector3( direction.x, direction.y, direction.z ) ), &callback );
::world->raycast( rp3d::Ray( ::convert( center ), ::convert( direction ) ), &callback );
if ( !callback.isHit ) return -1;
return callback.raycastInfo.hitFraction;
}
@ -436,7 +502,7 @@ float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector
return -1;
::RaycastCallback callback;
::world->raycast( rp3d::Ray( rp3d::Vector3( center.x, center.y, center.z ), rp3d::Vector3( direction.x, direction.y, direction.z ) ), &callback );
::world->raycast( rp3d::Ray( ::convert( center ), ::convert( direction ) ), &callback );
uid = 0;
if ( !callback.isHit ) {
return -1;
@ -450,7 +516,7 @@ float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector
return -1;
::RaycastCallback callback;
::world->raycast( rp3d::Ray( rp3d::Vector3( center.x, center.y, center.z ), rp3d::Vector3( direction.x, direction.y, direction.z ) ), &callback );
::world->raycast( rp3d::Ray( ::convert( center ), ::convert( direction ) ), &callback );
object = NULL;
if ( !callback.isHit ) {
return -1;
@ -464,111 +530,4 @@ void ext::reactphysics::activateCollision( pod::PhysicsState& state, bool s ) {
}
struct VertexLine {
pod::Vector3f position;
pod::Vector3f color;
static UF_API uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
UF_VERTEX_DESCRIPTOR(VertexLine,
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(VertexLine, R32G32B32_SFLOAT, color)
);
namespace {
pod::Vector3f uintToVector( uint32_t u ) {
switch ( u ) {
case (uint) rp3d::DebugRenderer::DebugColor::RED: return pod::Vector3f{ 1.0f, 0.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::GREEN: return pod::Vector3f{ 0.0f, 1.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::BLUE: return pod::Vector3f{ 0.0f, 0.0f, 1.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::BLACK: return pod::Vector3f{ 0.0f, 0.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::WHITE: return pod::Vector3f{ 1.0f, 1.0f, 1.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::YELLOW: return pod::Vector3f{ 1.0f, 1.0f, 0.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::MAGENTA: return pod::Vector3f{ 1.0f, 0.0f, 1.0f }; break;
case (uint) rp3d::DebugRenderer::DebugColor::CYAN: return pod::Vector3f{ 0.0f, 1.0f, 1.0f }; break;
default: return pod::Vector3f{};
}
}
}
// allows showing collision models
void ext::reactphysics::debugDraw( uf::Object& object ) {
static size_t oldCount = 0;
uf::Mesh mesh;
rp3d::DebugRenderer& debugRenderer = ::world->getDebugRenderer();
if ( !mesh.hasVertex<VertexLine>() ) mesh.bind<VertexLine>();
size_t lineCount = debugRenderer.getNbLines();
size_t triCount = debugRenderer.getNbTriangles();
if ( !lineCount || !triCount ) return;
if ( oldCount == lineCount * 2 + triCount * 3 ) return;
oldCount = lineCount * 2 + triCount * 3;
auto* lines = debugRenderer.getLinesArray();
auto* tris = debugRenderer.getTrianglesArray();
uf::stl::vector<VertexLine> vertices;
vertices.reserve( lineCount * 2 + triCount * 3 );
for ( size_t i = 0; i < lineCount; ++i ) {
auto& line = lines[i];
auto& vertex1 = vertices.emplace_back();
vertex1.position = { line.point1.x, line.point1.y, line.point1.z };
vertex1.color = uintToVector( line.color1 );
auto& vertex2 = vertices.emplace_back();
vertex2.position = { line.point2.x, line.point2.y, line.point2.z };
vertex2.color = uintToVector( line.color2 );
}
for ( size_t i = 0; i < triCount; ++i ) {
auto& tri = tris[i];
auto& vertex1 = vertices.emplace_back();
vertex1.position = { tri.point1.x, tri.point1.y, tri.point1.z };
vertex1.color = uintToVector( tri.color1 );
auto& vertex2 = vertices.emplace_back();
vertex2.position = { tri.point2.x, tri.point2.y, tri.point2.z };
vertex2.color = uintToVector( tri.color2 );
auto& vertex3 = vertices.emplace_back();
vertex3.position = { tri.point3.x, tri.point3.y, tri.point3.z };
vertex3.color = uintToVector( tri.color3 );
}
mesh.insertVertices(vertices);
if ( !mesh.vertex.count ) return;
bool create = !object.hasComponent<uf::Graphic>();
auto& graphic = object.getComponent<uf::Graphic>();
graphic.process = false;
if ( create ) {
graphic.device = &uf::renderer::device;
graphic.material.device = &uf::renderer::device;
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root + "/shaders/bullet/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
graphic.material.getShader("vertex").buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
graphic.initialize(ext::reactphysics::debugDrawLayer);
graphic.initializeMesh( mesh );
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
graphic.descriptor.lineWidth = ext::reactphysics::debugDrawLineWidth;
} else {
if ( graphic.updateMesh( mesh ) ) {
graphic.getPipeline().update( graphic );
}
}
graphic.process = true;
}
#endif

View File

@ -14,6 +14,7 @@ namespace {
int endian = 0;
namespace funs {
size_t read( void* destination, size_t size, size_t nmemb, void* userdata ) {
//UF_MSG_DEBUG( size * nmemb );
uf::Audio::Metadata& metadata = *((uf::Audio::Metadata*) userdata);
std::ifstream& file = *metadata.stream.file;
@ -54,6 +55,7 @@ namespace {
return length;
}
int seek( void* userdata, ogg_int64_t to, int type ) {
//UF_MSG_DEBUG(type << " " << to);
uf::Audio::Metadata& metadata = *((uf::Audio::Metadata*) userdata);
switch ( type ) {
case SEEK_CUR: metadata.stream.consumed += to; break; // increment
@ -73,6 +75,7 @@ namespace {
return 0;
}
int close( void* userdata ) {
//UF_MSG_DEBUG( userdata );
uf::Audio::Metadata& metadata = *((uf::Audio::Metadata*) userdata);
if ( !metadata.stream.file ) return 0;
@ -83,6 +86,7 @@ namespace {
return 0;
}
long tell( void* userdata ) {
//UF_MSG_DEBUG( userdata );
uf::Audio::Metadata& metadata = *((uf::Audio::Metadata*) userdata);
return metadata.stream.consumed;
}
@ -194,10 +198,13 @@ void ext::vorbis::stream( uf::Audio::Metadata& metadata ) {
else if ( metadata.info.channels == 2 && metadata.info.bitDepth == 8 ) metadata.info.format = AL_FORMAT_STEREO8;
else if ( metadata.info.channels == 2 && metadata.info.bitDepth == 16 ) metadata.info.format = AL_FORMAT_STEREO16;
else {
UF_MSG_ERROR("Vorbis: unrecognized OGG format: " << metadata.info.channels << " channels, " << metadata.info.bitDepth << " bps");
UF_MSG_ERROR("Vorbis: unrecognized OGG format: " << (int) metadata.info.channels << " channels, " << (int) metadata.info.bitDepth << " bps");
return;
}
// UF_MSG_DEBUG( "filename\tchannels\tbitDepth\tfrequency\tduration\tchannels" );
// UF_MSG_DEBUG( metadata.filename << "\t" << (int)metadata.info.channels << "\t" << (int)metadata.info.bitDepth << "\t" << (int)metadata.info.frequency << "\t" << metadata.info.duration << "\t" << (int) metadata.info.channels );
// fill and queue initial buffers
char buffer[uf::audio::bufferSize];
uint8_t queuedBuffers = 0;
@ -230,8 +237,9 @@ void ext::vorbis::stream( uf::Audio::Metadata& metadata ) {
}
read += result;
}
if ( read == 0 ) {
// UF_MSG_WARNING("Vorbis: consumed file stream before buffers are filled: " << (int) queuedBuffers << " " << metadata.filename);
// UF_MSG_WARNING("Vorbis: consumed file stream before buffers are filled: " << (int) queuedBuffers << " " << metadata.filename);
// if ( metadata.settings.loopMode == 0 ) metadata.settings.loopMode = 1;
// if ( metadata.settings.loop ) metadata.al.source.set( AL_LOOPING, AL_TRUE );
break;
@ -241,7 +249,7 @@ void ext::vorbis::stream( uf::Audio::Metadata& metadata ) {
AL_CHECK_RESULT(alSourceQueueBuffers(metadata.al.source.getIndex(), queuedBuffers, &metadata.al.buffer.getIndex()));
// switch to soft looping
if ( queuedBuffers >= metadata.settings.buffers ) {
// UF_MSG_WARNING("Vorbis: file not completely consumed from initial buffer filled, yet looping is enabled. Soft looping...: " << metadata.filename );
// UF_MSG_WARNING("Vorbis: file not completely consumed from initial buffer filled, yet looping is enabled. Soft looping...: " << metadata.filename );
metadata.settings.loopMode = 1;
metadata.al.source.set( AL_LOOPING, AL_FALSE );
}
@ -256,11 +264,11 @@ void ext::vorbis::update( uf::Audio::Metadata& metadata ) {
metadata.al.source.get( AL_SOURCE_STATE, state );
if ( state != AL_PLAYING ) {
if ( !metadata.settings.loop && metadata.stream.consumed >= metadata.info.size ) {
// UF_MSG_INFO("Vorbis stream finished: " << metadata.filename);
// UF_MSG_INFO("Vorbis stream finished: " << metadata.filename);
return;
}
// stream stalled, restart it
// UF_MSG_INFO("Vorbis stream stalled: " << metadata.filename);
// UF_MSG_INFO("Vorbis stream stalled: " << metadata.filename);
metadata.al.source.play();
}
@ -325,7 +333,7 @@ void ext::vorbis::update( uf::Audio::Metadata& metadata ) {
if ( metadata.settings.loopMode == 1 ) metadata.al.source.set( AL_LOOPING, AL_TRUE );
}
void ext::vorbis::close( uf::Audio::Metadata& metadata ) {
// UF_MSG_INFO("Vorbis " << ( metadata.settings.streamed ? "stream" : "load" ) << " closed: " << metadata.filename);
// UF_MSG_INFO("Vorbis " << ( metadata.settings.streamed ? "stream" : "load" ) << " closed: " << metadata.filename);
if ( metadata.stream.handle ) {
ov_clear((OggVorbis_File*) metadata.stream.handle);
delete (OggVorbis_File*) metadata.stream.handle;

View File

@ -12,6 +12,8 @@
#include <uf/utils/serialize/serializer.h>
#define UF_MSG_VALIDATION(X) if ( ext::vulkan::settings::validation ) UF_MSG("VULKAN", X);
namespace {
#if UF_USE_OPENVR
void VRInstanceExtensions( uf::stl::vector<uf::stl::string>& requested ) {
@ -23,7 +25,6 @@ namespace {
vr::VRCompositor()->GetVulkanInstanceExtensionsRequired( pExtensionStr, nBufferSize );
uf::stl::vector<uf::stl::string> extensions = uf::string::split( pExtensionStr, " " );
for ( auto& str : extensions ) {
// uf::iostream << str << "\n";
requested.push_back(str);
}
// requested.insert( requested.end(), extensions.begin(), extensions.end() );
@ -55,9 +56,7 @@ namespace {
supportedExtensions.push_back( extensionName );
break;
}
if ( !found ) {
uf::iostream << "Vulkan missing requested extension: " << requestedExtension << "\n";
}
if ( !found ) UF_MSG_ERROR("Vulkan missing requested extension: " << requestedExtension);
}
}
@ -68,8 +67,8 @@ namespace {
if ( feature == #NAME ) {\
if ( device.features.NAME == VK_TRUE ) {\
device.enabledFeatures.NAME = true;\
if ( ext::vulkan::settings::validation ) uf::iostream << "Enabled feature: " << feature << "\n";\
} else if ( ext::vulkan::settings::validation ) uf::iostream << "Failed to enable feature: " << feature << "\n";\
UF_MSG_VALIDATION("Enabled feature: " << feature);\
} else UF_MSG_VALIDATION("Failed to enable feature: " << feature);\
}
for ( auto& feature : ext::vulkan::settings::requestedDeviceFeatures ) {
@ -135,8 +134,8 @@ namespace {
if ( feature == #NAME ) {\
if ( device.features2.NAME == VK_TRUE ) {\
device.enabledFeatures2.NAME = true;\
if ( ext::vulkan::settings::validation ) uf::iostream << "Enabled feature: " << feature << "\n";\
} else if ( ext::vulkan::settings::validation ) uf::iostream << "Failed to enable feature: " << feature << "\n";\
UF_MSG_VALIDATION("Enabled feature: " << feature);\
} else UF_MSG_VALIDATION("Failed to enable feature: " << feature);\
}
#undef CHECK_FEATURE2
}
@ -546,8 +545,7 @@ void ext::vulkan::Device::initialize() {
{
uf::stl::vector<const char*> instanceExtensions;
for ( auto& s : supportedExtensions.instance ) {
if ( ext::vulkan::settings::validation )
uf::iostream << "Enabled instance extension: " << s << "\n";
UF_MSG_VALIDATION("Enabled instance extension: " << s);
instanceExtensions.push_back( s.c_str() );
}
@ -669,8 +667,7 @@ void ext::vulkan::Device::initialize() {
#endif
{
// Allocate enough ExtensionProperties to support all extensions being enabled
if ( ext::vulkan::settings::validation )
for ( auto ext : requestedExtensions ) uf::iostream << "Requested device extension: " << ext << "\n";
for ( auto ext : requestedExtensions ) UF_MSG_VALIDATION("Requested device extension: " << ext);
uint32_t extensionsCount = 0;
uint32_t enabledExtensionsCount = 0;
@ -685,7 +682,7 @@ void ext::vulkan::Device::initialize() {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
for ( auto& s : supportedExtensions.device ) {
if ( ext::vulkan::settings::validation ) uf::iostream << "Enabled device extension: " << s << "\n";
UF_MSG_VALIDATION("Enabled device extension: " << s);
deviceExtensions.push_back( s.c_str() );
}
@ -762,6 +759,7 @@ void ext::vulkan::Device::initialize() {
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{};
VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures{};
VkPhysicalDeviceShaderDrawParametersFeatures shaderDrawParametersFeatures{};
{
deviceCreateInfo.pEnabledFeatures = nullptr;
deviceCreateInfo.pNext = &physicalDeviceFeatures2;
@ -769,7 +767,7 @@ void ext::vulkan::Device::initialize() {
{
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physicalDeviceFeatures2.features = enabledFeatures;
physicalDeviceFeatures2.pNext = &descriptorIndexingFeatures;
physicalDeviceFeatures2.pNext = &descriptorIndexingFeatures;
}
{
descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
@ -777,6 +775,11 @@ void ext::vulkan::Device::initialize() {
descriptorIndexingFeatures.shaderStorageImageArrayNonUniformIndexing = VK_TRUE;
descriptorIndexingFeatures.runtimeDescriptorArray = VK_TRUE;
descriptorIndexingFeatures.descriptorBindingVariableDescriptorCount = VK_TRUE;
descriptorIndexingFeatures.pNext = &shaderDrawParametersFeatures;
}
{
shaderDrawParametersFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES;
shaderDrawParametersFeatures.shaderDrawParameters = VK_TRUE;
}
if ( vkCreateDevice( this->physicalDevice, &deviceCreateInfo, nullptr, &this->logicalDevice) != VK_SUCCESS ) {
@ -789,7 +792,7 @@ void ext::vulkan::Device::initialize() {
}
{
ext::json::Value payload = retrieveDeviceFeatures( *this );
if ( ext::vulkan::settings::validation ) uf::iostream << payload.dump() << "\n";
UF_MSG_VALIDATION(payload.dump());
uf::hooks.call("vulkan:Device.FeaturesEnabled", payload);
}
}
@ -917,6 +920,7 @@ void ext::vulkan::Device::initialize() {
}
// setup allocator
{
/*
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_2;
allocatorInfo.physicalDevice = physicalDevice;
@ -924,6 +928,19 @@ void ext::vulkan::Device::initialize() {
allocatorInfo.device = logicalDevice;
allocatorInfo.frameInUseCount = 1;
vmaCreateAllocator(&allocatorInfo, &allocator);
*/
VmaVulkanFunctions vulkanFunctions = {};
vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_2;
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.instance = instance;
allocatorInfo.device = logicalDevice;
allocatorInfo.pVulkanFunctions = &vulkanFunctions;
vmaCreateAllocator(&allocatorInfo, &allocator);
}
}

View File

@ -40,6 +40,9 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
if ( settings::experimental::bloom ) settings::experimental::deferredAliasOutputToSwapchain = false;
auto HDR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
auto SDR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
ext::vulkan::RenderMode::initialize( device );
renderTarget.device = &device;
renderTarget.views = metadata.eyes;
@ -76,7 +79,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
});
} else {
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::experimental::hdr ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM,
/*.format = */ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */blend,
@ -91,21 +94,21 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.samples = */msaa,
});
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ blend,
@ -139,7 +142,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
} else {
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ blend,

View File

@ -22,10 +22,19 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
auto& name = graph.meshes[index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
UF_ASSERT( !mesh.isInterleaved() );
/*
if ( mesh.isInterleaved() ) {
sources.emplace_back(mesh.convert()).updateDescriptor();
} else {
sources.emplace_back(mesh).updateDescriptor();
}
*/
if ( mesh.isInterleaved() ) {
UF_EXCEPTION("unwrapping interleaved mesh is not supported");
}
sources.emplace_back(mesh).updateDescriptor();
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Attribute positionAttribute;
@ -102,10 +111,10 @@ 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.bruteForce = false;
// packOptions.resolution = resolution;
// packOptions.texelsPerUnit = 64.0f;
packOptions.blockAlign = true;
@ -162,21 +171,29 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
auto srcAttribute = source.remapVertexAttribute( source.vertex.attributes[k], entry.command );
auto dstAttribute = mesh.remapVertexAttribute( mesh.vertex.attributes[k], entry.command );
// auto srcAttribute = source.remapVertexAttribute( source.vertex.attributes[k], entry.command );
// auto dstAttribute = mesh.remapVertexAttribute( mesh.vertex.attributes[k], entry.command );
auto srcInput = source.remapVertexInput( entry.command );
auto dstInput = mesh.remapVertexInput( entry.command );
auto srcAttribute = source.vertex.attributes[k];
auto dstAttribute = mesh.vertex.attributes[k];
if ( dstAttribute.descriptor.name == "st" ) {
pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j);
pod::Vector2f& st = *(pod::Vector2f*) ( dstAttribute.pointer + dstAttribute.stride * (j + dstInput.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
} else {
memcpy( dstAttribute.pointer + dstAttribute.stride * j, srcAttribute.pointer + srcAttribute.stride * ref, srcAttribute.stride );
memcpy( dstAttribute.pointer + dstAttribute.stride * (j + dstInput.first), srcAttribute.pointer + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride );
}
}
}
// indices
if ( mesh.index.count ) {
uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.command );
uint8_t* pointer = (uint8_t*) indexAttribute.pointer;
uf::Mesh::Input indexInput = mesh.remapIndexInput( entry.command );
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
// uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.command );
uint8_t* pointer = (uint8_t*) indexAttribute.pointer + indexAttribute.stride * indexInput.first;
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
switch ( mesh.index.size ) {
case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break;

View File

@ -1413,18 +1413,38 @@ void UF_API_CALL spec::win32::Window::grabMouse(bool state) {
pod::Vector2ui UF_API_CALL spec::win32::Window::getResolution() {
return { GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) };
}
void UF_API_CALL spec::win32::Window::switchToFullscreen( bool borderless ) {
void UF_API_CALL spec::win32::Window::toggleFullscreen( bool borderless ) {
static pod::Vector2ui lastSize = this->getSize();
static LONG lastStyle;
static LONG lastExStyle;
if ( fullscreenWindow == (void*) this ) {
fullscreenWindow = NULL;
SetWindowLong(this->m_handle, GWL_STYLE, lastStyle);
SetWindowLong(this->m_handle, GWL_EXSTYLE, lastExStyle);
this->setSize( lastSize );
this->centerWindow();
return;
}
lastSize = this->getSize();
lastStyle = GetWindowLong(this->m_handle, GWL_STYLE);
lastExStyle = GetWindowLong(this->m_handle, GWL_EXSTYLE);
if ( borderless ) {
SetWindowLong(this->m_handle, GWL_STYLE, WS_POPUP );
// SetWindowLong(this->m_handle, GWL_EXSTYLE, 0);
// SetWindowPos(this->m_handle, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
SetWindowPos(this->m_handle, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
ShowWindow(this->m_handle, SW_SHOW);
return;
}
SetWindowLong(this->m_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
SetWindowLong(this->m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
SetWindowPos(this->m_handle, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
ShowWindow(this->m_handle, SW_SHOW);
fullscreenWindow = (void*) this;
}

View File

@ -1,8 +1,135 @@
#include <uf/utils/mesh/grid.h>
namespace {
inline bool isInside( const pod::Vector3f& p, const pod::Vector3f& min, const pod::Vector3f& max ) {
// return ( min.x <= p.x && p.x <= max.x && min.y <= p.y && p.y <= max.y && min.z <= p.z && p.z <= max.z );
return (p.x <= max.x && p.x >= min.x) && (p.y <= max.y && p.y >= min.y) && (p.z <= max.z && p.z >= min.z);
}
}
uf::stl::vector<uf::meshgrid::Node> UF_API uf::meshgrid::partition( uf::Mesh& mesh, int divisions ) {
struct {
pod::Vector3f min = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
pod::Vector3f max = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
pod::Vector3f center = {};
pod::Vector3f corner = {};
pod::Vector3f size = {};
pod::Vector3f piece = {};
} extents;
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Input indexInput = mesh.index;
uf::Mesh::Attribute vertexAttribute = mesh.vertex.attributes.front();
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "position" ) { vertexAttribute = attribute; break; }
UF_ASSERT( vertexAttribute.descriptor.name == "position" );
for ( size_t i = 0; i < mesh.vertex.count; ++i ) {
pod::Vector3f& position = *(pod::Vector3f*) (vertexAttribute.pointer + vertexAttribute.stride * (vertexInput.first + i));
extents.min = uf::vector::min( position, extents.min );
extents.max = uf::vector::max( position, extents.max );
}
constexpr float epsilon = std::numeric_limits<float>::epsilon();
extents.min -= pod::Vector3f{ epsilon, epsilon, epsilon }; // dilate
extents.max += pod::Vector3f{ epsilon, epsilon, epsilon }; // dilate
extents.size = uf::vector::abs(extents.max - extents.min);
extents.piece = extents.size / divisions;
extents.center = (extents.max + extents.min) * 0.5f;
extents.corner = extents.size * 0.5f;
uf::stl::vector<uf::meshgrid::Node> nodes;
nodes.reserve( divisions * divisions * divisions );
for ( int z = 0; z < divisions; ++z ) {
for ( int y = 0; y < divisions; ++y ) {
for ( int x = 0; x < divisions; ++x ) {
nodes.emplace_back(uf::meshgrid::Node{
.extents = {
.min = extents.min + extents.piece * pod::Vector3f{ x, y, z },
.max = extents.min + extents.piece * pod::Vector3f{ x+1, y+1, z+1 },
},
.id = pod::Vector3ui{ x, y, z },
});
}
}
}
for ( size_t i = 0; i < indexInput.count; i+=3 ) {
size_t indexA = 0;
size_t indexB = 0;
size_t indexC = 0;
uint8_t* indexPointerA = (uint8_t*) (indexAttribute.pointer + indexAttribute.stride * (indexInput.first + i + 0));
uint8_t* indexPointerB = (uint8_t*) (indexAttribute.pointer + indexAttribute.stride * (indexInput.first + i + 1));
uint8_t* indexPointerC = (uint8_t*) (indexAttribute.pointer + indexAttribute.stride * (indexInput.first + i + 2));
switch ( indexInput.size ) {
case sizeof(uint8_t): {
indexA = *( uint8_t*) indexPointerA;
indexB = *( uint8_t*) indexPointerB;
indexC = *( uint8_t*) indexPointerC;
} break;
case sizeof(uint16_t): {
indexA = *(uint16_t*) indexPointerA;
indexB = *(uint16_t*) indexPointerB;
indexC = *(uint16_t*) indexPointerC;
} break;
case sizeof(uint32_t): {
indexA = *(uint32_t*) indexPointerA;
indexB = *(uint32_t*) indexPointerB;
indexC = *(uint32_t*) indexPointerC;
} break;
}
pod::Vector3f& positionA = *(pod::Vector3f*) (vertexAttribute.pointer + vertexAttribute.stride * (vertexInput.first + indexA));
pod::Vector3f& positionB = *(pod::Vector3f*) (vertexAttribute.pointer + vertexAttribute.stride * (vertexInput.first + indexB));
pod::Vector3f& positionC = *(pod::Vector3f*) (vertexAttribute.pointer + vertexAttribute.stride * (vertexInput.first + indexC));
for ( auto& node : nodes ) {
// if ( isInside( positionA, node.extents.min, node.extents.max ) || isInside( positionB, node.extents.min, node.extents.max ) || isInside( positionC, node.extents.min, node.extents.max ) ) {
if ( isInside( (positionA + positionB + positionC) / 3.0f, node.extents.min, node.extents.max ) ) {
node.indices.emplace_back( indexA );
node.indices.emplace_back( indexB );
node.indices.emplace_back( indexC );
}
}
}
UF_MSG_DEBUG( "== == == ==");
float total = 0.0f;
for ( auto& node : nodes ) {
float percentage = 100.8f * node.indices.size() / indexInput.count;
total += percentage;
UF_MSG_DEBUG(
"[" << node.id.x << "," << node.id.y << "," << node.id.z << "] "
"[" << percentage << "%|" << total << "%] "
"Min: " << uf::vector::toString( node.extents.min ) << " | "
"Max: " << uf::vector::toString( node.extents.max )
);
}
UF_MSG_DEBUG( "== == == ==");
UF_MSG_DEBUG( "Min: " << uf::vector::toString( extents.min ) );
UF_MSG_DEBUG( "Max: " << uf::vector::toString( extents.max ) );
UF_MSG_DEBUG( "Center: " << uf::vector::toString( extents.center ) );
UF_MSG_DEBUG( "Corner: " << uf::vector::toString( extents.corner ) );
UF_MSG_DEBUG( "Size: " << uf::vector::toString( extents.size ) );
UF_MSG_DEBUG( "Piece: " << uf::vector::toString( extents.piece ) );
UF_MSG_DEBUG( "== == == ==");
return nodes;
}
#if 0
#include <uf/utils/memory/pool.h>
#include <uf/utils/mesh/grid.h>
#include <uf/utils/math/collision/mesh.h>
#include <uf/utils/math/collision/boundingbox.h>
#if 0
uf::MeshGrid::~MeshGrid() {
this->destroy();
}

View File

@ -47,7 +47,12 @@ UF_VERTEX_DESCRIPTOR(pod::Vertex_3F,
UF_VERTEX_DESCRIPTION(pod::Vertex_3F, R32G32B32_SFLOAT, position)
)
bool uf::Mesh::defaultInterleaved = false;
#if UF_USE_OPENGL
bool uf::Mesh::defaultInterleaved = true;
#else
bool uf::Mesh::defaultInterleaved = false;
#endif
void uf::Mesh::initialize() {}
void uf::Mesh::destroy() {
_destroy(vertex);
@ -164,37 +169,17 @@ uf::Mesh uf::Mesh::expand( bool interleaved ) {
return res;
}
uf::Mesh::Input uf::Mesh::remapInput( const uf::Mesh::Input& input, size_t i ) const {
uf::Mesh::Input res = input;
UF_ASSERT( &input == &vertex || &input == &index );
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = &input == &vertex ? drawCommand.vertexID : drawCommand.indexID;
res.count = &input == &vertex ? drawCommand.vertices : drawCommand.indices;
return res;
void uf::Mesh::eraseAttribute( uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute ) {
for ( size_t i = 0; i < input.attributes.size(); ++i ) if ( input.attributes[i].descriptor == attribute.descriptor ) return eraseAttribute( input, i );
}
uf::Mesh::Input uf::Mesh::remapVertexInput( size_t i ) const {
uf::Mesh::Input res = vertex;
UF_ASSERT( i < indirect.count );
void uf::Mesh::eraseAttribute( uf::Mesh::Input& input, size_t i ) {
UF_ASSERT( !isInterleaved( input ) ); // can't be assed to de-interleave, erase, and then interleave again
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = drawCommand.vertexID;
res.count = drawCommand.vertices;
return res;
auto attribute = input.attributes[i];
buffers[attribute.buffer].clear();
}
uf::Mesh::Input uf::Mesh::remapIndexInput( size_t i ) const {
uf::Mesh::Input res = index;
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = drawCommand.indexID;
res.count = drawCommand.indices;
return res;
}
void uf::Mesh::generateIndirect() {
if ( index.count == 0 ) generateIndices();
@ -209,7 +194,7 @@ void uf::Mesh::generateIndirect() {
.instanceID = 0,
// .materialID = 0,
// .objectID = 0,
// .vertices = vertex.count,
.vertices = vertex.count,
});
}
@ -219,6 +204,7 @@ void uf::Mesh::generateIndirect() {
insertIndirects( commands );
}
bool uf::Mesh::isInterleaved() const { return isInterleaved( vertex.interleaved ); }
bool uf::Mesh::isInterleaved( const uf::Mesh::Input& input ) const { return isInterleaved( input.interleaved ); }
bool uf::Mesh::isInterleaved( size_t i ) const { return 0 <= i && i < buffers.size(); }
uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, size_t i ) {
return getBuffer( input, input.attributes[i] );
@ -232,13 +218,13 @@ const uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, siz
const uf::Mesh::buffer_t& uf::Mesh::getBuffer( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute ) const {
return buffers[isInterleaved(input.interleaved) ? input.interleaved : attribute.buffer];
}
#define PRINT_HEADER(input) "Count: " << input.count << " | First: " << input.first << " | Size: " << input.size << " | Offset: " << input.offset << " | " << (isInterleaved(input.interleaved) ? "interleaved" : "deinterleaved") << "\n"
void uf::Mesh::print( bool full ) const {
std::cout << "Buffers: " << buffers.size() << "\n" << printVertices(full) << printIndices(full) << printInstances(full) << printIndirects() << std::endl;
}
#define PRINT_HEADER(input) "Count: " << input.count << " | First: " << input.first << " | Size: " << input.size << " | Offset: " << input.offset << " | " << (isInterleaved(input.interleaved) ? "interleaved" : "deinterleaved") << "\n"
std::string uf::Mesh::printVertices( bool full ) const {
std::stringstream str;
str << "Vertices: " << PRINT_HEADER( vertex );
@ -306,6 +292,38 @@ std::string uf::Mesh::printIndirects( bool full ) const {
}
return str.str();
}
uf::Mesh::Input uf::Mesh::remapInput( const uf::Mesh::Input& input, size_t i ) const {
uf::Mesh::Input res = input;
UF_ASSERT( &input == &vertex || &input == &index );
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = &input == &vertex ? drawCommand.vertexID : drawCommand.indexID;
res.count = &input == &vertex ? drawCommand.vertices : drawCommand.indices;
return res;
}
uf::Mesh::Input uf::Mesh::remapVertexInput( size_t i ) const {
uf::Mesh::Input res = vertex;
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = drawCommand.vertexID;
res.count = drawCommand.vertices;
return res;
}
uf::Mesh::Input uf::Mesh::remapIndexInput( size_t i ) const {
uf::Mesh::Input res = index;
UF_ASSERT( i < indirect.count );
const auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
res.first = drawCommand.indexID;
res.count = drawCommand.indices;
return res;
}
//
void uf::Mesh::_destroy( uf::Mesh::Input& input ) {
for ( auto& attribute : input.attributes ) {
@ -351,9 +369,11 @@ void uf::Mesh::_updateDescriptor( uf::Mesh::Input& input ) {
}
}
uf::Mesh::Attribute uf::Mesh::_remapAttribute( const uf::Mesh::Input& input, const uf::Mesh::Attribute& attribute, size_t i ) const {
uf::Mesh::Attribute res = attribute;
UF_ASSERT( i < indirect.count );
UF_ASSERT( &input == &vertex || &input == &index );
UF_MSG_WARNING( "deprecated, please use remapInput" );
uf::Mesh::Attribute res = attribute;
auto& drawCommand = ((const pod::DrawCommand*) getBuffer(indirect).data())[i];
if ( &input == &vertex ) {

View File

@ -115,9 +115,9 @@ bool UF_API_CALL uf::Window::hasFocus() const {
pod::Vector2ui UF_API_CALL uf::Window::getResolution() {
return uf::Window::window_t::getResolution();
}
void UF_API_CALL uf::Window::switchToFullscreen( bool borderless ) {
void UF_API_CALL uf::Window::toggleFullscreen( bool borderless ) {
if ( !this->m_window ) return;
this->m_window->switchToFullscreen( borderless );
this->m_window->toggleFullscreen( borderless );
}
// Update
void UF_API_CALL uf::Window::bufferInputs() {

View File

@ -179,6 +179,8 @@ uf::stl::vector<pod::GlyphBox> ext::Gui::generateGlyphs( const uf::stl::string&
glyph.setSpread( metadataGlyph.spread );
#if UF_USE_VULKAN
if ( metadataGlyph.sdf ) glyph.useSdf(true);
#else
glyph.useSdf(false);
#endif
glyph.generate( ::glyphs.glyph, c, metadataGlyph.size );
}

View File

@ -311,20 +311,23 @@ void EXT_API ext::initialize() {
ext::bullet::defaultMaxCollisionAlgorithmPoolSize = configEngineBulletJson["pool size"]["max collision algorithm"].as( ext::bullet::defaultMaxCollisionAlgorithmPoolSize );
ext::bullet::defaultMaxPersistentManifoldPoolSize = configEngineBulletJson["pool size"]["max persistent manifold"].as( ext::bullet::defaultMaxPersistentManifoldPoolSize );
ext::bullet::debugDrawEnabled = configEngineBulletJson["debug draw"]["enabled"].as( ext::bullet::debugDrawEnabled );
ext::bullet::debugDrawRate = configEngineBulletJson["debug draw"]["rate"].as( ext::bullet::debugDrawRate );
ext::bullet::debugDrawLayer = configEngineBulletJson["debug draw"]["layer"].as( ext::bullet::debugDrawLayer );
ext::bullet::debugDrawLineWidth = configEngineBulletJson["debug draw"]["line width"].as( ext::bullet::debugDrawLineWidth );
ext::bullet::debugDraw::enabled = configEngineBulletJson["debug draw"]["enabled"].as( ext::bullet::debugDraw::enabled );
ext::bullet::debugDraw::rate = configEngineBulletJson["debug draw"]["rate"].as( ext::bullet::debugDraw::rate );
ext::bullet::debugDraw::layer = configEngineBulletJson["debug draw"]["layer"].as( ext::bullet::debugDraw::layer );
ext::bullet::debugDraw::lineWidth = configEngineBulletJson["debug draw"]["line width"].as( ext::bullet::debugDraw::lineWidth );
}
#elif UF_USE_REACTPHYSICS
{
auto& configEngineReactJson = ::json["engine"]["ext"]["reactphysics"];
ext::reactphysics::timescale = configEngineReactJson["timescale"].as( ext::reactphysics::timescale );
ext::reactphysics::debugDrawEnabled = configEngineReactJson["debug draw"]["enabled"].as( ext::reactphysics::debugDrawEnabled );
ext::reactphysics::debugDrawRate = configEngineReactJson["debug draw"]["rate"].as( ext::reactphysics::debugDrawRate );
ext::reactphysics::debugDrawLayer = configEngineReactJson["debug draw"]["layer"].as( ext::reactphysics::debugDrawLayer );
ext::reactphysics::debugDrawLineWidth = configEngineReactJson["debug draw"]["line width"].as( ext::reactphysics::debugDrawLineWidth );
ext::reactphysics::interpolate = configEngineReactJson["interpolate"].as( ext::reactphysics::interpolate );
ext::reactphysics::shared = configEngineReactJson["shared"].as( ext::reactphysics::shared );
ext::reactphysics::debugDraw::enabled = configEngineReactJson["debug draw"]["enabled"].as( ext::reactphysics::debugDraw::enabled );
ext::reactphysics::debugDraw::rate = configEngineReactJson["debug draw"]["rate"].as( ext::reactphysics::debugDraw::rate );
ext::reactphysics::debugDraw::layer = configEngineReactJson["debug draw"]["layer"].as( ext::reactphysics::debugDraw::layer );
ext::reactphysics::debugDraw::lineWidth = configEngineReactJson["debug draw"]["line width"].as( ext::reactphysics::debugDraw::lineWidth );
}
#endif