physics controller can use root motion from animation

This commit is contained in:
Mikulas Florek 2020-09-10 13:04:57 +02:00
parent 9fe74e7cf6
commit d3f925c67f
6 changed files with 111 additions and 104 deletions

View file

@ -612,7 +612,9 @@ struct AnimationSceneImpl final : AnimationScene
LocalRigidTransform getAnimatorRootMotion(EntityRef entity) override
{
Animator& animator = m_animators[m_animator_map[entity]];
auto iter = m_animator_map.find(entity);
if (!iter.isValid()) return {};
Animator& animator = m_animators[iter.value()];
return animator.root_motion;
}
@ -663,13 +665,6 @@ struct AnimationSceneImpl final : AnimationScene
animator.ctx->root_bone_hash = crc32("RigRoot");
animator.resource->update(*animator.ctx, Ref(animator.root_motion));
if (animator.resource->m_flags.isSet(Anim::Controller::Flags::USE_ROOT_MOTION)) {
Transform tr = m_universe.getTransform(entity);
tr.rot = tr.rot * animator.root_motion.rot;
tr.pos = tr.pos + tr.rot.rotate(animator.root_motion.pos);
m_universe.setTransform(entity, tr);
}
model->getRelativePose(*pose);
animator.resource->getPose(*animator.ctx, Ref(*pose));

View file

@ -46,9 +46,7 @@ public:
Array<String> m_animation_slots;
Array<BoneMask> m_bone_masks;
InputDecl m_inputs;
enum class Flags : u32 {
USE_ROOT_MOTION = 1 << 0
};
enum class Flags : u32 {};
FlagSet<Flags, u32> m_flags;
struct IK {
enum { MAX_BONES_COUNT = 8 };

View file

@ -664,12 +664,6 @@ struct ControllerEditorImpl : ControllerEditor {
ImGui::Text("Please select a model.");
}
}
if (ImGui::CollapsingHeader("Controller properties")) {
bool use_root_motion = m_controller->m_flags.isSet(Anim::Controller::Flags::USE_ROOT_MOTION);
ImGui::Checkbox("Use root motion", &use_root_motion);
m_controller->m_flags.set(Anim::Controller::Flags::USE_ROOT_MOTION, use_root_motion);
}
}
ImGui::End();
}

View file

@ -1,6 +1,7 @@
#include <PxPhysicsAPI.h>
#include "physics/physics_scene.h"
#include "animation/animation_scene.h"
#include "engine/associative_array.h"
#include "engine/crc32.h"
#include "engine/engine.h"
@ -450,7 +451,7 @@ struct PhysicsSceneImpl final : PhysicsScene
{
for (auto& controller : m_controllers)
{
controller.m_controller->release();
controller.controller->release();
}
m_controllers.clear();
@ -575,26 +576,26 @@ struct PhysicsSceneImpl final : PhysicsScene
IPlugin& getPlugin() const override { return *m_system; }
u32 getControllerLayer(EntityRef entity) override { return m_controllers[entity].m_layer; }
u32 getControllerLayer(EntityRef entity) override { return m_controllers[entity].layer; }
void setControllerLayer(EntityRef entity, u32 layer) override
{
ASSERT(layer < lengthOf(m_layers.names));
auto& controller = m_controllers[entity];
controller.m_layer = layer;
controller.layer = layer;
PxFilterData data;
data.word0 = 1 << layer;
data.word1 = m_layers.filter[layer];
controller.m_filter_data = data;
controller.filter_data = data;
PxShape* shapes[8];
int shapes_count = controller.m_controller->getActor()->getShapes(shapes, lengthOf(shapes));
int shapes_count = controller.controller->getActor()->getShapes(shapes, lengthOf(shapes));
for (int i = 0; i < shapes_count; ++i)
{
shapes[i]->setSimulationFilterData(data);
}
controller.m_controller->invalidateCache();
controller.controller->invalidateCache();
}
@ -1126,7 +1127,7 @@ struct PhysicsSceneImpl final : PhysicsScene
void destroyController(EntityRef entity)
{
m_controllers[entity].m_controller->release();
m_controllers[entity].controller->release();
m_controllers.erase(entity);
m_universe.onComponentDestroyed(entity, CONTROLLER_TYPE, this);
}
@ -1313,23 +1314,23 @@ struct PhysicsSceneImpl final : PhysicsScene
DVec3 position = m_universe.getPosition(entity);
cDesc.position.set(position.x, position.y, position.z);
Controller& c = m_controllers.insert(entity, Controller());
c.m_controller = m_controller_manager->createController(cDesc);
c.m_entity = entity;
c.m_frame_change.set(0, 0, 0);
c.m_radius = cDesc.radius;
c.m_height = cDesc.height;
c.m_custom_gravity = false;
c.m_custom_gravity_acceleration = 9.8f;
c.m_layer = 0;
c.controller = m_controller_manager->createController(cDesc);
c.entity = entity;
c.frame_change.set(0, 0, 0);
c.radius = cDesc.radius;
c.height = cDesc.height;
c.custom_gravity = false;
c.custom_gravity_acceleration = 9.8f;
c.layer = 0;
PxFilterData data;
int controller_layer = c.m_layer;
int controller_layer = c.layer;
data.word0 = 1 << controller_layer;
data.word1 = m_layers.filter[controller_layer];
c.m_filter_data = data;
c.filter_data = data;
PxShape* shapes[8];
int shapes_count = c.m_controller->getActor()->getShapes(shapes, lengthOf(shapes));
c.m_controller->getActor()->userData = (void*)(intptr_t)entity.index;
int shapes_count = c.controller->getActor()->getShapes(shapes, lengthOf(shapes));
c.controller->getActor()->userData = (void*)(intptr_t)entity.index;
for (int i = 0; i < shapes_count; ++i)
{
shapes[i]->setSimulationFilterData(data);
@ -1540,29 +1541,20 @@ struct PhysicsSceneImpl final : PhysicsScene
}
bool isControllerCollisionDown(EntityRef entity) const override
{
const Controller& ctrl = m_controllers[entity];
PxControllerState state;
ctrl.m_controller->getState(state);
return (state.collisionFlags & PxControllerCollisionFlag::eCOLLISION_DOWN) != 0;
}
void updateControllers(float time_delta)
{
PROFILE_FUNCTION();
for (auto& controller : m_controllers)
{
Vec3 dif = controller.m_frame_change;
controller.m_frame_change.set(0, 0, 0);
Vec3 dif = controller.frame_change;
controller.frame_change.set(0, 0, 0);
PxControllerState state;
controller.m_controller->getState(state);
controller.controller->getState(state);
float gravity_acceleration = 0.0f;
if (controller.m_custom_gravity)
if (controller.custom_gravity)
{
gravity_acceleration = controller.m_custom_gravity_acceleration * -1.0f;
gravity_acceleration = controller.custom_gravity_acceleration * -1.0f;
}
else
{
@ -1580,12 +1572,12 @@ struct PhysicsSceneImpl final : PhysicsScene
controller.gravity_speed = 0;
}
m_filter_callback.m_filter_data = controller.m_filter_data;
m_filter_callback.m_filter_data = controller.filter_data;
PxControllerFilters filters(nullptr, &m_filter_callback);
controller.m_controller->move(toPhysx(dif), 0.001f, time_delta, filters);
PxExtendedVec3 p = controller.m_controller->getFootPosition();
controller.controller->move(toPhysx(dif), 0.001f, time_delta, filters);
PxExtendedVec3 p = controller.controller->getFootPosition();
m_universe.setPosition(controller.m_entity, {p.x, p.y, p.z});
m_universe.setPosition(controller.entity, {p.x, p.y, p.z});
}
}
@ -2139,6 +2131,21 @@ struct PhysicsSceneImpl final : PhysicsScene
PxVehicleUpdates(time_delta, m_scene->getGravity(), *m_vehicle_frictions, count, wheels, nullptr);
}
void lateUpdate(float time_delta, bool paused) override {
if (!m_is_game_running || paused) return;
AnimationScene* anim_scene = (AnimationScene*)m_universe.getScene(crc32("animation"));
if (!anim_scene) return;
for (Controller& ctrl : m_controllers) {
if (ctrl.use_root_motion) {
const LocalRigidTransform tr = anim_scene->getAnimatorRootMotion(ctrl.entity);
const Quat rot = m_universe.getRotation(ctrl.entity);
ctrl.frame_change += rot.rotate(tr.pos);
m_universe.setRotation(ctrl.entity, rot * tr.rot);
}
}
}
void update(float time_delta, bool paused) override
{
@ -2472,12 +2479,12 @@ struct PhysicsSceneImpl final : PhysicsScene
void stopGame() override { m_is_game_running = false; }
float getControllerRadius(EntityRef entity) override { return m_controllers[entity].m_radius; }
float getControllerHeight(EntityRef entity) override { return m_controllers[entity].m_height; }
bool getControllerCustomGravity(EntityRef entity) override { return m_controllers[entity].m_custom_gravity; }
float getControllerRadius(EntityRef entity) override { return m_controllers[entity].radius; }
float getControllerHeight(EntityRef entity) override { return m_controllers[entity].height; }
bool getControllerCustomGravity(EntityRef entity) override { return m_controllers[entity].custom_gravity; }
float getControllerCustomGravityAcceleration(EntityRef entity) override
{
return m_controllers[entity].m_custom_gravity_acceleration;
return m_controllers[entity].custom_gravity_acceleration;
}
@ -2486,9 +2493,9 @@ struct PhysicsSceneImpl final : PhysicsScene
if (value <= 0) return;
Controller& ctrl = m_controllers[entity];
ctrl.m_radius = value;
ctrl.radius = value;
PxRigidActor* actor = ctrl.m_controller->getActor();
PxRigidActor* actor = ctrl.controller->getActor();
PxShape* shapes;
if (actor->getNbShapes() == 1 && actor->getShapes(&shapes, 1))
{
@ -2506,9 +2513,9 @@ struct PhysicsSceneImpl final : PhysicsScene
if (value <= 0) return;
Controller& ctrl = m_controllers[entity];
ctrl.m_height = value;
ctrl.height = value;
PxRigidActor* actor = ctrl.m_controller->getActor();
PxRigidActor* actor = ctrl.controller->getActor();
PxShape* shapes;
if (actor->getNbShapes() == 1 && actor->getShapes(&shapes, 1))
{
@ -2523,28 +2530,36 @@ struct PhysicsSceneImpl final : PhysicsScene
void setControllerCustomGravity(EntityRef entity, bool value) override
{
Controller& ctrl = m_controllers[entity];
ctrl.m_custom_gravity = value;
ctrl.custom_gravity = value;
}
void setControllerCustomGravityAcceleration(EntityRef entity, float value) override
{
Controller& ctrl = m_controllers[entity];
ctrl.m_custom_gravity_acceleration = value;
ctrl.custom_gravity_acceleration = value;
}
bool isControllerTouchingDown(EntityRef entity) override
bool isControllerCollisionDown(EntityRef entity) const override
{
const Controller& ctrl = m_controllers[entity];
PxControllerState state;
m_controllers[entity].m_controller->getState(state);
ctrl.controller->getState(state);
return (state.collisionFlags & PxControllerCollisionFlag::eCOLLISION_DOWN) != 0;
}
bool getControllerUseRootMotion(EntityRef entity) override {
return m_controllers[entity].use_root_motion;
}
void setControllerUseRootMotion(EntityRef entity, bool enable) override {
m_controllers[entity].use_root_motion = enable;
}
void resizeController(EntityRef entity, float height) override
{
Controller& ctrl = m_controllers[entity];
ctrl.m_height = height;
ctrl.m_controller->resize(height);
ctrl.height = height;
ctrl.controller->resize(height);
}
@ -2569,7 +2584,7 @@ struct PhysicsSceneImpl final : PhysicsScene
}
void moveController(EntityRef entity, const Vec3& v) override { m_controllers[entity].m_frame_change += v; }
void moveController(EntityRef entity, const Vec3& v) override { m_controllers[entity].frame_change += v; }
static int LUA_raycast(lua_State* L)
@ -2693,7 +2708,7 @@ struct PhysicsSceneImpl final : PhysicsScene
Controller& controller = iter.value();
DVec3 pos = m_universe.getPosition(entity);
PxExtendedVec3 pvec(pos.x, pos.y, pos.z);
controller.m_controller->setFootPosition(pvec);
controller.controller->setFootPosition(pvec);
}
}
@ -2900,17 +2915,17 @@ struct PhysicsSceneImpl final : PhysicsScene
for (auto& controller : m_controllers)
{
PxFilterData data;
int controller_layer = controller.m_layer;
int controller_layer = controller.layer;
data.word0 = 1 << controller_layer;
data.word1 = m_layers.filter[controller_layer];
controller.m_filter_data = data;
controller.filter_data = data;
PxShape* shapes[8];
int shapes_count = controller.m_controller->getActor()->getShapes(shapes, lengthOf(shapes));
int shapes_count = controller.controller->getActor()->getShapes(shapes, lengthOf(shapes));
for (int i = 0; i < shapes_count; ++i)
{
shapes[i]->setSimulationFilterData(data);
}
controller.m_controller->invalidateCache();
controller.controller->invalidateCache();
}
for (auto& terrain : m_terrains)
@ -3332,12 +3347,13 @@ struct PhysicsSceneImpl final : PhysicsScene
serializer.write((i32)m_controllers.size());
for (const auto& controller : m_controllers)
{
serializer.write(controller.m_entity);
serializer.write(controller.m_layer);
serializer.write(controller.m_radius);
serializer.write(controller.m_height);
serializer.write(controller.m_custom_gravity);
serializer.write(controller.m_custom_gravity_acceleration);
serializer.write(controller.entity);
serializer.write(controller.layer);
serializer.write(controller.radius);
serializer.write(controller.height);
serializer.write(controller.custom_gravity);
serializer.write(controller.custom_gravity_acceleration);
serializer.write(controller.use_root_motion);
}
serializer.write((i32)m_terrains.size());
for (auto& terrain : m_terrains)
@ -3775,23 +3791,24 @@ struct PhysicsSceneImpl final : PhysicsScene
serializer.read(entity);
entity = entity_map.get(entity);
Controller& c = m_controllers.insert(entity, Controller());
c.m_frame_change.set(0, 0, 0);
c.frame_change.set(0, 0, 0);
serializer.read(c.m_layer);
serializer.read(c.m_radius);
serializer.read(c.m_height);
serializer.read(c.m_custom_gravity);
serializer.read(c.m_custom_gravity_acceleration);
serializer.read(c.layer);
serializer.read(c.radius);
serializer.read(c.height);
serializer.read(c.custom_gravity);
serializer.read(c.custom_gravity_acceleration);
serializer.read(c.use_root_motion);
PxCapsuleControllerDesc cDesc;
initControllerDesc(cDesc);
cDesc.height = c.m_height;
cDesc.radius = c.m_radius;
cDesc.height = c.height;
cDesc.radius = c.radius;
DVec3 position = m_universe.getPosition(entity);
cDesc.position.set(position.x, position.y - cDesc.height * 0.5f, position.z);
c.m_controller = m_controller_manager->createController(cDesc);
c.m_controller->getActor()->userData = (void*)(intptr_t)entity.index;
c.m_entity = entity;
c.m_controller->setFootPosition({position.x, position.y, position.z});
c.controller = m_controller_manager->createController(cDesc);
c.controller->getActor()->userData = (void*)(intptr_t)entity.index;
c.entity = entity;
c.controller->setFootPosition({position.x, position.y, position.z});
m_universe.onComponentCreated(entity, CONTROLLER_TYPE, this);
}
}
@ -4114,16 +4131,17 @@ struct PhysicsSceneImpl final : PhysicsScene
struct Controller
{
PxController* m_controller;
EntityRef m_entity;
Vec3 m_frame_change;
float m_radius;
float m_height;
bool m_custom_gravity;
float m_custom_gravity_acceleration;
u32 m_layer;
PxFilterData m_filter_data;
PxController* controller;
EntityRef entity;
Vec3 frame_change;
float radius;
float height;
float custom_gravity_acceleration;
u32 layer;
PxFilterData filter_data;
bool custom_gravity = false;
bool use_root_motion = 0;
float gravity_speed = 0;
};

View file

@ -196,8 +196,9 @@ struct LUMIX_PHYSICS_API PhysicsScene : IScene
virtual void setControllerCustomGravity(EntityRef entity, bool gravity) = 0;
virtual float getControllerCustomGravityAcceleration(EntityRef entity) = 0;
virtual void setControllerCustomGravityAcceleration(EntityRef entity, float gravityacceleration) = 0;
virtual bool isControllerTouchingDown(EntityRef entity) = 0;
virtual void resizeController(EntityRef entity, float height) = 0;
virtual bool getControllerUseRootMotion(EntityRef entity) = 0;
virtual void setControllerUseRootMotion(EntityRef entity, bool enable) = 0;
virtual void addBoxGeometry(EntityRef entity, int index) = 0;
virtual void removeBoxGeometry(EntityRef entity, int index) = 0;

View file

@ -123,8 +123,9 @@ namespace Lumix
property("Radius", LUMIX_PROP(PhysicsScene, ControllerRadius)),
property("Height", LUMIX_PROP(PhysicsScene, ControllerHeight)),
property("Layer", LUMIX_PROP(PhysicsScene, ControllerLayer), LayerEnum()),
property("Use Custom Gravity", LUMIX_PROP(PhysicsScene, ControllerCustomGravity)),
property("Custom Gravity Acceleration", LUMIX_PROP(PhysicsScene, ControllerCustomGravityAcceleration))
property("Use root motion", LUMIX_PROP(PhysicsScene, ControllerUseRootMotion)),
property("Use custom gravity", LUMIX_PROP(PhysicsScene, ControllerCustomGravity)),
property("Custom gravity acceleration", LUMIX_PROP(PhysicsScene, ControllerCustomGravityAcceleration))
),
component("rigid_actor",
property("Layer", LUMIX_PROP(PhysicsScene, ActorLayer), LayerEnum()),