File: RigidBody.cpp

package info (click to toggle)
blender 2.42a-7
  • links: PTS
  • area: main
  • in suites: etch-m68k
  • size: 60,700 kB
  • ctags: 83,393
  • sloc: ansic: 576,763; cpp: 187,760; python: 48,472; sh: 15,785; makefile: 4,298; perl: 2,082; asm: 1,471; java: 8
file content (133 lines) | stat: -rwxr-xr-x 4,213 bytes parent folder | download | duplicates (5)
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);
	}
}