1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/*
* SOLID - Software Library for Interference Detection
*
* Copyright (C) 2001-2003 Dtecta. All rights reserved.
*
* This library may be distributed under the terms of the Q Public License
* (QPL) as defined by Trolltech AS of Norway and appearing in the file
* LICENSE.QPL included in the packaging of this file.
*
* This library may be distributed and/or modified under the terms of the
* GNU General Public License (GPL) version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Commercial use or any other use of this library not covered by either
* the QPL or the GPL requires an additional license from Dtecta.
* Please contact info@dtecta.com for enquiries about the terms of commercial
* use of this library.
*/
#include "RigidBody.h"
static MT_Scalar ContactThreshold = -10.0f;
void RigidBody::setGravity(const MT_Vector3& acceleration)
{
if (m_inv_mass != 0.0f)
{
m_gravity = acceleration * (1.0f / m_inv_mass);
}
}
void RigidBody::setDamping(MT_Scalar lin_damping, MT_Scalar ang_damping)
{
m_lin_damping = GEN_clamped(1.0f - lin_damping, 0.0f, 1.0f);
m_ang_damping = GEN_clamped(1.0f - ang_damping, 0.0f, 1.0f);
}
void RigidBody::reset(const MT_Transform& xform)
{
Dynamic::reset(xform);
}
void RigidBody::applyForces(MT_Scalar step)
{
applyCentralForce(m_gravity);
#if defined (__sun) || defined(__sun__) || defined(__sparc) || defined(__sparc__) || defined (__APPLE)
m_lin_vel *= pow(m_lin_damping, step);
m_ang_vel *= pow(m_ang_damping, step);
#else
m_lin_vel *= powf(m_lin_damping, step);
m_ang_vel *= powf(m_ang_damping, step);
#endif
}
void RigidBody::proceed(MT_Scalar step)
{
m_prev_xform = m_xform;
m_prev_orn = m_orn;
Dynamic::proceed(step);
}
void RigidBody::backup()
{
m_xform = m_prev_xform;
m_orn = m_prev_orn;
updateInertiaTensor();
}
inline MT_Scalar restitutionCurve(MT_Scalar rel_vel, MT_Scalar restitution)
{
return restitution * GEN_min(1.0f, rel_vel / ContactThreshold);
}
void RigidBody::resolveCollision(const MT_Vector3& pos,
MT_Scalar depth, const MT_Vector3& normal,
MT_Scalar restitution, MT_Scalar friction)
{
MT_Vector3 rel_pos = pos - getPosition();
MT_Vector3 vel = getVelocity(rel_pos);
MT_Scalar rel_vel = normal.dot(vel);
if (rel_vel < -MT_EPSILON)
{
MT_Vector3 temp = getInvInertiaTensor() * rel_pos.cross(normal);
MT_Scalar rest = restitutionCurve(rel_vel, restitution);
MT_Scalar impulse = -(1.0f + rest) * rel_vel /
(getInvMass() + normal.dot(temp.cross(rel_pos)));
applyImpulse(normal * impulse, rel_pos);
MT_Vector3 lat_vel = vel - normal * rel_vel;
MT_Scalar lat_rel_vel = lat_vel.length();
if (lat_rel_vel > 0.0f)
{
lat_vel /= lat_rel_vel;
temp = getInvInertiaTensor() * rel_pos.cross(lat_vel);
MT_Scalar friction_impulse = -lat_rel_vel /
(getInvMass() + lat_vel.dot(temp.cross(rel_pos)));
GEN_set_min(friction_impulse, impulse * friction);
applyImpulse(lat_vel * friction_impulse, rel_pos);
}
}
}
void resolveCollision(RigidBody& body1, const MT_Vector3& pos1,
RigidBody& body2, const MT_Vector3& pos2,
MT_Scalar depth, const MT_Vector3& normal, MT_Scalar restitution)
{
MT_Vector3 rel_pos1 = pos1 - body1.getPosition();
MT_Vector3 rel_pos2 = pos2 - body2.getPosition();
MT_Scalar rel_vel = normal.dot(body1.getVelocity(rel_pos1) - body2.getVelocity(rel_pos2));
if (rel_vel < -MT_EPSILON)
{
MT_Vector3 temp1 = body1.getInvInertiaTensor() * rel_pos1.cross(normal);
MT_Vector3 temp2 = body2.getInvInertiaTensor() * rel_pos2.cross(normal);
MT_Scalar rest = restitutionCurve(rel_vel, restitution);
MT_Scalar impulse = -(1.0f + rest) * rel_vel /
(body1.getInvMass() + body2.getInvMass() + normal.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2)));
MT_Vector3 impulse_vector = normal * impulse;
body1.applyImpulse(impulse_vector, rel_pos1);
body2.applyImpulse(-impulse_vector, rel_pos2);
}
}
|