Pārlūkot izejas kodu

Improve Actor. We still miss enable/disable_collision(). Investigating.

Daniele Bartolini 12 gadi atpakaļ
vecāks
revīzija
3168e8ea13
3 mainītis faili ar 392 papildinājumiem un 164 dzēšanām
  1. 138 35
      engine/lua/LuaActor.cpp
  2. 193 84
      engine/physics/Actor.cpp
  3. 61 45
      engine/physics/Actor.h

+ 138 - 35
engine/lua/LuaActor.cpp

@@ -31,6 +31,72 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
+//-----------------------------------------------------------------------------
+static int actor_world_position(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	stack.push_vector3(actor->world_position());
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+static int actor_world_rotation(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	stack.push_quaternion(actor->world_rotation());
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+static int actor_world_pose(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	stack.push_matrix4x4(actor->world_pose());
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+static int actor_teleport_world_position(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	const Vector3& pos = stack.get_vector3(2);
+	actor->teleport_world_position(pos);
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+static int actor_teleport_world_rotation(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	const Quaternion& rot = stack.get_quaternion(2);
+	actor->teleport_world_rotation(rot);
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+static int actor_teleport_world_pose(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	const Matrix4x4& mat = stack.get_matrix4x4(2);
+	actor->teleport_world_pose(mat);
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+static int actor_center_of_mass(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	stack.push_vector3(actor->center_of_mass());
+	return 1;
+}
+
 //-----------------------------------------------------------------------------
 static int actor_enable_gravity(lua_State* L)
 {
@@ -75,24 +141,20 @@ static int actor_disable_collision(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-static int actor_set_kinematic(lua_State* L)
+static int actor_set_collision_filter(lua_State* L)
 {
 	LuaStack stack(L);
 	Actor* actor = stack.get_actor(1);
-
-	actor->set_kinematic();
-
+	actor->set_collision_filter(stack.get_string(2));
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-static int actor_clear_kinematic(lua_State* L)
+static int actor_set_kinematic(lua_State* L)
 {
 	LuaStack stack(L);
 	Actor* actor = stack.get_actor(1);
-
-	actor->clear_kinematic();
-
+	actor->set_kinematic(stack.get_bool(2));
 	return 0;
 }
 
@@ -141,6 +203,18 @@ static int actor_is_kinematic(lua_State* L)
 	return 1;
 }
 
+//-----------------------------------------------------------------------------
+static int actor_is_nonkinematic(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Actor* actor = stack.get_actor(1);
+
+	stack.push_bool(actor->is_nonkinematic());
+	return 1;
+}
+
+
 //-----------------------------------------------------------------------------
 static int actor_linear_damping(lua_State* L)
 {
@@ -260,6 +334,15 @@ static int actor_add_impulse_at(lua_State* L)
 	return 0;
 }
 
+//-----------------------------------------------------------------------------
+static int actor_add_torque_impulse(lua_State* L)
+{
+	LuaStack stack(L);
+	Actor* actor = stack.get_actor(1);
+	actor->add_torque_impulse(stack.get_vector3(2));
+	return 0;
+}
+
 //-----------------------------------------------------------------------------
 static int actor_push(lua_State* L)
 {
@@ -274,6 +357,16 @@ static int actor_push(lua_State* L)
 	return 0;
 }
 
+//-----------------------------------------------------------------------------
+static int actor_push_at(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Actor* actor = stack.get_actor(1);
+	actor->push_at(stack.get_vector3(2), stack.get_float(2), stack.get_vector3(3));
+	return 0;
+}
+
 //-----------------------------------------------------------------------------
 static int actor_is_sleeping(lua_State* L)
 {
@@ -312,30 +405,40 @@ static int actor_unit(lua_State* L)
 //-----------------------------------------------------------------------------
 void load_actor(LuaEnvironment& env)
 {
-	env.load_module_function("Actor", "enable_gravity",			actor_enable_gravity);
-	env.load_module_function("Actor", "disable_gravity",		actor_disable_gravity);
-	env.load_module_function("Actor", "enable_collision",		actor_enable_collision);
-	env.load_module_function("Actor", "disable_collision",		actor_disable_collision);
-	env.load_module_function("Actor", "set_kinematic",			actor_set_kinematic);
-	env.load_module_function("Actor", "clear_kinematic",		actor_clear_kinematic);
-	env.load_module_function("Actor", "move",					actor_move);
-	env.load_module_function("Actor", "is_static",				actor_is_static);
-	env.load_module_function("Actor", "is_dynamic",				actor_is_dynamic);
-	env.load_module_function("Actor", "is_kinematic",			actor_is_kinematic);
-	env.load_module_function("Actor", "linear_damping",			actor_linear_damping);
-	env.load_module_function("Actor", "set_linear_damping",		actor_set_linear_damping);
-	env.load_module_function("Actor", "angular_damping",		actor_angular_damping);
-	env.load_module_function("Actor", "set_angular_damping",	actor_set_angular_damping);
-	env.load_module_function("Actor", "linear_velocity",		actor_linear_velocity);
-	env.load_module_function("Actor", "set_linear_velocity",	actor_set_linear_velocity);
-	env.load_module_function("Actor", "angular_velocity",		actor_angular_velocity);
-	env.load_module_function("Actor", "set_angular_velocity",	actor_set_angular_velocity);
-	env.load_module_function("Actor", "add_impulse",			actor_add_impulse);
-	env.load_module_function("Actor", "add_impulse_at",			actor_add_impulse_at);
-	env.load_module_function("Actor", "push",					actor_push);
-	env.load_module_function("Actor", "is_sleeping",			actor_is_sleeping);
-	env.load_module_function("Actor", "wake_up",				actor_wake_up);
-	env.load_module_function("Actor", "unit",					actor_unit);
-}
-
-} // namespace crown
+	env.load_module_function("Actor", "world_position", 			actor_world_position);
+	env.load_module_function("Actor", "world_rotation", 			actor_world_rotation);
+	env.load_module_function("Actor", "world_pose", 				actor_world_pose);
+	env.load_module_function("Actor", "teleport_world_position",	actor_teleport_world_position);
+	env.load_module_function("Actor", "teleport_world_rotation",	actor_teleport_world_rotation);
+	env.load_module_function("Actor", "teleport_world_pose",		actor_teleport_world_pose);
+	env.load_module_function("Actor", "center_of_mass",				actor_center_of_mass);
+	env.load_module_function("Actor", "enable_gravity",				actor_enable_gravity);
+	env.load_module_function("Actor", "disable_gravity",			actor_disable_gravity);
+	env.load_module_function("Actor", "enable_collision",			actor_enable_collision);
+	env.load_module_function("Actor", "set_collision_filter",		actor_set_collision_filter);
+	env.load_module_function("Actor", "disable_collision",			actor_disable_collision);
+	env.load_module_function("Actor", "set_kinematic",				actor_set_kinematic);
+	env.load_module_function("Actor", "move",						actor_move);
+	env.load_module_function("Actor", "is_static",					actor_is_static);
+	env.load_module_function("Actor", "is_dynamic",					actor_is_dynamic);
+	env.load_module_function("Actor", "is_kinematic",				actor_is_kinematic);
+	env.load_module_function("Actor", "is_nonkinematic",			actor_is_nonkinematic);
+	env.load_module_function("Actor", "linear_damping",				actor_linear_damping);
+	env.load_module_function("Actor", "set_linear_damping",			actor_set_linear_damping);
+	env.load_module_function("Actor", "angular_damping",			actor_angular_damping);
+	env.load_module_function("Actor", "set_angular_damping",		actor_set_angular_damping);
+	env.load_module_function("Actor", "linear_velocity",			actor_linear_velocity);
+	env.load_module_function("Actor", "set_linear_velocity",		actor_set_linear_velocity);
+	env.load_module_function("Actor", "angular_velocity",			actor_angular_velocity);
+	env.load_module_function("Actor", "set_angular_velocity",		actor_set_angular_velocity);
+	env.load_module_function("Actor", "add_impulse",				actor_add_impulse);
+	env.load_module_function("Actor", "add_impulse_at",				actor_add_impulse_at);
+	env.load_module_function("Actor", "add_torque_impulse",			actor_add_torque_impulse);
+	env.load_module_function("Actor", "push",						actor_push);
+	env.load_module_function("Actor", "push_at",					actor_push_at);
+	env.load_module_function("Actor", "is_sleeping",				actor_is_sleeping);
+	env.load_module_function("Actor", "wake_up",					actor_wake_up);
+	env.load_module_function("Actor", "unit",						actor_unit);
+}
+
+} // namespace crown

+ 193 - 84
engine/physics/Actor.cpp

@@ -38,6 +38,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Vector3.h"
 #include "World.h"
 #include "PhysicsWorld.h"
+#include "Quaternion.h"
+#include "StringUtils.h"
 #include "PxCooking.h"
 #include "PxDefaultStreams.h"
 
@@ -74,6 +76,7 @@ using physx::PxVec3;
 using physx::PxDefaultMemoryOutputStream;
 using physx::PxDefaultMemoryInputData;
 using physx::PxConvexMeshGeometry;
+using physx::PxRigidBodyFlag;
 
 namespace crown
 {
@@ -189,6 +192,11 @@ void Actor::create_objects()
 			}
 		}
 
+		PxFilterData filter_data;
+		filter_data.word0 = config->filter(shape_class.collision_filter).me;
+		filter_data.word1 = config->filter(shape_class.collision_filter).mask;
+		px_shape->setSimulationFilterData(filter_data);
+
 		if (shape_class.trigger)
 		{
 			px_shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
@@ -198,6 +206,10 @@ void Actor::create_objects()
 		shape_index++;
 	}
 
+	if (is_dynamic())
+	{
+		PxRigidBodyExt::updateMassAndInertia(*static_cast<PxRigidBody*>(m_actor), actor.mass);
+	}
 	m_actor->userData = this;
 	scene->addActor(*m_actor);
 }
@@ -213,92 +225,155 @@ void Actor::destroy_objects()
 }
 
 //-----------------------------------------------------------------------------
-void Actor::enable_gravity()
+Vector3 Actor::world_position() const
 {
-	m_actor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, false);
+	const PxTransform tr = m_actor->getGlobalPose();
+	return Vector3(tr.p.x, tr.p.y, tr.p.z);
 }
 
 //-----------------------------------------------------------------------------
-void Actor::disable_gravity()
+Quaternion Actor::world_rotation() const
 {
-	m_actor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+	const PxTransform tr = m_actor->getGlobalPose();
+	return Quaternion(tr.q.x, tr.q.y, tr.q.z, tr.q.w);
 }
 
 //-----------------------------------------------------------------------------
-void Actor::enable_collision()
+Matrix4x4 Actor::world_pose() const
 {
-	// PxFilterData filter_data;
-	// filter_data.word0 = (PxU32) m_group;
-	// filter_data.word1 = (PxU32) m_mask;
+	const PxTransform tr = m_actor->getGlobalPose();
+	return Matrix4x4(Quaternion(tr.q.x, tr.q.y, tr.q.z, tr.q.w), Vector3(tr.p.x, tr.p.y, tr.p.z));
+}
 
-	// const PxU32 num_shapes = m_actor->getNbShapes();
+//-----------------------------------------------------------------------------
+void Actor::teleport_world_position(const Vector3& p)
+{
+	PxTransform tr = m_actor->getGlobalPose();
+	tr.p.x = p.x;
+	tr.p.y = p.y;
+	tr.p.z = p.z;
+	m_actor->setGlobalPose(tr);
+}
 
-	// PxShape** shapes = (PxShape**) default_allocator().allocate((sizeof(PxShape*) * num_shapes));
-	// m_actor->getShapes(shapes, num_shapes);
+//-----------------------------------------------------------------------------
+void Actor::teleport_world_rotation(const Quaternion& r)
+{
+	PxTransform tr = m_actor->getGlobalPose();
+	tr.q.x = r.x;
+	tr.q.y = r.y;
+	tr.q.z = r.z;
+	tr.q.w = r.w;
+	m_actor->setGlobalPose(tr);
+}
 
-	// for(PxU32 i = 0; i < num_shapes; i++)
-	// {
-	// 	PxShape* shape = shapes[i];
-	// 	shape->setSimulationFilterData(filter_data);
-	// }
+//-----------------------------------------------------------------------------
+void Actor::teleport_world_pose(const Matrix4x4& m)
+{
+	const PxVec3 x(m.x().x, m.x().y, m.x().z);
+	const PxVec3 y(m.y().x, m.y().y, m.y().z);
+	const PxVec3 z(m.z().x, m.z().y, m.z().z);
+	const PxVec3 t(m.translation().x, m.translation().y, m.translation().z);
+	m_actor->setGlobalPose(PxTransform(PxMat44(x, y, z, t)));
+}
 
-	// default_allocator().deallocate(shapes);
+//-----------------------------------------------------------------------------
+Vector3 Actor::center_of_mass() const
+{
+	if (is_static())
+		return Vector3(0, 0, 0);
+
+	const PxTransform tr = static_cast<PxRigidBody*>(m_actor)->getCMassLocalPose();
+	return Vector3(tr.p.x, tr.p.y, tr.p.z);
 }
 
 //-----------------------------------------------------------------------------
-void Actor::disable_collision()
+void Actor::enable_gravity()
 {
-	// PxFilterData filter_data;
-	// filter_data.word0 = (PxU32) CollisionGroup::GROUP_0;
-	// filter_data.word1 = (PxU32) CollisionGroup::GROUP_0;
+	m_actor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, false);
+}
 
-	// const PxU32 num_shapes = m_actor->getNbShapes();
+//-----------------------------------------------------------------------------
+void Actor::disable_gravity()
+{
+	m_actor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+}
 
-	// PxShape** shapes = (PxShape**) default_allocator().allocate((sizeof(PxShape*) * num_shapes));
-	// m_actor->getShapes(shapes, num_shapes);
+//-----------------------------------------------------------------------------
+void Actor::enable_collision()
+{
+	// const PxU32 num_shapes = m_actor->getNbShapes();
+	// PxU32 idx = 0;
 
-	// for(PxU32 i = 0; i < num_shapes; i++)
+	// while (idx != num_shapes)
 	// {
-	// 	PxShape* shape = shapes[i];
-	// 	shape->setSimulationFilterData(filter_data);
+	// 	PxShape* shapes[8];
+	// 	const PxU32 written = m_actor->getShapes(shapes, 8, idx);
+
+	// 	for (PxU32 i = 0; i < written; i++)
+	// 	{
+	// 		PxFilterData fdata;
+	// 		fdata.word0 = 0;
+	// 		fdata.word1 = 0;
+	// 		shapes[i]->setSimulationFilterData(fdata);
+	// 	}
+
+	// 	idx += written;
 	// }
+}
 
-	// default_allocator().deallocate(shapes);
+//-----------------------------------------------------------------------------
+void Actor::disable_collision()
+{
 }
 
 //-----------------------------------------------------------------------------
-void Actor::set_kinematic()
+void Actor::set_collision_filter(const char* name)
 {
-	static_cast<PxRigidDynamic*>(m_actor)->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);
+	set_collision_filter(string::murmur2_32(name, string::strlen(name)));
 }
 
 //-----------------------------------------------------------------------------
-void Actor::clear_kinematic()
+void Actor::set_collision_filter(StringId32 filter)
 {
-	static_cast<PxRigidDynamic*>(m_actor)->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, false);
+	const PhysicsCollisionFilter& pcf = m_world.resource()->filter(filter);
+
+	const PxU32 num_shapes = m_actor->getNbShapes();
+	PxU32 idx = 0;
+
+	while (idx != num_shapes)
+	{
+		PxShape* shapes[8];
+		const PxU32 written = m_actor->getShapes(shapes, 8, idx);
 
-	m_scene_graph.set_world_pose(m_node, get_kinematic_pose());
+		for (PxU32 i = 0; i < written; i++)
+		{
+			PxFilterData fdata;
+			fdata.word0 = pcf.me;
+			fdata.word1 = pcf.mask;
+			shapes[i]->setSimulationFilterData(fdata);
+		}
+
+		idx += written;
+	}
 }
 
 //-----------------------------------------------------------------------------
-void Actor::move(const Vector3& pos)
+void Actor::set_kinematic(bool kinematic)
 {
-	CE_ASSERT(is_kinematic(), "Cannot call 'move' method for non-kinematic actor");
+	if (is_static())
+		return;
 
-	PxVec3 position(pos.x, pos.y, pos.z);
-	static_cast<PxRigidDynamic*>(m_actor)->setKinematicTarget(PxTransform(position));
+	static_cast<PxRigidBody*>(m_actor)->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, kinematic);
 }
 
 //-----------------------------------------------------------------------------
-Matrix4x4 Actor::get_kinematic_pose() const
+void Actor::move(const Vector3& pos)
 {
-	PxTransform transform;
-	static_cast<PxRigidDynamic*>(m_actor)->getKinematicTarget(transform);
+	if (!is_kinematic())
+		return;
 
-	Quaternion rot(transform.q.x, transform.q.y, transform.q.z, transform.q.w);
-	Vector3 pos(transform.p.x, transform.p.y, transform.p.z);
-	
-	return Matrix4x4(rot, pos);
+	const PxVec3 position(pos.x, pos.y, pos.z);
+	static_cast<PxRigidDynamic*>(m_actor)->setKinematicTarget(PxTransform(position));
 }
 
 //-----------------------------------------------------------------------------
@@ -316,118 +391,152 @@ bool Actor::is_dynamic() const
 //-----------------------------------------------------------------------------
 bool Actor::is_kinematic() const
 {
-	if (!is_dynamic()) return false;
+	if (!is_dynamic())
+		return false;
+
 	return static_cast<PxRigidDynamic*>(m_actor)->getRigidDynamicFlags() & PxRigidDynamicFlag::eKINEMATIC;
 }
 
+//-----------------------------------------------------------------------------
+bool Actor::is_nonkinematic() const
+{
+	return is_dynamic() && !is_kinematic();
+}
+
 //-----------------------------------------------------------------------------
 float Actor::linear_damping() const
 {
-	return ((PxRigidDynamic*)m_actor)->getLinearDamping();
+	if (is_static())
+		return 0;
+
+	return static_cast<PxRigidDynamic*>(m_actor)->getLinearDamping();
 }
 
 //-----------------------------------------------------------------------------
 void Actor::set_linear_damping(float rate)
 {
-	((PxRigidDynamic*)m_actor)->setLinearDamping(rate);
+	if (is_static())
+		return;
+
+	static_cast<PxRigidDynamic*>(m_actor)->setLinearDamping(rate);
 }
 
 //-----------------------------------------------------------------------------
 float Actor::angular_damping() const
 {
-	return ((PxRigidDynamic*)m_actor)->getAngularDamping();
+	if (is_static())
+		return 0;
+
+	return static_cast<PxRigidDynamic*>(m_actor)->getAngularDamping();
 }
 
 //-----------------------------------------------------------------------------
 void Actor::set_angular_damping(float rate)
 {
-	((PxRigidDynamic*)m_actor)->setAngularDamping(rate);
+	if (is_static())
+		return;
+
+	static_cast<PxRigidDynamic*>(m_actor)->setAngularDamping(rate);
 }
 
 //-----------------------------------------------------------------------------
 Vector3 Actor::linear_velocity() const
 {
-	PxVec3 vel = ((PxRigidBody*)m_actor)->getLinearVelocity();
-	Vector3 velocity(vel.x, vel.y, vel.z);
-	return velocity;
+	if (is_static())
+		return Vector3(0, 0, 0);
+
+	const PxVec3 vel = static_cast<PxRigidBody*>(m_actor)->getLinearVelocity();
+	return Vector3(vel.x, vel.y, vel.z);
 }
 
 //-----------------------------------------------------------------------------
 void Actor::set_linear_velocity(const Vector3& vel)
 {
-	PxVec3 velocity(vel.x, vel.y, vel.z);
-	((PxRigidBody*)m_actor)->setLinearVelocity(velocity);
+	if (!is_nonkinematic())
+		return;
+
+	const PxVec3 velocity(vel.x, vel.y, vel.z);
+	static_cast<PxRigidBody*>(m_actor)->setLinearVelocity(velocity);
 }
 
 //-----------------------------------------------------------------------------
 Vector3 Actor::angular_velocity() const
 {
-	PxVec3 vel = ((PxRigidBody*)m_actor)->getAngularVelocity();
-	Vector3 velocity(vel.x, vel.y, vel.z);
-	return velocity;
+	if (is_static())
+		return Vector3(0, 0, 0);
+
+	const PxVec3 vel = static_cast<PxRigidBody*>(m_actor)->getAngularVelocity();
+	return Vector3(vel.x, vel.y, vel.z);
 }
 
 //-----------------------------------------------------------------------------
 void Actor::set_angular_velocity(const Vector3& vel)
 {
-	PxVec3 velocity(vel.x, vel.y, vel.z);
-	((PxRigidBody*)m_actor)->setAngularVelocity(velocity);
+	if (!is_nonkinematic())
+		return;
+
+	const PxVec3 velocity(vel.x, vel.y, vel.z);
+	static_cast<PxRigidBody*>(m_actor)->setAngularVelocity(velocity);
 }
 
 //-----------------------------------------------------------------------------
 void Actor::add_impulse(const Vector3& impulse)
 {
-	Vector3 p = m_scene_graph.world_pose(m_node).translation();
+	if (!is_nonkinematic())
+		return;
 
-	PxRigidBodyExt::addForceAtPos(*static_cast<PxRigidDynamic*>(m_actor),
-								  PxVec3(impulse.x, impulse.y, impulse.z),
-								  PxVec3(p.x, p.y, p.z),
-								  PxForceMode::eIMPULSE,
-								  true);
+	static_cast<PxRigidDynamic*>(m_actor)->addForce(PxVec3(impulse.x, impulse.y, impulse.z), PxForceMode::eIMPULSE);
 }
 
 //-----------------------------------------------------------------------------
 void Actor::add_impulse_at(const Vector3& impulse, const Vector3& pos)
 {
-	PxRigidBodyExt::addForceAtLocalPos(*static_cast<PxRigidDynamic*>(m_actor),
+	if (!is_nonkinematic())
+		return;
+
+	PxRigidBodyExt::addForceAtPos(*static_cast<PxRigidDynamic*>(m_actor),
 									   PxVec3(impulse.x, impulse.y, impulse.z),
 									   PxVec3(pos.x, pos.y, pos.z),
-									   PxForceMode::eIMPULSE,
-									   true);
+									   PxForceMode::eIMPULSE);
 }
 
 //-----------------------------------------------------------------------------
-void Actor::push(const Vector3& vel, const float mass)
+void Actor::add_torque_impulse(const Vector3& i)
 {
-	// FIXME FIXME FIXME
-	Vector3 p = m_scene_graph.world_pose(m_node).translation();
-
-	Vector3 mq(vel.x * mass, vel.y * mass, vel.z * mass);
-	Vector3 f(mq.x / 0.017, mq.y / 0.017, mq.z / 0.017);
+	if (!is_nonkinematic())
+		return;
 
-	PxRigidBodyExt::addForceAtPos(*static_cast<PxRigidDynamic*>(m_actor),
-								  PxVec3(f.x, f.y, f.z),
-								  PxVec3(p.x, p.y, p.z));
+	static_cast<PxRigidBody*>(m_actor)->addTorque(PxVec3(i.x, i.y, i.z), PxForceMode::eIMPULSE);
 }
 
+//-----------------------------------------------------------------------------
+void Actor::push(const Vector3& vel, float mass)
+{
+	add_impulse(vel * mass);
+}
 
 //-----------------------------------------------------------------------------
-bool Actor::is_sleeping()
+void Actor::push_at(const Vector3& vel, float mass, const Vector3& pos)
 {
-	return ((PxRigidDynamic*)m_actor)->isSleeping();
+	add_impulse_at(vel * mass, pos);
 }
 
 //-----------------------------------------------------------------------------
-void Actor::wake_up()
+bool Actor::is_sleeping()
 {
-	((PxRigidDynamic*)m_actor)->wakeUp();
+	if (is_static())
+		return true;
+
+	return static_cast<PxRigidDynamic*>(m_actor)->isSleeping();
 }
 
 //-----------------------------------------------------------------------------
-StringId32 Actor::name()
+void Actor::wake_up()
 {
-	const PhysicsActor& a = m_resource->actor(m_index);
-	return a.name;
+	if (is_static())
+		return;
+
+	static_cast<PxRigidDynamic*>(m_actor)->wakeUp();
 }
 
 //-----------------------------------------------------------------------------

+ 61 - 45
engine/physics/Actor.h

@@ -59,6 +59,27 @@ struct Actor
 	Actor(PhysicsWorld& pw, const PhysicsResource* res, uint32_t actor_idx, SceneGraph& sg, int32_t node, UnitId unit_id);
 	~Actor();
 
+	/// Sets the world position of the actor.
+	Vector3 world_position() const;
+
+	/// Sets the world rotation of the actor.
+	Quaternion world_rotation() const;
+
+	/// Sets the world pose of the actor.
+	Matrix4x4 world_pose() const;
+
+	/// Teleports the actor to the given world position.
+	void teleport_world_position(const Vector3& p);
+
+	/// Teleports the actor to the given world rotation.
+	void teleport_world_rotation(const Quaternion& r);
+
+	/// Teleports the actor to the given world pose.
+	void teleport_world_pose(const Matrix4x4& m);
+
+	/// Returns the center of mass of the actor.
+	Vector3 center_of_mass() const;
+
 	/// Makes the actor subject to gravity
 	void enable_gravity();
 
@@ -68,86 +89,82 @@ struct Actor
 	void enable_collision();
 	void disable_collision();
 
-	/// Makes the actor kinematic (keyframed)
-	/// @note
-	/// Works only for dynamic actors
-	void set_kinematic();
+	/// Sets the collision filter of the actor.
+	void set_collision_filter(const char* filter);
+	void set_collision_filter(StringId32 filter);
 
-	/// Makes the actor dynamic
-	/// @note
-	/// Works only for kinematic actors
-	void clear_kinematic();
+	/// Sets whether the actor is kinematic or not.
+	/// @note This call has no effect on static actors.
+	void set_kinematic(bool kinematic);
 
 	/// Moves the actor to @a pos
-	/// @note
-	/// Works only for kinematic actors
+	/// @note This call only affects nonkinematic actors.
 	void move(const Vector3& pos);
 
-	/// Returns whether the actor is static (i.e. immovable).
+	/// Returns whether the actor is static.
 	bool is_static() const;
 
-	/// Returns whether the actor is dynamic (i.e. driven dy physics).
+	/// Returns whether the actor is dynamic.
 	bool is_dynamic() const;
 
-	/// Returns whether the actor is kinematic (i.e. driven by the user).
+	/// Returns whether the actor is kinematic (keyframed).
 	bool is_kinematic() const;
 
-	/// Returns the rate at which rigid bodies dissipate linear momentum
+	/// Returns whether the actor is nonkinematic (i.e. dynamic and not kinematic).
+	bool is_nonkinematic() const;
+
+	/// Returns the linear damping of the actor.
 	float linear_damping() const;
 
-	/// Sets the rate at which rigid bodies dissipate linear momentum
+	/// Sets the linear damping of the actor.
 	void set_linear_damping(float rate);
 
-	/// Returns the rate at which rigid bodies dissipate angular momentum
+	/// Returns the angular damping of the actor.
 	float angular_damping() const;
 
-	/// Sets the rate at which rigid bodies dissipate angular momentum
+	/// Sets the angular damping of the actor.
 	void set_angular_damping(float rate);
  
-	/// Returns linear velocity of the actor
-	/// @note
-	/// If actor is sleeping, linear velocity must be 0
+	/// Returns the linear velocity of the actor.
 	Vector3 linear_velocity() const;
 
-	/// Sets linear velocity of the actor
-	/// @note
-	/// If actor is sleeping, this will wake it up
+	/// Sets the linear velocity of the actor.
+	/// @note This call only affects nonkinematic actors.
 	void set_linear_velocity(const Vector3& vel);
 
-	/// Returns angular velocity of the actor
-	/// @note
-	/// If actor is sleeping, angular velocity must be 0
+	/// Returns the angular velocity of the actor.
 	Vector3 angular_velocity() const;
 
-	/// Sets angular velocity of the actor
-	/// @note
-	/// If actor is sleeping, this will wake it up
+	/// Sets the angular velocity of the actor.
+	/// @note This call only affects nonkinematic actors.
 	void set_angular_velocity(const Vector3& vel);
 
-	/// Applies a force (or impulse) defined in the global coordinate frame, acting at a particular point in global coordinates, to the actor.
-	/// @note
-	/// If the force does not act along the center of mass of the actor, this will also add the corresponding torque.
-	/// Because forces are reset at the end of every timestep, you can maintain a total external force on an object by calling this once every frame.
+	/// Adds a linear impulse (acting along the center of mass) to the actor.
+	/// @note This call only affects nonkinematic actors.
 	void add_impulse(const Vector3& impulse);
 
-	/// Applies a force (or impulse) defined in the global coordinate frame, acting at a particular point in local coordinates, to the actor.
-	/// @note
-	/// If the force does not act along the center of mass of the actor, this will also add the corresponding torque.
-	/// Because forces are reset at the end of every timestep, you can maintain a total external force on an object by calling this once every frame. 
+	/// Adds a linear impulse (acting along the world position @a pos) to the actor.
+	/// @note This call only affects nonkinematic actors.
 	void add_impulse_at(const Vector3& impulse, const Vector3& pos);
 
-	/// Applies a force, evaluated by actor's @a mass and @a velocity that will be achieved, to the actor
-	void push(const Vector3& vel, const float mass);
+	/// Adds a torque impulse to the actor.
+	void add_torque_impulse(const Vector3& i);
+
+	/// Pushes the actor as if it was hit by a point object with the given @a mass
+	/// travelling at the given @a velocity.
+	/// @note This call only affects nonkinematic actors.
+	void push(const Vector3& vel, float mass);
 
-	/// Returns true if tha actor is sleeping, false otherwise
+	/// Like push() but applies the force at the world position @a pos.
+	/// @note This call only affects nonkinematic actors.
+	void push_at(const Vector3& vel, float mass, const Vector3& pos);
+
+	/// Returns whether the actor is sleeping.
 	bool is_sleeping();
 
-	/// Forces the actor to wake up
+	/// Wakes the actor up.
 	void wake_up();
 
-	/// Returns actor's name
-	StringId32 name();
-
 	/// Returns the unit that owns the actor.
 	Unit* unit();
 
@@ -159,7 +176,6 @@ private:
 	void destroy_objects();
 
 	void update(const Matrix4x4& pose);
-	Matrix4x4 get_kinematic_pose() const;
 
 public: