diff --git a/Makefile b/Makefile index b38a3749..eb430cc5 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/bin/data/config.json b/bin/data/config.json index 60088413..1561098e 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -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, diff --git a/bin/data/entities/player.json b/bin/data/entities/player.json index 4260dacf..657cb622 100644 --- a/bin/data/entities/player.json +++ b/bin/data/entities/player.json @@ -32,7 +32,7 @@ }, "gravity": [ 0, -9.81, 0 ], - "inertia": [ 10, 10, 10 ], + "inertia": [ 0, 0, 0 ], "type": "capsule", "radius": 1, diff --git a/bin/data/scenes/sh2_mcdonalds/door.json b/bin/data/scenes/sh2_mcdonalds/door.json index 41caf066..1f268ed9 100644 --- a/bin/data/scenes/sh2_mcdonalds/door.json +++ b/bin/data/scenes/sh2_mcdonalds/door.json @@ -2,6 +2,8 @@ "assets": ["./scripts/door.lua"], "system": { "physics": { + "mass": 0, + "inertia": [0, 0, 0], "type": "bounding box", "recenter": true } diff --git a/bin/data/scenes/sh2_mcdonalds/prop.json b/bin/data/scenes/sh2_mcdonalds/prop.json new file mode 100644 index 00000000..2d33ce82 --- /dev/null +++ b/bin/data/scenes/sh2_mcdonalds/prop.json @@ -0,0 +1,11 @@ +{ + "assets": [], + "system": { + "physics": { + "mass": 0, + "inertia": [0, 0, 0], + "type": "bounding box", + "recenter": true + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sh2_mcdonalds/scene.json b/bin/data/scenes/sh2_mcdonalds/scene.json index eaf478d4..0423132d 100644 --- a/bin/data/scenes/sh2_mcdonalds/scene.json +++ b/bin/data/scenes/sh2_mcdonalds/scene.json @@ -2,8 +2,8 @@ "import": "/scene.json", "assets": [ "./audio/soundscape/ambience.ogg", - "./loading.json", - "./static.json" + "./loading.json" + // "./static.json" ], "system": { "hot reload": { diff --git a/bin/data/scenes/sh2_mcdonalds/scripts/door.lua b/bin/data/scenes/sh2_mcdonalds/scripts/door.lua index ce18d5c1..accdcce0 100644 --- a/bin/data/scenes/sh2_mcdonalds/scripts/door.lua +++ b/bin/data/scenes/sh2_mcdonalds/scripts/door.lua @@ -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 ) \ No newline at end of file diff --git a/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json b/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json index 407bf7cc..bf833b41 100644 --- a/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json +++ b/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json @@ -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" } } } } } diff --git a/engine/inc/uf/ext/bullet/bullet.h b/engine/inc/uf/ext/bullet/bullet.h index 27207075..9de14a97 100644 --- a/engine/inc/uf/ext/bullet/bullet.h +++ b/engine/inc/uf/ext/bullet/bullet.h @@ -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 - pod::Bullet& create( uf::Object& o, const uf::Mesh_T& 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& UF_API create( uf::Object&, const uf::stl::vector& ); + pod::PhysicsState& UF_API create( uf::Object&, const pod::Vector3f& ); + uf::stl::vector& UF_API create( uf::Object&, const uf::stl::vector& ); // 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& ); diff --git a/engine/inc/uf/ext/reactphysics/reactphysics.h b/engine/inc/uf/ext/reactphysics/reactphysics.h new file mode 100644 index 00000000..4774e509 --- /dev/null +++ b/engine/inc/uf/ext/reactphysics/reactphysics.h @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#if UF_USE_REACTPHYSICS +#include + +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 \ No newline at end of file diff --git a/engine/inc/uf/utils/math/physics.h b/engine/inc/uf/utils/math/physics.h index 5061e84d..20b9a1bf 100644 --- a/engine/inc/uf/utils/math/physics.h +++ b/engine/inc/uf/utils/math/physics.h @@ -4,22 +4,20 @@ #include #include -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 +#elif UF_USE_REACTPHYSICS +#include +#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 pod::Transform& update( pod::Transform& transform, pod::Physics& physics ); template pod::Transform& update( pod::Physics& physics, pod::Transform& transform ); } diff --git a/engine/src/engine/graph/decode.cpp b/engine/src/engine/graph/decode.cpp index a54de24c..1d54bbdb 100644 --- a/engine/src/engine/graph/decode.cpp +++ b/engine/src/engine/graph/decode.cpp @@ -1,11 +1,11 @@ #include -#include #include #include #include #include #include #include +#include #include #include diff --git a/engine/src/engine/graph/encode.cpp b/engine/src/engine/graph/encode.cpp index 8c593a17..cd9cf9c8 100644 --- a/engine/src/engine/graph/encode.cpp +++ b/engine/src/engine/graph/encode.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -7,6 +6,7 @@ #include #include #include +#include #include #if UF_ENV_DREAMCAST diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index 401dcfb1..d4d33887 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -7,6 +6,7 @@ #include #include #include +#include #include #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(); - #if UF_USE_BULLET if ( type == "mesh" ) { - auto& collider = entity.getComponent(); + auto& collider = entity.getComponent(); 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(), mesh, !info["static"].as(true) ); + uf::physics::impl::create( entity.as(), mesh, !info["static"].as(true) ); } else { auto min = uf::matrix::multiply( model, bounds.min, 1.0f ); auto max = uf::matrix::multiply( 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 } } } diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index 814ee3f2..e0b1a2cd 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -9,8 +9,8 @@ #include #include #include +#include #include -#include 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(); + auto& collider = this->getComponent(); + 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() ) collider.transform.position = center - transform.position; + if ( metadataJson["system"]["physics"]["recenter"].as() ) collider.transform.position = (center - transform.position) * 0.5f; + uf::physics::impl::create( *this, corner ); } else if ( metadataJson["system"]["physics"]["type"].as() == "capsule" ) { float radius = metadataJson["system"]["physics"]["radius"].as(); float height = metadataJson["system"]["physics"]["height"].as(); - 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(); @@ -221,8 +219,8 @@ void uf::ObjectBehavior::tick( uf::Object& self ) { } /* - if ( this->hasComponent() && this->hasComponent() ) { - auto& collider = this->getComponent(); + if ( this->hasComponent() && this->hasComponent() ) { + auto& collider = this->getComponent(); auto& transform = this->getComponent>(); auto& physics = this->getComponent(); UF_MSG_DEBUG( this->getName() << ": " << this->getUid() << " " << uf::vector::toString( physics.linear.velocity ) << " " << uf::vector::toString( transform.position ) ); diff --git a/engine/src/ext/bullet/bullet.cpp b/engine/src/ext/bullet/bullet.cpp index 2f6a657f..7aa3816f 100644 --- a/engine/src/ext/bullet/bullet.cpp +++ b/engine/src/ext/bullet/bullet.cpp @@ -1,5 +1,5 @@ -#include #if UF_USE_BULLET +#include #include #include @@ -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() ) continue; + if ( !entity || !entity->isValid() || !entity->hasComponent() ) continue; - auto& collider = entity->getComponent(); + auto& collider = entity->getComponent(); if ( !collider.shared ) continue; auto& physics = entity->getComponent(); 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() ) continue; - size_t uid = entity->getUid(); + if ( !entity || !entity->isValid() || !entity->hasComponent() ) continue; - auto& collider = entity->getComponent(); + auto& collider = entity->getComponent(); auto& transform = entity->getComponent>(); 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::PhysicsState& ext::bullet::create( uf::Object& object ) { + auto& collider = object.getComponent(); 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>(); @@ -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>(); - 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>(); 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& ext::bullet::create( uf::Object& object, const uf::stl::vector& bounds ) { - auto& colliders = object.getComponent>(); +uf::stl::vector& ext::bullet::create( uf::Object& object, const uf::stl::vector& bounds ) { + auto& colliders = object.getComponent>(); colliders.reserve(colliders.size() + bounds.size()); auto& transform = object.getComponent>(); @@ -446,15 +413,15 @@ uf::stl::vector& 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 ); diff --git a/engine/src/ext/lua/usertypes/bullet.cpp b/engine/src/ext/lua/usertypes/bullet.cpp deleted file mode 100644 index 6d9996bf..00000000 --- a/engine/src/ext/lua/usertypes/bullet.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#if UF_USE_LUA && UF_USE_BULLET -#include -#include - -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 \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/object.cpp b/engine/src/ext/lua/usertypes/object.cpp index 67499068..597199fd 100644 --- a/engine/src/ext/lua/usertypes/object.cpp +++ b/engine/src/ext/lua/usertypes/object.cpp @@ -7,9 +7,6 @@ #include #include #include -#if UF_USE_BULLET - #include -#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 ); diff --git a/engine/src/ext/lua/usertypes/physics.cpp b/engine/src/ext/lua/usertypes/physics.cpp index e6f187ec..33e2e93f 100644 --- a/engine/src/ext/lua/usertypes/physics.cpp +++ b/engine/src/ext/lua/usertypes/physics.cpp @@ -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 \ No newline at end of file diff --git a/engine/src/ext/reactphysics/reactphysics.cpp b/engine/src/ext/reactphysics/reactphysics.cpp new file mode 100644 index 00000000..c6f596de --- /dev/null +++ b/engine/src/ext/reactphysics/reactphysics.cpp @@ -0,0 +1,517 @@ +#if UF_USE_REACTPHYSICS +#include +#include +#include +#include +#include +#include + +#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(rp3d::Logger::Level::Warning) | static_cast(rp3d::Logger::Level::Error); // | static_cast(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(); + + state.uid = object.getUid(); + state.object = &object; + state.transform.reference = &object.getComponent>(); +#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(); + 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(); 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();; + auto& transform = state.object->getComponent>(); + auto& physics = state.object->getComponent(); + + /*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(); + 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(); + 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>(); + 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 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() ) mesh.bind(); + + 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 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(); + auto& graphic = object.getComponent(); + 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 \ No newline at end of file diff --git a/engine/src/utils/math/physics.cpp b/engine/src/utils/math/physics.cpp index 1d74c9ea..8724d449 100644 --- a/engine/src/utils/math/physics.cpp +++ b/engine/src/utils/math/physics.cpp @@ -1,4 +1,5 @@ #include +#include 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 +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(); } \ No newline at end of file diff --git a/ext/behaviors/player/behavior.cpp b/ext/behaviors/player/behavior.cpp index db4d5bd8..19e006b7 100644 --- a/ext/behaviors/player/behavior.cpp +++ b/ext/behaviors/player/behavior.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -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>(); - auto& collider = this->getComponent(); + auto& collider = this->getComponent(); auto& metadata = this->getComponent(); auto& metadataJson = this->getComponent(); @@ -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(); - 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(); + 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; } diff --git a/ext/main.cpp b/ext/main.cpp index 0d1c4875..a23cfef9 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -45,7 +45,6 @@ #include #include #include -#include bool ext::ready = false; uf::stl::vector ext::arguments; @@ -216,12 +215,19 @@ void EXT_API ext::initialize() { // Set worker threads if ( ::config["engine"]["threads"]["workers"].as() == "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(); UF_MSG_DEBUG("Using async worker threads"); } else if ( ::config["engine"]["threads"]["workers"].as() == "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(); UF_MSG_DEBUG("Using " << threads << " worker threads"); + } else if ( ::config["engine"]["threads"]["workers"].is() ) { + auto threads = ::config["engine"]["threads"]["workers"].as(); + 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(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(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() ) { ext::ultralight::terminate();