Lephisto/src/dynamic_body.cpp

194 lines
4.5 KiB
C++

#include "libs.h"
#include "dynamic_body.h"
#include "space.h"
#include "frame.h"
#include "serializer.h"
DynamicBody::DynamicBody(void) : ModelBody() {
m_flags = Body::FLAG_CAN_MOVE_FRAME;
m_orient = matrix4x4d::Identity();
m_force = vector3d(0.0);
m_torque = vector3d(0.0);
m_vel = vector3d(0.0);
m_angVel = vector3d(0.0);
m_mass = 1;
m_angInertia = 1;
m_massRadius = 1;
m_enabled = true;
}
void DynamicBody::SetForce(const vector3d f) {
m_force = f;
}
void DynamicBody::AddForce(const vector3d f) {
m_force += f;
}
void DynamicBody::AddForceAtPos(const vector3d force, const vector3d pos) {
assert(0);
/*
dBodyAddForceAtPos(m_body, force.x, force.y, force.z,
pos.x, pos.y, pos.z);
*/
}
void DynamicBody::AddRelForce(const vector3d f) {
m_force += m_orient.ApplyRotationOnly(f);
}
void DynamicBody::AddRelTorque(const vector3d t) {
m_torque += m_orient.ApplyRotationOnly(t);
}
void DynamicBody::Save(void) {
using namespace Serializer::Write;
ModelBody::Save();
for(int i = 0; i < 16; i++) wr_double(m_orient[i]);
wr_vector3d(m_force);
wr_vector3d(m_torque);
wr_vector3d(m_vel);
wr_vector3d(m_angVel);
wr_double(m_mass);
wr_double(m_massRadius);
wr_double(m_angInertia);
wr_bool(m_enabled);
}
void DynamicBody::Load(void) {
using namespace Serializer::Read;
ModelBody::Load();
for(int i = 0; i < 16; i++) m_orient[i] = rd_double();
m_force = rd_vector3d();
m_torque = rd_vector3d();
m_vel = rd_vector3d();
m_angVel = rd_vector3d();
m_mass = rd_double();
m_massRadius = rd_double();
m_angInertia = rd_double();
m_enabled = rd_bool();
}
void DynamicBody::SetTorque(const vector3d t) {
m_torque = t;
}
void DynamicBody::SetMass(double mass) {
m_mass = mass;
/* This is solid sphere mass distribution yo'! */
m_angInertia = (2/5.0)*m_mass*m_massRadius*m_massRadius;
printf("radius %f, angInert %f\n", m_massRadius, m_angInertia);
}
void DynamicBody::SetPosition(vector3d p) {
m_orient[12] = p.x;
m_orient[13] = p.y;
m_orient[14] = p.z;
ModelBody::SetPosition(p);
}
vector3d DynamicBody::GetPosition(void) const {
return vector3d(m_orient[12], m_orient[13], m_orient[14]);
}
void DynamicBody::TimeStepUpdate(const float timeStep) {
/*
* XXX Remember this is used to step back also in the collision code.
* very silly btw.
*/
if(m_enabled) {
m_vel += timeStep * m_force * (1.0/m_mass);
m_angVel += timeStep * m_torque * (1.0 / m_angInertia);
vector3d pos = GetPosition();
/* Applying angular velocity :/ */
{
double len = m_angVel.Length();
if(len != 0) {
vector3d rotAxis = m_angVel * (1.0 / len);
matrix4x4d rotMatrix = matrix4x4d::RotateMatrix(len * timeStep,
rotAxis.x, rotAxis.y, rotAxis.z);
m_orient = rotMatrix * m_orient;
}
}
pos += m_vel * timeStep;
m_orient[12] = pos.x;
m_orient[13] = pos.y;
m_orient[14] = pos.z;
TriMeshUpdateLastPos(m_orient);
m_force = vector3d(0.0);
m_torque = vector3d(0.0);
}
}
void DynamicBody::Enable(void) {
ModelBody::Enable();
m_enabled = true;
}
void DynamicBody::Disable(void) {
ModelBody::Disable();
m_enabled = false;
}
void DynamicBody::SetRotMatrix(const matrix4x4d& r) {
vector3d pos = GetPosition();
m_orient = r;
SetPosition(pos);
}
void DynamicBody::GetRotMatrix(matrix4x4d& m) {
m = m_orient;
m[12] = 0;
m[13] = 0;
m[14] = 0;
}
void DynamicBody::SetMassDistributionFromCollMesh(const CollMesh* m) {
/*
* XXX: This is silly. the radius of mass distribution should be
* defined on the model, not cooked up in some stupid way.
*/
vector3d min = vector3d(FLT_MAX);
vector3d max = vector3d(-FLT_MAX);
for(int i = 0; i < 3*m->nv; i += 3) {
min.x = MIN(m->pVertex[i], min.x);
min.y = MIN(m->pVertex[i+1], min.y);
min.z = MIN(m->pVertex[i+2], min.z);
max.x = MAX(m->pVertex[i], max.x);
max.y = MAX(m->pVertex[i+1], max.y);
max.z = MAX(m->pVertex[i+2], max.z);
}
const vector3d size = max-min;
m_massRadius = (size.x + size.y + size.z) * 0.333;
SetMass(m_mass);
}
vector3d DynamicBody::GetAngularMomentum(void) {
return m_angInertia * m_angVel;
}
DynamicBody::~DynamicBody(void) {
}
vector3d DynamicBody::GetAngVelocity(void) {
return m_angVel;
}
vector3d DynamicBody::GetVelocity(void) {
return m_vel;
}
void DynamicBody::SetVelocity(vector3d v) {
m_vel = v;
}
void DynamicBody::SetAngVelocity(vector3d v) {
m_angVel = v;
}