194 lines
4.5 KiB
C++
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;
|
|
}
|
|
|