Commit for 2021.11.01 00-13-09.7z

This commit is contained in:
mrq 2021-11-01 00:13:00 -05:00
parent 386bf04eb9
commit e16f3d77d7
23 changed files with 916 additions and 260 deletions

View File

@ -46,7 +46,7 @@ LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS)
DEPS +=
ifneq (,$(findstring win64,$(ARCH)))
REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype ncurses curl luajit bullet meshoptimizer xatlas simd ctti # openvr draco discord
REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype ncurses curl luajit reactphysics meshoptimizer xatlas simd ctti # openvr draco discord bullet
FLAGS +=
DEPS += -lgdi32
else ifneq (,$(findstring dreamcast,$(ARCH)))
@ -153,6 +153,10 @@ ifneq (,$(findstring bullet,$(REQ_DEPS)))
INCS += -I./dep/bullet/
endif
endif
ifneq (,$(findstring reactphysics,$(REQ_DEPS)))
FLAGS += -DUF_USE_REACTPHYSICS
DEPS += -lreactphysics3d
endif
ifneq (,$(findstring simd,$(REQ_DEPS)))
FLAGS += -DUF_USE_SIMD -DUF_MATRIX_ALIGNED #-DUF_VECTOR_ALIGNED #-march=native

View File

@ -141,14 +141,22 @@
"json": "/json.lua"
}
},
"reactphysics": {
"timescale": 0.01666666666,
"debug draw": {
"enabled": false,
// "layer": "Gui",
"rate": 0.0125
}
},
"bullet": {
"iterations": 1,
"substeps": 12,
"substeps": 4,
"timescale": 1,
"multithreaded": false,
"pool size": {
"max collision algorithm": 1024,
"max persistent manifold": 1024
"max collision algorithm": 65535,
"max persistent manifold": 65535
},
"debug draw": {
"enabled": false,

View File

@ -32,7 +32,7 @@
},
"gravity": [ 0, -9.81, 0 ],
"inertia": [ 10, 10, 10 ],
"inertia": [ 0, 0, 0 ],
"type": "capsule",
"radius": 1,

View File

@ -2,6 +2,8 @@
"assets": ["./scripts/door.lua"],
"system": {
"physics": {
"mass": 0,
"inertia": [0, 0, 0],
"type": "bounding box",
"recenter": true
}

View File

@ -0,0 +1,11 @@
{
"assets": [],
"system": {
"physics": {
"mass": 0,
"inertia": [0, 0, 0],
"type": "bounding box",
"recenter": true
}
}
}

View File

@ -2,8 +2,8 @@
"import": "/scene.json",
"assets": [
"./audio/soundscape/ambience.ogg",
"./loading.json",
"./static.json"
"./loading.json"
// "./static.json"
],
"system": {
"hot reload": {

View File

@ -86,7 +86,7 @@ ent:bind( "tick", function(self)
end )
-- on use
ent:addHook( "entity:Use.%UID%", function( payload )
if state == 0 then
if state == 0 or state == 3 then
state = 1
playSound("default_move")
if payload.uid ~= nil then
@ -100,11 +100,8 @@ ent:addHook( "entity:Use.%UID%", function( payload )
polarity = -1
end
end
io.print(ent:name())
end
if state == 2 then
elseif state == 2 or state == 1 then
state = 3
playSound("default_move")
end
io.print( state, json.encode( payload ) )
end )

View File

@ -13,16 +13,12 @@
"alpha mode": "BLEND",
"tags": {
"worldspawn": { "physics": { "type": "mesh", "static": true } },
"worldspawn_sh2": { "physics": { "type": "mesh", "static": true } },
// "worldspawn_sh2": { "physics": { "type": "mesh", "static": true } },
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },
"func_door_rotating_5409": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5487": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
"func_door_rotating_5495": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
"func_door_rotating_5568": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5568": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5576": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5584": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5656": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } },
"func_door_rotating_5664": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5689": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
@ -31,7 +27,69 @@
"func_physbox_5212": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_physbox_5548": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_physbox_5931": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }
"func_physbox_5931": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5568": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5576": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_door_rotating_5584": { "action": "load", "payload": { "import": "./door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } },
"func_physbox_5212": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_5548": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_5931": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5839": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5848": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5857": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5864": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5872": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5879": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5886": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5893": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5905": { "action": "load", "payload": { "import": "./prop.json" } },
"func_physbox_multiplayer_5913": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5563": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5564": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5687": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5719": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5721": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5722": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5815": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5816": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5817": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5818": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5819": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5820": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_multiplayer_5821": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5227": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5373": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5374": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5375": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5545": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5546": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5565": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5566": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5591": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5675": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5680": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5681": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5682": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5683": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5684": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5685": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5696": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5707": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5723": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5749": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5750": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5760": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5764": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5787": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5807": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5808": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5809": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5810": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5814": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5822": { "action": "load", "payload": { "import": "./prop.json" } },
"prop_physics_override_5824": { "action": "load", "payload": { "import": "./prop.json" } }
}
}
}

View File

@ -12,28 +12,39 @@
#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h"
#endif
namespace pod {
struct UF_API Bullet {
struct UF_API Physics {
size_t uid = 0;
uf::Object* pointer = NULL;
pod::Transform<> transform;
pod::Transform<> previous;
bool shared = false; // share control of the transform both in-engine and bullet, set to true if you're directly modifying the transform
#if UF_USE_BULLET
btRigidBody* body = NULL;
btCollisionShape* shape = NULL;
#else
void* body = NULL;
void* shape = NULL;
#endif
struct {
pod::Vector3 velocity;
pod::Vector3 acceleration;
} linear;
struct {
pod::Quaternion<> velocity;
pod::Quaternion<> acceleration;
} rotational;
struct {
uint32_t flags = 0;
float mass = 0.0f;
float friction = 0.8f;
float restitution = 0.0f;
pod::Vector3f inertia = {};
pod::Vector3f gravity = {};
pod::Vector3f inertia = {0, 0, 0};
pod::Vector3f gravity = {0, 0, 0};
} stats;
};
typedef Physics PhysicsState;
}
#if UF_USE_BULLET
namespace ext {
@ -48,52 +59,43 @@ namespace ext {
extern UF_API bool debugDrawEnabled;
extern UF_API float debugDrawRate;
extern UF_API uf::stl::string debugDrawLayer;
extern UF_API float debugDrawLineWidth;
void UF_API initialize();
void UF_API tick( float = 0 );
void UF_API terminate();
// base collider creation
pod::Bullet& create( uf::Object& );
pod::PhysicsState& UF_API create( uf::Object& );
void destroy( uf::Object& );
void destroy( pod::Bullet& );
void UF_API destroy( uf::Object& );
void UF_API destroy( pod::PhysicsState& );
void UF_API attach( pod::Bullet& );
void UF_API detach( pod::Bullet& );
void UF_API attach( pod::PhysicsState& );
void UF_API detach( pod::PhysicsState& );
/*
pod::Bullet& create( uf::Object&, const void* verticesPointer, size_t verticesCount, size_t verticesStride, const void* indicesPointer, size_t indicesCount, size_t indicesStride, bool );
template<typename T, typename U>
pod::Bullet& create( uf::Object& o, const uf::Mesh_T<T,U>& m, bool b ) {
return create( o, m.vertices.data() + offsetof(T, position), m.vertices.size(), sizeof(T), m.indices.data(), m.indices.size(), sizeof(U), b );
}
*/
// collider for mesh (static or dynamic)
pod::Bullet& create( uf::Object&, const uf::Mesh&, bool );
pod::PhysicsState& create( uf::Object&, const uf::Mesh&, bool );
// collider for boundingbox
pod::Bullet& UF_API create( uf::Object&, const pod::Vector3f& );
uf::stl::vector<pod::Bullet>& UF_API create( uf::Object&, const uf::stl::vector<pod::Instance::Bounds>& );
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::Bullet& UF_API create( uf::Object&, float, float );
pod::PhysicsState& UF_API create( uf::Object&, float, float );
// synchronize engine transforms to bullet transforms
void UF_API syncToBullet();
void UF_API syncTo();
// synchronize bullet transforms to engine transforms
void UF_API syncFromBullet();
void UF_API syncFrom();
// apply impulse
void UF_API applyImpulse( pod::Bullet&, const pod::Vector3f& );
void UF_API applyImpulse( pod::PhysicsState&, const pod::Vector3f& );
// directly move a transform
void UF_API applyMovement( pod::Bullet&, const pod::Vector3f& );
void UF_API applyMovement( pod::PhysicsState&, const pod::Vector3f& );
// directly apply a velocity
void UF_API setVelocity( pod::Bullet&, const pod::Vector3f& );
void UF_API applyVelocity( pod::Bullet&, const pod::Vector3f& );
void UF_API setVelocity( pod::PhysicsState&, const pod::Vector3f& );
void UF_API applyVelocity( pod::PhysicsState&, const pod::Vector3f& );
// directly rotate a transform
void UF_API applyRotation( pod::Bullet&, const pod::Quaternion<>& );
void UF_API applyRotation( pod::Bullet&, const pod::Vector3f&, float );
// picks an appropriate movement option
// void UF_API move( pod::Bullet&, const pod::Vector3f&, bool = false );
void UF_API applyRotation( pod::PhysicsState&, const pod::Quaternion<>& );
void UF_API applyRotation( pod::PhysicsState&, const pod::Vector3f&, float );
// ray casting
float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& );
@ -101,7 +103,7 @@ namespace ext {
float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*& );
// allows noclip
void UF_API activateCollision( pod::Bullet&, bool = true );
void UF_API activateCollision( pod::PhysicsState&, bool = true );
// allows showing collision models
void UF_API debugDraw( uf::Object& );

View File

@ -0,0 +1,105 @@
#pragma once
#include <uf/config.h>
#include <uf/engine/object/object.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/mesh/mesh.h>
#include <uf/utils/math/collision.h>
#include <uf/engine/graph/graph.h>
#if UF_USE_REACTPHYSICS
#include <reactphysics3d/reactphysics3d.h>
namespace rp3d = reactphysics3d;
namespace pod {
struct UF_API Physics {
size_t uid = 0;
uf::Object* object = NULL;
bool shared = false; // share control of the transform both in-engine and bullet, set to true if you're directly modifying the transform
rp3d::RigidBody* body = NULL;
rp3d::CollisionShape* shape = NULL;
pod::Transform<> transform = {};
pod::Transform<> previous = {};
struct {
pod::Vector3 velocity;
pod::Vector3 acceleration;
} linear;
struct {
pod::Quaternion<> velocity;
pod::Quaternion<> acceleration;
} rotational;
struct {
uint32_t flags = 0;
float mass = 0.0f;
float friction = 0.8f;
float restitution = 0.0f;
pod::Vector3f inertia = {0, 0, 0};
pod::Vector3f gravity = {0, 0, 0};
} stats;
};
typedef Physics PhysicsState;
}
namespace ext {
namespace reactphysics {
void UF_API initialize();
void UF_API tick( float = 0 );
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;
// base collider creation
pod::PhysicsState& UF_API create( uf::Object& );
void UF_API destroy( uf::Object& );
void UF_API destroy( pod::PhysicsState& );
void UF_API attach( pod::PhysicsState& );
void UF_API detach( pod::PhysicsState& );
// collider for mesh (static or dynamic)
pod::PhysicsState& create( uf::Object&, const uf::Mesh&, bool );
// collider for boundingbox
pod::PhysicsState& UF_API create( uf::Object&, const pod::Vector3f& );
// 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();
// apply impulse
void UF_API applyImpulse( pod::PhysicsState&, const pod::Vector3f& );
// directly move a transform
void UF_API applyMovement( pod::PhysicsState&, const pod::Vector3f& );
// directly apply a velocity
void UF_API setVelocity( pod::PhysicsState&, const pod::Vector3f& );
void UF_API applyVelocity( pod::PhysicsState&, const pod::Vector3f& );
// directly rotate a transform
void UF_API applyRotation( pod::PhysicsState&, const pod::Quaternion<>& );
void UF_API applyRotation( pod::PhysicsState&, const pod::Vector3f&, float );
// ray casting
float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& );
float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, size_t& );
float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*& );
// allows noclip
void UF_API activateCollision( pod::PhysicsState&, bool = true );
// allows showing collision models
void UF_API debugDraw( uf::Object& );
}
}
#endif

View File

@ -4,22 +4,20 @@
#include <uf/utils/math/transform.h>
#include <uf/utils/time/time.h>
namespace pod {
struct UF_API Physics {
struct {
pod::Vector3 velocity;
pod::Vector3 acceleration;
} linear;
struct {
pod::Quaternion<> velocity;
pod::Quaternion<> acceleration;
} rotational;
pod::Transform<> previous;
};
}
#if UF_USE_BULLET
#include <uf/ext/bullet/bullet.h>
#elif UF_USE_REACTPHYSICS
#include <uf/ext/reactphysics/reactphysics.h>
#endif
namespace uf {
namespace physics {
#if UF_USE_BULLET
namespace impl = ext::bullet;
#elif UF_USE_REACTPHYSICS
namespace impl = ext::reactphysics;
#endif
typedef pod::Math::num_t num_t;
namespace time {
@ -29,7 +27,9 @@ namespace uf {
extern UF_API uf::physics::num_t delta;
extern UF_API uf::physics::num_t clamp;
}
void UF_API initialize();
void UF_API tick();
void UF_API terminate();
template<typename T> pod::Transform<T>& update( pod::Transform<T>& transform, pod::Physics& physics );
template<typename T> pod::Transform<T>& update( pod::Physics& physics, pod::Transform<T>& transform );
}

View File

@ -1,11 +1,11 @@
#include <uf/engine/graph/graph.h>
#include <uf/ext/bullet/bullet.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/mesh/grid.h>
#include <uf/utils/thread/thread.h>
#include <uf/utils/string/base64.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/camera/camera.h>
#include <uf/ext/xatlas/xatlas.h>

View File

@ -1,5 +1,4 @@
#include <uf/engine/graph/graph.h>
#include <uf/ext/bullet/bullet.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/mesh/grid.h>
@ -7,6 +6,7 @@
#include <uf/utils/string/base64.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/math/physics.h>
#include <uf/ext/xatlas/xatlas.h>
#if UF_ENV_DREAMCAST

View File

@ -1,5 +1,4 @@
#include <uf/engine/graph/graph.h>
#include <uf/ext/bullet/bullet.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/mesh/grid.h>
@ -7,6 +6,7 @@
#include <uf/utils/string/base64.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/math/physics.h>
#include <uf/ext/xatlas/xatlas.h>
#if UF_ENV_DREAMCAST
@ -694,17 +694,16 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
if ( ext::json::isObject( info ) ) {
uf::stl::string type = info["type"].as<uf::stl::string>();
#if UF_USE_BULLET
if ( type == "mesh" ) {
auto& collider = entity.getComponent<pod::Bullet>();
auto& collider = entity.getComponent<pod::PhysicsState>();
collider.stats.mass = info["mass"].as(collider.stats.mass);
collider.stats.friction = info["friction"].as(collider.stats.friction);
collider.stats.restitution = info["restitution"].as(collider.stats.restitution);
collider.stats.inertia = uf::vector::decode( info["inertia"], collider.stats.inertia );
collider.stats.gravity = uf::vector::decode( info["gravity"], collider.stats.gravity );
ext::bullet::create( entity.as<uf::Object>(), mesh, !info["static"].as<bool>(true) );
uf::physics::impl::create( entity.as<uf::Object>(), mesh, !info["static"].as<bool>(true) );
} else {
auto min = uf::matrix::multiply<float>( model, bounds.min, 1.0f );
auto max = uf::matrix::multiply<float>( model, bounds.max, 1.0f );
@ -715,7 +714,6 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
metadataJson["system"]["physics"]["center"] = uf::vector::encode( center );
metadataJson["system"]["physics"]["corner"] = uf::vector::encode( corner );
}
#endif
}
}
}

View File

@ -9,8 +9,8 @@
#include <uf/utils/camera/camera.h>
#include <uf/utils/mesh/mesh.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/math/physics.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/ext/bullet/bullet.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(uf::Object)
UF_BEHAVIOR_TRAITS_CPP(uf::ObjectBehavior, ticks = true, renders = false, multithread = false)
@ -114,9 +114,9 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
});
metadata.deserialize(self, metadataJson);
#if UF_USE_BULLET
if ( ext::json::isObject(metadataJson["system"]["physics"]) ) {
auto& collider = this->getComponent<pod::Bullet>();
auto& collider = this->getComponent<pod::PhysicsState>();
collider.stats.flags = metadataJson["system"]["physics"]["flags"].as(collider.stats.flags);
collider.stats.mass = metadataJson["system"]["physics"]["mass"].as(collider.stats.mass);
collider.stats.restitution = metadataJson["system"]["physics"]["restitution"].as(collider.stats.restitution);
collider.stats.friction = metadataJson["system"]["physics"]["friction"].as(collider.stats.friction);
@ -127,18 +127,16 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
pod::Vector3f center = uf::vector::decode( metadataJson["system"]["physics"]["center"], pod::Vector3f{} );
pod::Vector3f corner = uf::vector::decode( metadataJson["system"]["physics"]["corner"], pod::Vector3f{0.5, 0.5, 0.5} );
ext::bullet::create( *this, corner );
if ( metadataJson["system"]["physics"]["recenter"].as<bool>() ) collider.transform.position = center - transform.position;
if ( metadataJson["system"]["physics"]["recenter"].as<bool>() ) collider.transform.position = (center - transform.position) * 0.5f;
uf::physics::impl::create( *this, corner );
} else if ( metadataJson["system"]["physics"]["type"].as<uf::stl::string>() == "capsule" ) {
float radius = metadataJson["system"]["physics"]["radius"].as<float>();
float height = metadataJson["system"]["physics"]["height"].as<float>();
ext::bullet::create( *this, radius, height );
uf::physics::impl::create( *this, radius, height );
}
}
#endif
}
void uf::ObjectBehavior::destroy( uf::Object& self ) {
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
@ -221,8 +219,8 @@ void uf::ObjectBehavior::tick( uf::Object& self ) {
}
/*
if ( this->hasComponent<pod::Bullet>() && this->hasComponent<pod::Physics>() ) {
auto& collider = this->getComponent<pod::Bullet>();
if ( this->hasComponent<pod::PhysicsState>() && this->hasComponent<pod::Physics>() ) {
auto& collider = this->getComponent<pod::PhysicsState>();
auto& transform = this->getComponent<pod::Transform<>>();
auto& physics = this->getComponent<pod::Physics>();
UF_MSG_DEBUG( this->getName() << ": " << this->getUid() << " " << uf::vector::toString( physics.linear.velocity ) << " " << uf::vector::toString( transform.position ) );

View File

@ -1,5 +1,5 @@
#include <uf/ext/bullet/bullet.h>
#if UF_USE_BULLET
#include <uf/ext/bullet/bullet.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/renderer/renderer.h>
@ -80,6 +80,7 @@ size_t ext::bullet::defaultMaxPersistentManifoldPoolSize = 65535;
bool ext::bullet::debugDrawEnabled = false;
float ext::bullet::debugDrawRate = 1.0f;
uf::stl::string ext::bullet::debugDrawLayer = "";
float ext::bullet::debugDrawLineWidth = 1.0f;
namespace ext {
namespace bullet {
@ -143,12 +144,24 @@ void ext::bullet::initialize() {
#endif
}
void ext::bullet::tick( float delta ) { if ( delta == 0.0f ) delta = uf::physics::time::delta;
ext::bullet::syncToBullet();
ext::bullet::syncTo();
static float accumulator = 0;
static const float timeStep = 1.0f / 60.0f;
accumulator += uf::physics::time::delta;
while ( accumulator >= timeStep ) {
ext::bullet::dynamicsWorld->stepSimulation( delta, ext::bullet::substeps, timeStep );
accumulator -= timeStep;
}
/*
delta = delta * ext::bullet::timescale / ext::bullet::iterations;
for ( size_t i = 0; i < ext::bullet::iterations; ++i ) {
ext::bullet::dynamicsWorld->stepSimulation(delta, ext::bullet::substeps, delta / ext::bullet::substeps);
}
ext::bullet::syncFromBullet();
*/
ext::bullet::syncFrom();
TIMER(ext::bullet::debugDrawRate, ext::bullet::debugDrawEnabled && ) {
ext::bullet::dynamicsWorld->debugDrawWorld();
}
@ -174,8 +187,7 @@ void ext::bullet::terminate() {
if ( ext::bullet::collisionConfiguration ) delete ext::bullet::collisionConfiguration;
ext::bullet::collisionShapes.clear();
}
void ext::bullet::syncToBullet() {
auto& scene = uf::scene::getCurrentScene();
void ext::bullet::syncTo() {
// update bullet transforms
for ( int i = ext::bullet::dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; --i) {
btCollisionObject* obj = ext::bullet::dynamicsWorld->getCollisionObjectArray()[i];
@ -184,16 +196,15 @@ void ext::bullet::syncToBullet() {
if ( !body || !body->getMotionState() ) return;
uf::Object* entity = (uf::Object*) body->getUserPointer();
if ( !entity || !entity->isValid() || !entity->hasComponent<pod::Bullet>() ) continue;
if ( !entity || !entity->isValid() || !entity->hasComponent<pod::PhysicsState>() ) continue;
auto& collider = entity->getComponent<pod::Bullet>();
auto& collider = entity->getComponent<pod::PhysicsState>();
if ( !collider.shared ) continue;
auto& physics = entity->getComponent<pod::Physics>();
auto model = uf::transform::model( collider.transform );
btTransform t;
t = body->getWorldTransform();
btTransform t = body->getWorldTransform();
t.setFromOpenGLMatrix(&model[0]);
// t.setOrigin( btVector3( transform.position.x, transform.position.y, transform.position.z ) );
// t.setRotation( btQuaternion( transform.orientation.x, transform.orientation.y, transform.orientation.z, transform.orientation.w ) );
@ -203,20 +214,18 @@ void ext::bullet::syncToBullet() {
body->setLinearVelocity( btVector3( physics.linear.velocity.x, physics.linear.velocity.y, physics.linear.velocity.z ) );
}
}
void ext::bullet::syncFromBullet() {
auto& scene = uf::scene::getCurrentScene();
void ext::bullet::syncFrom() {
for ( int i = ext::bullet::dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; --i) {
btCollisionObject* obj = ext::bullet::dynamicsWorld->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if ( !body || !body->getMotionState() ) return;
btTransform t;
body->getMotionState()->getWorldTransform(t);
btTransform t = body->getWorldTransform();
// body->getMotionState()->getWorldTransform(t);
uf::Object* entity = (uf::Object*) body->getUserPointer();
if ( !entity || !entity->isValid() || !entity->hasComponent<pod::Bullet>() ) continue;
size_t uid = entity->getUid();
if ( !entity || !entity->isValid() || !entity->hasComponent<pod::PhysicsState>() ) continue;
auto& collider = entity->getComponent<pod::Bullet>();
auto& collider = entity->getComponent<pod::PhysicsState>();
auto& transform = entity->getComponent<pod::Transform<>>();
transform.position.x = t.getOrigin().getX();
@ -243,8 +252,8 @@ void ext::bullet::syncFromBullet() {
transform = uf::transform::reorient( transform );
}
}
pod::Bullet& ext::bullet::create( uf::Object& object ) {
auto& collider = object.getComponent<pod::Bullet>();
pod::PhysicsState& ext::bullet::create( uf::Object& object ) {
auto& collider = object.getComponent<pod::PhysicsState>();
collider.uid = object.getUid();
collider.pointer = &object;
@ -252,7 +261,7 @@ pod::Bullet& ext::bullet::create( uf::Object& object ) {
collider.shared = true;
return collider;
}
void ext::bullet::attach( pod::Bullet& collider ) {
void ext::bullet::attach( pod::PhysicsState& collider ) {
if ( !collider.shape ) return;
auto model = uf::transform::model( collider.transform );
@ -273,22 +282,26 @@ void ext::bullet::attach( pod::Bullet& collider ) {
collider.body->setFriction(collider.stats.friction);
collider.body->setGravity( btVector3( collider.stats.gravity.x, collider.stats.gravity.y, collider.stats.gravity.z ) );
if ( collider.stats.mass > 0 ) {
// collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
// collider.body->activate(true);
// collider.body->setActivationState(DISABLE_DEACTIVATION);
/*
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | collider.stats.flags);
if ( collider.stats.mass != 0.0f ) {
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | ~btCollisionObject::CF_STATIC_OBJECT);
} else {
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT);
}
collider.body->activate(true);
collider.body->setActivationState(DISABLE_DEACTIVATION);
*/
ext::bullet::dynamicsWorld->addRigidBody(collider.body);
ext::bullet::collisionShapes.push_back(collider.shape);
}
void ext::bullet::detach( pod::Bullet& collider ) {
void ext::bullet::detach( pod::PhysicsState& collider ) {
if ( !collider.body || !collider.shape ) return;
ext::bullet::dynamicsWorld->removeCollisionObject( collider.body );
}
pod::Bullet& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) {
pod::PhysicsState& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) {
btTriangleIndexVertexArray* bMesh = new btTriangleIndexVertexArray();
if ( mesh.index.count ) {
@ -342,6 +355,7 @@ pod::Bullet& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh, bool
auto& collider = ext::bullet::create( object );
collider.shape = new btBvhTriangleMeshShape( bMesh, true, true );
collider.stats.mass = 0;
ext::bullet::attach( collider );
auto& transform = object.getComponent<pod::Transform<>>();
@ -351,6 +365,7 @@ pod::Bullet& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh, bool
collider.body->setWorldTransform(t);
collider.body->setCenterOfMassTransform(t);
/*
btBvhTriangleMeshShape* triangleMeshShape = (btBvhTriangleMeshShape*) collider.shape;
btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
triangleInfoMap->m_edgeDistanceThreshold = 0.01f;
@ -359,58 +374,10 @@ pod::Bullet& ext::bullet::create( uf::Object& object, const uf::Mesh& mesh, bool
btGenerateInternalEdgeInfo( triangleMeshShape, triangleInfoMap );
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
}
return collider;
}
/*
pod::Bullet& ext::bullet::create( uf::Object& object, const void* verticesPointer, size_t verticesCount, size_t verticesStride, const void* indicesPointer, size_t indicesCount, size_t indicesStride, bool dynamic ) {
btTriangleIndexVertexArray* bMesh = new btTriangleIndexVertexArray();
if ( indicesCount ) {
PHY_ScalarType indexType = PHY_INTEGER;
PHY_ScalarType vertexType = PHY_FLOAT;
switch ( indicesStride ) {
case 1: indexType = PHY_UCHAR; break;
case 2: indexType = PHY_SHORT; break;
case 4: indexType = PHY_INTEGER; break;
}
const uint8_t* indicesBuffer = (const uint8_t*) indicesPointer;
const uint8_t* verticesBuffer = (const uint8_t*) verticesPointer;
btIndexedMesh iMesh;
iMesh.m_numTriangles = indicesCount / 3;
iMesh.m_triangleIndexBase = indicesBuffer;
iMesh.m_triangleIndexStride = 3 * indicesStride;
iMesh.m_numVertices = verticesCount;
iMesh.m_vertexBase = verticesBuffer;
iMesh.m_vertexStride = verticesStride;
iMesh.m_indexType = indexType;
iMesh.m_vertexType = vertexType;
bMesh->addIndexedMesh( iMesh, indexType );
} else UF_EXCEPTION("to-do: not require indices for meshes");
auto& collider = ext::bullet::create( object );
collider.shape = new btBvhTriangleMeshShape( bMesh, true, true );
ext::bullet::attach( collider );
auto& transform = object.getComponent<pod::Transform<>>();
auto model = uf::transform::model( collider.transform );
btTransform t = collider.body->getWorldTransform();
t.setFromOpenGLMatrix(&model[0]);
collider.body->setWorldTransform(t);
collider.body->setCenterOfMassTransform(t);
btBvhTriangleMeshShape* triangleMeshShape = (btBvhTriangleMeshShape*) collider.shape;
btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
triangleInfoMap->m_edgeDistanceThreshold = 0.01f;
triangleInfoMap->m_maxEdgeAngleThreshold = SIMD_HALF_PI*0.25;
if ( !false ) btGenerateInternalEdgeInfo( triangleMeshShape, triangleInfoMap );
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
return collider;
}
*/
pod::Bullet& ext::bullet::create( uf::Object& object, const pod::Vector3f& corner ) {
return collider;
}
pod::PhysicsState& ext::bullet::create( uf::Object& object, const pod::Vector3f& corner ) {
auto& collider = ext::bullet::create( object );
collider.shape = new btBoxShape(btVector3(corner.x, corner.y, corner.z));
ext::bullet::attach( collider );
@ -418,14 +385,14 @@ pod::Bullet& ext::bullet::create( uf::Object& object, const pod::Vector3f& corne
auto& transform = object.getComponent<pod::Transform<>>();
auto model = uf::transform::model( collider.transform );
collider.body->setContactProcessingThreshold(0.0);
collider.body->setAngularFactor(0.0);
collider.body->setCcdMotionThreshold(1e-7);
collider.body->setCcdSweptSphereRadius(0.25 * 0.2);
// collider.body->setContactProcessingThreshold(0.0);
// collider.body->setAngularFactor(0.0);
// collider.body->setCcdMotionThreshold(1e-7);
// collider.body->setCcdSweptSphereRadius(0.25 * 0.2);
return collider;
}
uf::stl::vector<pod::Bullet>& ext::bullet::create( uf::Object& object, const uf::stl::vector<pod::Instance::Bounds>& bounds ) {
auto& colliders = object.getComponent<uf::stl::vector<pod::Bullet>>();
uf::stl::vector<pod::PhysicsState>& ext::bullet::create( uf::Object& object, const uf::stl::vector<pod::Instance::Bounds>& bounds ) {
auto& colliders = object.getComponent<uf::stl::vector<pod::PhysicsState>>();
colliders.reserve(colliders.size() + bounds.size());
auto& transform = object.getComponent<pod::Transform<>>();
@ -446,15 +413,15 @@ uf::stl::vector<pod::Bullet>& ext::bullet::create( uf::Object& object, const uf:
collider.shape = new btBoxShape(btVector3(corner.x, corner.y, corner.z));
ext::bullet::attach( collider );
collider.body->setContactProcessingThreshold(0.0);
collider.body->setAngularFactor(0.0);
collider.body->setCcdMotionThreshold(1e-7);
collider.body->setCcdSweptSphereRadius(0.25 * 0.2);
// collider.body->setContactProcessingThreshold(0.0);
// collider.body->setAngularFactor(0.0);
// collider.body->setCcdMotionThreshold(1e-7);
// collider.body->setCcdSweptSphereRadius(0.25 * 0.2);
}
return colliders;
}
pod::Bullet& ext::bullet::create( uf::Object& object, float radius, float height ) {
pod::PhysicsState& ext::bullet::create( uf::Object& object, float radius, float height ) {
auto& collider = ext::bullet::create( object );
collider.shape = new btCapsuleShape(radius, height);
ext::bullet::attach( collider );
@ -470,7 +437,7 @@ pod::Bullet& ext::bullet::create( uf::Object& object, float radius, float height
return collider;
}
void UF_API ext::bullet::setVelocity( pod::Bullet& collider, const pod::Vector3f& v ) {
void UF_API ext::bullet::setVelocity( pod::PhysicsState& collider, const pod::Vector3f& v ) {
if ( !collider.body ) return;
collider.body->activate(true);
if ( collider.shared ) {
@ -480,24 +447,26 @@ void UF_API ext::bullet::setVelocity( pod::Bullet& collider, const pod::Vector3f
collider.body->setLinearVelocity( btVector3( v.x, v.y, v.z ) );
}
}
void UF_API ext::bullet::applyImpulse( pod::Bullet& collider, const pod::Vector3f& v ) {
void UF_API ext::bullet::applyImpulse( pod::PhysicsState& collider, const pod::Vector3f& v ) {
if ( !collider.body ) return;
collider.body->activate(true);
collider.body->applyCentralImpulse( btVector3( v.x, v.y, v.z ) /** uf::physics::time::delta*/ );
}
void UF_API ext::bullet::applyMovement( pod::Bullet& collider, const pod::Vector3f& v ) {
void UF_API ext::bullet::applyMovement( pod::PhysicsState& collider, const pod::Vector3f& v ) {
if ( !collider.body ) return;
btTransform transform;
collider.body->activate(true);
collider.body->getMotionState()->getWorldTransform(transform);
btTransform transform = collider.body->getWorldTransform();
// collider.body->getMotionState()->getWorldTransform(transform);
transform.setOrigin( transform.getOrigin() + btVector3( v.x, v.y, v.z ) * uf::physics::time::delta );
collider.body->getMotionState()->setWorldTransform(transform);
// collider.body->getMotionState()->setWorldTransform(transform);
collider.body->setWorldTransform(transform);
collider.body->setCenterOfMassTransform(transform);
}
void UF_API ext::bullet::applyVelocity( pod::Bullet& collider, const pod::Vector3f& v ) {
void UF_API ext::bullet::applyVelocity( pod::PhysicsState& collider, const pod::Vector3f& v ) {
if ( !collider.body ) return;
collider.body->activate(true);
@ -508,10 +477,10 @@ void UF_API ext::bullet::applyVelocity( pod::Bullet& collider, const pod::Vector
collider.body->setLinearVelocity( collider.body->getLinearVelocity() + btVector3( v.x, v.y, v.z ) );
}
}
void UF_API ext::bullet::applyRotation( pod::Bullet& collider, const pod::Vector3f& axis, float delta ) {
void UF_API ext::bullet::applyRotation( pod::PhysicsState& collider, const pod::Vector3f& axis, float delta ) {
ext::bullet::applyRotation( collider, uf::quaternion::axisAngle( axis, delta ) );
}
void UF_API ext::bullet::applyRotation( pod::Bullet& collider, const pod::Quaternion<>& q ) {
void UF_API ext::bullet::applyRotation( pod::PhysicsState& collider, const pod::Quaternion<>& q ) {
if ( !collider.body ) return;
collider.body->activate(true);
@ -521,8 +490,8 @@ void UF_API ext::bullet::applyRotation( pod::Bullet& collider, const pod::Quater
return;
}
btTransform transform;
collider.body->getMotionState()->getWorldTransform(transform);
btTransform transform = collider.body->getWorldTransform();
// collider.body->getMotionState()->getWorldTransform(transform);
pod::Quaternion<> orientation = uf::vector::normalize(uf::quaternion::multiply({
transform.getRotation().getX(),
@ -532,10 +501,11 @@ void UF_API ext::bullet::applyRotation( pod::Bullet& collider, const pod::Quater
}, q));
transform.setRotation( btQuaternion( orientation.x, orientation.y, orientation.z, orientation.w ) );
collider.body->getMotionState()->setWorldTransform(transform);
// collider.body->getMotionState()->setWorldTransform(transform);
collider.body->setWorldTransform(transform);
collider.body->setCenterOfMassTransform(transform);
}
void UF_API ext::bullet::activateCollision( pod::Bullet& collider, bool enabled ) {
void UF_API ext::bullet::activateCollision( pod::PhysicsState& collider, bool enabled ) {
if ( !collider.body ) return;
collider.body->activate(enabled);
}
@ -597,7 +567,7 @@ void UF_API ext::bullet::debugDraw( uf::Object& object ) {
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
graphic.descriptor.lineWidth = 8.0f;
graphic.descriptor.lineWidth = ext::bullet::debugDrawLineWidth;
} else {
if ( graphic.updateMesh( mesh ) ) {
graphic.getPipeline().update( graphic );

View File

@ -1,15 +0,0 @@
#include <uf/ext/lua/lua.h>
#if UF_USE_LUA && UF_USE_BULLET
#include <uf/utils/math/physics.h>
#include <uf/ext/bullet/bullet.h>
UF_LUA_REGISTER_USERTYPE(pod::Bullet,
UF_LUA_REGISTER_USERTYPE_DEFINE( setVelocity, UF_LUA_C_FUN(ext::bullet::setVelocity) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( applyImpulse, UF_LUA_C_FUN(ext::bullet::applyImpulse) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( applyMovement, UF_LUA_C_FUN(ext::bullet::applyMovement) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( applyVelocity, UF_LUA_C_FUN(ext::bullet::applyVelocity) ),
// UF_LUA_REGISTER_USERTYPE_DEFINE( applyRotation, UF_LUA_C_FUN(ext::bullet::applyRotation) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( activateCollision, UF_LUA_C_FUN(ext::bullet::activateCollision) )
)
#endif

View File

@ -7,9 +7,6 @@
#include <uf/engine/asset/asset.h>
#include <uf/utils/math/physics.h>
#include <uf/engine/object/behaviors/lua.h>
#if UF_USE_BULLET
#include <uf/ext/bullet/bullet.h>
#endif
namespace binds {
uf::stl::string formatHookName(uf::Object& self, const uf::stl::string n ){
@ -32,9 +29,7 @@ namespace binds {
UF_LUA_RETRIEVE_COMPONENT(uf::Asset)
UF_LUA_RETRIEVE_COMPONENT(uf::Camera)
UF_LUA_RETRIEVE_COMPONENT(pod::Physics)
#if UF_USE_BULLET
UF_LUA_RETRIEVE_COMPONENT(pod::Bullet)
#endif
UF_LUA_RETRIEVE_COMPONENT(pod::PhysicsState)
return sol::make_object( ext::lua::state, sol::lua_nil );
}
void setComponent(uf::Object& self, const uf::stl::string& type, sol::object value ) {
@ -56,9 +51,7 @@ namespace binds {
UF_LUA_UPDATE_COMPONENT(uf::Asset)
UF_LUA_UPDATE_COMPONENT(uf::Camera)
UF_LUA_UPDATE_COMPONENT(pod::Physics)
#if UF_USE_BULLET
UF_LUA_UPDATE_COMPONENT(pod::Bullet)
#endif
UF_LUA_UPDATE_COMPONENT(pod::PhysicsState)
}
bool bind(uf::Object& self, const uf::stl::string& type, sol::protected_function fun ) {
// if ( !self.hasBehavior({.type = uf::LuaBehavior::type}) ) uf::instantiator::bind( "LuaBehavior", self );

View File

@ -17,4 +17,14 @@ UF_LUA_REGISTER_USERTYPE(pod::Physics,
UF_LUA_REGISTER_USERTYPE_DEFINE( setLinearVelocity, UF_LUA_C_FUN(::binds::setLinearVelocity) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( setRotationalVelocity, UF_LUA_C_FUN(::binds::setRotationalVelocity) )
)
UF_LUA_REGISTER_USERTYPE(pod::PhysicsState,
UF_LUA_REGISTER_USERTYPE_DEFINE( setVelocity, UF_LUA_C_FUN(uf::physics::impl::setVelocity) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( applyImpulse, UF_LUA_C_FUN(uf::physics::impl::applyImpulse) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( applyMovement, UF_LUA_C_FUN(uf::physics::impl::applyMovement) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( applyVelocity, UF_LUA_C_FUN(uf::physics::impl::applyVelocity) ),
// UF_LUA_REGISTER_USERTYPE_DEFINE( applyRotation, UF_LUA_C_FUN(uf::physics::impl::applyRotation) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( activateCollision, UF_LUA_C_FUN(uf::physics::impl::activateCollision) )
)
#endif

View File

@ -0,0 +1,517 @@
#if UF_USE_REACTPHYSICS
#include <uf/utils/math/physics.h>
#include <uf/ext/reactphysics/reactphysics.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/engine/scene/scene.h>
#include <uf/engine/graph/graph.h>
#define UF_PHYSICS_SHARED 1
namespace {
rp3d::PhysicsCommon common;
rp3d::PhysicsWorld* world;
class EventListener : public rp3d::EventListener {
public:
virtual void onContact( const rp3d::CollisionCallback::CallbackData& callbackData ) override {
// UF_MSG_DEBUG("Contact");
}
} listener;
class RaycastCallback : public rp3d::RaycastCallback {
public:
bool isHit = false;
rp3d::RaycastInfo raycastInfo;
virtual rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& info) override {
if ( !isHit || raycastInfo.hitFraction > info.hitFraction ) {
raycastInfo.body = info.body;
raycastInfo.hitFraction = info.hitFraction;
raycastInfo.collider = info.collider;
raycastInfo.worldNormal = info.worldNormal;
raycastInfo.worldPoint = info.worldPoint;
isHit = true;
}
// return rp3d::decimal(1.0);
return raycastInfo.hitFraction;
}
};
rp3d::DefaultLogger* logger = NULL;
}
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;
void ext::reactphysics::initialize() {
rp3d::PhysicsWorld::WorldSettings settings;
settings.gravity = rp3d::Vector3( 0, -9.81, 0 );
// ::logger = ::common.createDefaultLogger();
// size_t logLevel = static_cast<uint>(rp3d::Logger::Level::Warning) | static_cast<uint>(rp3d::Logger::Level::Error); // | static_cast<uint>(rp3d::Logger::Level::Information);
// logger->addFileDestination("./data/logs/rp3d_log_.html", logLevel, rp3d::DefaultLogger::Format::HTML);
// ::common.setLogger(::logger);
::world = ::common.createPhysicsWorld(settings);
// ::world->setEventListener(&::listener);
if ( ext::reactphysics::debugDrawEnabled ) {
::world->setIsDebugRenderingEnabled(true);
rp3d::DebugRenderer& debugRenderer = ::world->getDebugRenderer();
// Select the contact points and contact normals to be displayed
debugRenderer.setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLIDER_AABB, true);
debugRenderer.setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::COLLISION_SHAPE, true);
debugRenderer.setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true);
debugRenderer.setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true);
}
}
void ext::reactphysics::tick( float delta ) {
#if UF_PHYSICS_SHARED
ext::reactphysics::syncTo();
#endif
static float accumulator = 0;
accumulator += uf::physics::time::delta;
while ( accumulator >= ext::reactphysics::timescale ) {
::world->update(ext::reactphysics::timescale);
accumulator -= ext::reactphysics::timescale;
}
TIMER(ext::reactphysics::debugDrawRate, ext::reactphysics::debugDrawEnabled && ) {
auto& scene = uf::scene::getCurrentScene();
ext::reactphysics::debugDraw( scene );
}
ext::reactphysics::syncFrom();
}
void ext::reactphysics::terminate() {
::common.destroyPhysicsWorld(::world);
::world = NULL;
}
// base collider creation
pod::PhysicsState& ext::reactphysics::create( uf::Object& object ) {
auto& state = object.getComponent<pod::PhysicsState>();
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
return state;
}
void ext::reactphysics::destroy( uf::Object& object ) {
auto& state = object.getComponent<pod::PhysicsState>();
ext::reactphysics::destroy( state );
}
void ext::reactphysics::destroy( pod::PhysicsState& state ) {
ext::reactphysics::detach( 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 ) );
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);
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();
state.body->updateMassPropertiesFromColliders();
} else {
state.body->setType(rp3d::BodyType::STATIC);
}
auto& material = collider->getMaterial();
material.setBounciness(0);
state.body->setLocalInertiaTensor( rp3d::Vector3( state.stats.inertia.x, state.stats.inertia.y, state.stats.inertia.z ) );
}
void ext::reactphysics::detach( pod::PhysicsState& state ) {
if ( !state.body ) return;
::world->destroyRigidBody(state.body);
state.body = NULL;
}
// collider for mesh (static or dynamic)
pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) {
auto* rMesh = ::common.createTriangleMesh();
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.stride ) {
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,
(const uint8_t*) remappedVertexAttribute.pointer,
remappedVertexAttribute.stride,
remappedIndexAttribute.length / 3,
(const uint8_t*) remappedIndexAttribute.pointer,
remappedIndexAttribute.stride * 3,
vertexType,
indexType
);
rMesh->addSubpart(vArray);
}
} else {
vArray = new rp3d::TriangleVertexArray(
vertexAttribute.length,
(const uint8_t*) vertexAttribute.pointer,
vertexAttribute.stride,
indexAttribute.length / 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 );
state.stats.mass = 0;
ext::reactphysics::attach( state );
return state;
}
// collider for boundingbox
pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const pod::Vector3f& extent ) {
auto& state = ext::reactphysics::create( object );
state.shape = ::common.createBoxShape( rp3d::Vector3( abs(extent.x), abs(extent.y), abs(extent.z) ) );
ext::reactphysics::attach( state );
return state;
}
// collider for capsule
pod::PhysicsState& ext::reactphysics::create( uf::Object& object, float radius, float height ) {
auto& state = ext::reactphysics::create( object );
state.shape = ::common.createCapsuleShape( radius, height );
ext::reactphysics::attach( state );
return state;
}
// synchronize engine transforms to bullet transforms
void ext::reactphysics::syncTo() {
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& 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 ) );
}
}
// synchronize bullet transforms to engine transforms
void ext::reactphysics::syncFrom() {
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;
// state transform is an offset, un-offset
if ( state.transform.reference ) {
transform.position -= state.transform.position;
}
/*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;
}
}
// apply impulse
void ext::reactphysics::applyImpulse( pod::PhysicsState& state, const pod::Vector3f& v ) {
}
// directly move a transform
void ext::reactphysics::applyMovement( pod::PhysicsState& state, const pod::Vector3f& v ) {
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 );
state.body->setTransform(transform);
}
// directly apply a velocity
void ext::reactphysics::setVelocity( pod::PhysicsState& state, const pod::Vector3f& v ) {
if ( !state.body ) return;
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 ) );
}
}
void ext::reactphysics::applyVelocity( pod::PhysicsState& state, const pod::Vector3f& v ) {
if ( !state.body ) return;
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 ) );
}
}
// directly rotate a transform
void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Quaternion<>& q ) {
if ( !state.body ) return;
if ( state.shared ) {
auto& transform = state.object->getComponent<pod::Transform<>>();
uf::transform::rotate( transform, q );
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 ) );
state.body->setTransform(transform);
}
void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Vector3f& axis, float delta ) {
ext::reactphysics::applyRotation( state, uf::quaternion::axisAngle( axis, delta ) );
}
// ray casting
float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction ) {
if ( !::world )
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 );
if ( !callback.isHit ) return -1;
return callback.raycastInfo.hitFraction;
}
float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, size_t& uid ) {
if ( !::world )
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 );
uid = 0;
if ( !callback.isHit ) {
return -1;
}
auto* object = (uf::Object*) callback.raycastInfo.body->getUserData();
uid = object->getUid();
return callback.raycastInfo.hitFraction;
}
float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, uf::Object*& object ) {
if ( !::world )
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 );
object = NULL;
if ( !callback.isHit ) {
return -1;
}
object = (uf::Object*) callback.raycastInfo.body->getUserData();
return callback.raycastInfo.hitFraction;
}
// allows noclip
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

@ -1,4 +1,5 @@
#include <uf/utils/math/physics.h>
#include <iostream>
uf::Timer<> uf::physics::time::timer;
uf::physics::num_t uf::physics::time::current;
@ -6,8 +7,10 @@ uf::physics::num_t uf::physics::time::previous;
uf::physics::num_t uf::physics::time::delta;
uf::physics::num_t uf::physics::time::clamp;
#include <iostream>
void UF_API uf::physics::initialize() {
uf::physics::impl::initialize();
}
void UF_API uf::physics::tick() {
uf::physics::time::previous = uf::physics::time::current;
uf::physics::time::current = uf::physics::time::timer.elapsed();
@ -15,4 +18,8 @@ void UF_API uf::physics::tick() {
if ( uf::physics::time::delta > uf::physics::time::clamp ) {
uf::physics::time::delta = uf::physics::time::clamp;
}
uf::physics::impl::tick();
}
void UF_API uf::physics::terminate() {
uf::physics::impl::terminate();
}

View File

@ -10,7 +10,6 @@
#include <uf/utils/audio/audio.h>
#include <uf/ext/openvr/openvr.h>
#include <uf/engine/graph/graph.h>
#include <uf/ext/bullet/bullet.h>
#include <uf/utils/math/physics.h>
#include <uf/spec/controller/controller.h>
#include <uf/utils/io/inputs.h>
@ -23,7 +22,7 @@ UF_BEHAVIOR_TRAITS_CPP(ext::PlayerBehavior, ticks = true, renders = false, multi
void ext::PlayerBehavior::initialize( uf::Object& self ) {
auto& transform = this->getComponent<pod::Transform<>>();
auto& collider = this->getComponent<pod::Bullet>();
auto& collider = this->getComponent<pod::PhysicsState>();
auto& metadata = this->getComponent<ext::PlayerBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
@ -80,9 +79,7 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
if ( metadata.camera.invert.x ) relta.x *= -1;
metadata.camera.limit.current.x += relta.x;
if ( metadata.camera.limit.current.x != metadata.camera.limit.current.x || ( metadata.camera.limit.current.x < metadata.camera.limit.max.x && metadata.camera.limit.current.x > metadata.camera.limit.min.x ) ) {
#if UF_USE_BULLET
if ( collider.body ) ext::bullet::applyRotation( collider, transform.up, relta.x ); else
#endif
if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, relta.x ); else
uf::transform::rotate( transform, transform.up, relta.x );
} else metadata.camera.limit.current.x -= relta.x;
}
@ -91,7 +88,7 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
metadata.camera.limit.current.y += relta.y;
if ( metadata.camera.limit.current.y != metadata.camera.limit.current.y || ( metadata.camera.limit.current.y < metadata.camera.limit.max.y && metadata.camera.limit.current.y > metadata.camera.limit.min.y ) ) {
// if ( collider.body && !collider.shared ) {
// ext::bullet::applyRotation( collider, cameraTransform.right, relta.y );
// uf::physics::impl::applyRotation( collider, cameraTransform.right, relta.y );
// } else {
uf::transform::rotate( cameraTransform, cameraTransform.right, relta.y );
// }
@ -209,14 +206,10 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
stats.menu = metadata.system.menu;
stats.noclipped = metadata.system.noclipped;
stats.floored = stats.noclipped;
#if UF_USE_BULLET
auto& collider = this->getComponent<pod::Bullet>();
if ( !stats.floored && collider.body && ext::bullet::rayCast( transform.position, transform.position - pod::Vector3f{0,1,0} ) >= 0.0f ) stats.floored = true; else
#endif
auto& collider = this->getComponent<pod::PhysicsState>();
if ( !stats.floored && collider.body && uf::physics::impl::rayCast( transform.position, transform.position - pod::Vector3f{0,1,0} ) >= 0.0f ) stats.floored = true; else
stats.floored |= fabs(physics.linear.velocity.y) < 0.01f;
#if UF_USE_BULLET
TIMER(0.125, keys.use && ) {
size_t uid = 0;
uf::Object* pointer = NULL;
@ -224,7 +217,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
pod::Vector3f pos = transform.position + cameraTransform.position;
pod::Vector3f dir = uf::vector::normalize( transform.forward + pod::Vector3f{ 0, cameraTransform.forward.y, 0 } ) * length;
float depth = ext::bullet::rayCast( pos, pos + dir, pointer );
float depth = uf::physics::impl::rayCast( pos, pos + dir, pointer );
if ( pointer ) {
uf::Serializer payload;
payload["uid"] = this->getUid();
@ -248,7 +241,6 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
}
}
}
#endif
struct {
float move = 4;
@ -324,21 +316,19 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
metadata.system.noclipped = state;
UF_MSG_DEBUG( (state ? "En" : "Dis") << "abled noclip: " << uf::vector::toString(transform.position));
#if 0
if ( state ) {
#if UF_USE_BULLET
if ( collider.body ) {
collider.body->setGravity(btVector3(0,0.0,0));
collider.body->setCollisionFlags(collider.body->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
}
#endif
} else {
#if UF_USE_BULLET
if ( collider.body ) {
collider.body->setGravity(btVector3(0,-9.81,0));
collider.body->setCollisionFlags(collider.body->getCollisionFlags() & ~btCollisionObject::CF_NO_CONTACT_RESPONSE);
}
#endif
}
#endif
stats.noclipped = state;
}
// movement handler
@ -376,15 +366,11 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
}
if ( keys.lookRight ^ keys.lookLeft ) {
#if UF_USE_BULLET
if ( collider.body ) ext::bullet::applyRotation( collider, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else
#endif
if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else
uf::transform::rotate( transform, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) );
}
{
#if UF_USE_BULLET
if ( collider.body ) ext::bullet::setVelocity( collider, physics.linear.velocity ); else
#endif
if ( collider.body ) uf::physics::impl::setVelocity( collider, physics.linear.velocity ); else
transform.position += physics.linear.velocity * uf::physics::time::delta;
}

View File

@ -45,7 +45,6 @@
#include <uf/ext/openvr/openvr.h>
#include <uf/ext/lua/lua.h>
#include <uf/ext/ultralight/ultralight.h>
#include <uf/ext/bullet/bullet.h>
bool ext::ready = false;
uf::stl::vector<uf::stl::string> ext::arguments;
@ -216,12 +215,19 @@ void EXT_API ext::initialize() {
// Set worker threads
if ( ::config["engine"]["threads"]["workers"].as<uf::stl::string>() == "async" ) {
uf::thread::async = true;
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
::config["engine"]["threads"]["workers"] = threads;
uf::thread::workers = ::config["engine"]["threads"]["workers"].as<size_t>();
UF_MSG_DEBUG("Using async worker threads");
} else if ( ::config["engine"]["threads"]["workers"].as<uf::stl::string>() == "auto" ) {
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
::config["engine"]["threads"]["workers"] = threads;
uf::thread::workers = ::config["engine"]["threads"]["workers"].as<size_t>();
UF_MSG_DEBUG("Using " << threads << " worker threads");
} else if ( ::config["engine"]["threads"]["workers"].is<size_t>() ) {
auto threads = ::config["engine"]["threads"]["workers"].as<size_t>();
uf::thread::workers = threads;
UF_MSG_DEBUG("Using " << threads << " worker threads");
}
// Audio settings
{
@ -259,6 +265,15 @@ void EXT_API ext::initialize() {
ext::bullet::debugDrawEnabled = ::config["engine"]["ext"]["bullet"]["debug draw"]["enabled"].as( ext::bullet::debugDrawEnabled );
ext::bullet::debugDrawRate = ::config["engine"]["ext"]["bullet"]["debug draw"]["rate"].as( ext::bullet::debugDrawRate );
ext::bullet::debugDrawLayer = ::config["engine"]["ext"]["bullet"]["debug draw"]["layer"].as( ext::bullet::debugDrawLayer );
ext::bullet::debugDrawLineWidth = ::config["engine"]["ext"]["bullet"]["debug draw"]["line width"].as( ext::bullet::debugDrawLineWidth );
}
#elif UF_USE_REACTPHYSICS
{
ext::reactphysics::timescale = ::config["engine"]["ext"]["reactphysics"]["timescale"].as( ext::reactphysics::timescale );
ext::reactphysics::debugDrawEnabled = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["enabled"].as( ext::reactphysics::debugDrawEnabled );
ext::reactphysics::debugDrawRate = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["rate"].as( ext::reactphysics::debugDrawRate );
ext::reactphysics::debugDrawLayer = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["layer"].as( ext::reactphysics::debugDrawLayer );
ext::reactphysics::debugDrawLineWidth = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["line width"].as( ext::reactphysics::debugDrawLineWidth );
}
#endif
@ -341,12 +356,9 @@ void EXT_API ext::initialize() {
}
#endif
#if UF_USE_BULLET
/* Bullet */ {
ext::bullet::initialize();
/* Physics */ {
uf::physics::initialize();
}
#endif
#if UF_USE_OPENVR
{
ext::openvr::enabled = ::config["engine"]["ext"]["vr"]["enable"].as( ext::openvr::enabled );
@ -409,13 +421,13 @@ void EXT_API ext::initialize() {
#if UF_USE_VULKAN
/* Callbacks for 2KHR stuffs */ {
uf::hooks.addHook("vulkan:Instance.ExtensionsEnabled", []( const ext::json::Value& json ) {
UF_MSG_DEBUG("vulkan:Instance.ExtensionsEnabled: " << json);
// UF_MSG_DEBUG("vulkan:Instance.ExtensionsEnabled: " << json);
});
uf::hooks.addHook("vulkan:Device.ExtensionsEnabled", []( const ext::json::Value& json ) {
UF_MSG_DEBUG("vulkan:Device.ExtensionsEnabled: " << json);
// UF_MSG_DEBUG("vulkan:Device.ExtensionsEnabled: " << json);
});
uf::hooks.addHook("vulkan:Device.FeaturesEnabled", []( const ext::json::Value& json ) {
UF_MSG_DEBUG("vulkan:Device.FeaturesEnabled: " << json);
// UF_MSG_DEBUG("vulkan:Device.FeaturesEnabled: " << json);
VkPhysicalDeviceFeatures2KHR deviceFeatures2{};
VkPhysicalDeviceMultiviewFeaturesKHR extFeatures{};
@ -424,10 +436,10 @@ void EXT_API ext::initialize() {
deviceFeatures2.pNext = &extFeatures;
PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(vkGetInstanceProcAddr(uf::renderer::device.instance, "vkGetPhysicalDeviceFeatures2KHR"));
vkGetPhysicalDeviceFeatures2KHR(uf::renderer::device.physicalDevice, &deviceFeatures2);
UF_MSG_DEBUG("Multiview features:" );
UF_MSG_DEBUG("\tmultiview = " << extFeatures.multiview );
UF_MSG_DEBUG("\tmultiviewGeometryShader = " << extFeatures.multiviewGeometryShader );
UF_MSG_DEBUG("\tmultiviewTessellationShader = " << extFeatures.multiviewTessellationShader );
// UF_MSG_DEBUG("Multiview features:" );
// UF_MSG_DEBUG("\tmultiview = " << extFeatures.multiview );
// UF_MSG_DEBUG("\tmultiviewGeometryShader = " << extFeatures.multiviewGeometryShader );
// UF_MSG_DEBUG("\tmultiviewTessellationShader = " << extFeatures.multiviewTessellationShader );
VkPhysicalDeviceProperties2KHR deviceProps2{};
VkPhysicalDeviceMultiviewPropertiesKHR extProps{};
@ -436,9 +448,9 @@ void EXT_API ext::initialize() {
deviceProps2.pNext = &extProps;
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(vkGetInstanceProcAddr(uf::renderer::device.instance, "vkGetPhysicalDeviceProperties2KHR"));
vkGetPhysicalDeviceProperties2KHR(uf::renderer::device.physicalDevice, &deviceProps2);
UF_MSG_DEBUG("Multiview properties:");
UF_MSG_DEBUG("\tmaxMultiviewViewCount = " << extProps.maxMultiviewViewCount);
UF_MSG_DEBUG("\tmaxMultiviewInstanceIndex = " << extProps.maxMultiviewInstanceIndex);
// UF_MSG_DEBUG("Multiview properties:");
// UF_MSG_DEBUG("\tmaxMultiviewViewCount = " << extProps.maxMultiviewViewCount);
// UF_MSG_DEBUG("\tmaxMultiviewInstanceIndex = " << extProps.maxMultiviewInstanceIndex);
});
}
#endif
@ -561,11 +573,6 @@ void EXT_API ext::tick() {
/* Update physics timer */ {
uf::physics::tick();
}
#if UF_USE_BULLET
/* Update bullet */ {
ext::bullet::tick();
}
#endif
/* Update graph */ {
uf::graph::tick();
}
@ -659,11 +666,9 @@ void EXT_API ext::terminate() {
/* Terminate controllers */ {
spec::controller::terminate();
}
#if UF_USE_BULLET
/* Kill bullet */ {
ext::bullet::terminate();
/* Kill physics */ {
uf::physics::terminate();
}
#endif
#if UF_USE_ULTRALIGHT
/* Ultralight-UX */ if ( ::config["engine"]["ext"]["ultralight"]["enabled"].as<bool>() ) {
ext::ultralight::terminate();