|
@@ -37,12 +37,16 @@ void BodySW::_update_inertia() {
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-void BodySW::_update_inertia_tensor() {
|
|
|
-
|
|
|
- Matrix3 tb = get_transform().basis;
|
|
|
+void BodySW::_update_transform_dependant() {
|
|
|
+
|
|
|
+ center_of_mass = get_transform().basis.xform(center_of_mass_local);
|
|
|
+ principal_inertia_axes = get_transform().basis * principal_inertia_axes_local;
|
|
|
+
|
|
|
+ // update inertia tensor
|
|
|
+ Matrix3 tb = principal_inertia_axes;
|
|
|
+ Matrix3 tbt = tb.transposed();
|
|
|
tb.scale(_inv_inertia);
|
|
|
- _inv_inertia_tensor = tb * get_transform().basis.transposed();
|
|
|
+ _inv_inertia_tensor = tb * tbt;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -54,33 +58,56 @@ void BodySW::update_inertias() {
|
|
|
|
|
|
case PhysicsServer::BODY_MODE_RIGID: {
|
|
|
|
|
|
- //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
|
|
|
+ //update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet)
|
|
|
float total_area=0;
|
|
|
|
|
|
for (int i=0;i<get_shape_count();i++) {
|
|
|
|
|
|
- total_area+=get_shape_aabb(i).get_area();
|
|
|
+ total_area+=get_shape_area(i);
|
|
|
}
|
|
|
|
|
|
- Vector3 _inertia;
|
|
|
+ // We have to recompute the center of mass
|
|
|
+ center_of_mass_local.zero();
|
|
|
+
|
|
|
+ for (int i=0; i<get_shape_count(); i++) {
|
|
|
+ float area=get_shape_area(i);
|
|
|
+
|
|
|
+ float mass = area * this->mass / total_area;
|
|
|
+
|
|
|
+ // NOTE: we assume that the shape origin is also its center of mass
|
|
|
+ center_of_mass_local += mass * get_shape_transform(i).origin;
|
|
|
+ }
|
|
|
|
|
|
+ center_of_mass_local /= mass;
|
|
|
+
|
|
|
+ // Recompute the inertia tensor
|
|
|
+ Matrix3 inertia_tensor;
|
|
|
+ inertia_tensor.set_zero();
|
|
|
|
|
|
for (int i=0;i<get_shape_count();i++) {
|
|
|
|
|
|
const ShapeSW* shape=get_shape(i);
|
|
|
|
|
|
- float area=get_shape_aabb(i).get_area();
|
|
|
+ float area=get_shape_area(i);
|
|
|
|
|
|
float mass = area * this->mass / total_area;
|
|
|
|
|
|
- _inertia += shape->get_moment_of_inertia(mass) + mass * get_shape_transform(i).get_origin();
|
|
|
+ Matrix3 shape_inertia_tensor=shape->get_moment_of_inertia(mass).to_diagonal_matrix();
|
|
|
+ Transform shape_transform=get_shape_transform(i);
|
|
|
+ Matrix3 shape_basis = shape_transform.basis.orthonormalized();
|
|
|
+
|
|
|
+ // NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor!
|
|
|
+ shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed();
|
|
|
+
|
|
|
+ Vector3 shape_origin = shape_transform.origin - center_of_mass_local;
|
|
|
+ inertia_tensor += shape_inertia_tensor + (Matrix3()*shape_origin.dot(shape_origin)-shape_origin.outer(shape_origin))*mass;
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
|
- if (_inertia!=Vector3())
|
|
|
- _inv_inertia=_inertia.inverse();
|
|
|
- else
|
|
|
- _inv_inertia=Vector3();
|
|
|
+ // Compute the principal axes of inertia
|
|
|
+ principal_inertia_axes_local = inertia_tensor.diagonalize().transposed();
|
|
|
+ _inv_inertia = inertia_tensor.get_main_diagonal().inverse();
|
|
|
|
|
|
if (mass)
|
|
|
_inv_mass=1.0/mass;
|
|
@@ -92,20 +119,21 @@ void BodySW::update_inertias() {
|
|
|
case PhysicsServer::BODY_MODE_KINEMATIC:
|
|
|
case PhysicsServer::BODY_MODE_STATIC: {
|
|
|
|
|
|
- _inv_inertia=Vector3();
|
|
|
+ _inv_inertia_tensor.set_zero();
|
|
|
_inv_mass=0;
|
|
|
} break;
|
|
|
case PhysicsServer::BODY_MODE_CHARACTER: {
|
|
|
|
|
|
- _inv_inertia=Vector3();
|
|
|
+ _inv_inertia_tensor.set_zero();
|
|
|
_inv_mass=1.0/mass;
|
|
|
|
|
|
} break;
|
|
|
}
|
|
|
- _update_inertia_tensor();
|
|
|
+
|
|
|
|
|
|
//_update_shapes();
|
|
|
|
|
|
+ _update_transform_dependant();
|
|
|
}
|
|
|
|
|
|
|
|
@@ -582,6 +610,8 @@ void BodySW::integrate_velocities(real_t p_step) {
|
|
|
if (ang_vel!=0.0) {
|
|
|
Vector3 ang_vel_axis = total_angular_velocity / ang_vel;
|
|
|
Matrix3 rot( ang_vel_axis, -ang_vel*p_step );
|
|
|
+ Matrix3 identity3(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
|
|
+ transform.origin += ((identity3 - rot) * transform.basis).xform(center_of_mass_local);
|
|
|
transform.basis = rot * transform.basis;
|
|
|
transform.orthonormalize();
|
|
|
}
|
|
@@ -598,7 +628,7 @@ void BodySW::integrate_velocities(real_t p_step) {
|
|
|
_set_transform(transform);
|
|
|
_set_inv_transform(get_transform().inverse());
|
|
|
|
|
|
- _update_inertia_tensor();
|
|
|
+ _update_transform_dependant();
|
|
|
|
|
|
//if (fi_callback) {
|
|
|
|