Skip to content

Commit 08afc52

Browse files
committed
Added rudimentary support for rigid body manipulation
1 parent 7d164cc commit 08afc52

14 files changed

+360
-49
lines changed

Camera.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,21 @@ int Camera::getMouseButton()
230230
{
231231
return mb;
232232
}
233+
234+
glm::mat4 Camera::getModelview()
235+
{
236+
if (mode == CAM_ORBIT)
237+
{
238+
return glm::lookAt(vec3(loc), vec3(focus), vec3(up));
239+
}
240+
else if (mode == CAM_FPS)
241+
{
242+
return glm::lookAt(vec3(loc), vec3(focus+dir), vec3(up));
243+
}
244+
}
245+
246+
glm::mat4 Camera::getProjection()
247+
{
248+
float rad = 60.0*M_PI/180;
249+
gluPerspective(rad, (float)screenWidth/(float)screenHeight, near, far);
250+
}

Camera.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "helpers.hpp"
1515
#include "Transform.hpp"
1616
#include <glm/glm.hpp>
17+
#include <glm/gtc/matrix_transform.hpp>
1718

1819
class Camera
1920
{
@@ -50,5 +51,7 @@ class Camera
5051
void mov_sideways(float amount);
5152
void changeSpeed(float amount);
5253
int getMouseButton();
54+
glm::mat4 getModelview();
55+
glm::mat4 getProjection();
5356
};
5457
#endif

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
UNAME := $(shell uname)
22

3-
headers = helpers.hpp Camera.hpp callbacks.hpp ODE.hpp display.hpp globals.hpp Transform.hpp
4-
sources = main.cpp helpers.cpp Camera.cpp callbacks.cpp ODE.cpp display.cpp globals.cpp Transform.cpp
3+
headers = helpers.hpp Camera.hpp callbacks.hpp ODE.hpp display.hpp globals.hpp Transform.hpp RigidBody.hpp
4+
sources = main.cpp helpers.cpp Camera.cpp callbacks.cpp ODE.cpp display.cpp globals.cpp Transform.cpp RigidBody.cpp
55

66
CPPFLAGS = -std=c++11 -Wno-deprecated -lm
77

ODE.cpp

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "ODE.hpp"
22

3-
vector<float> EulerMethod(vector<float> y0, float t0, float t_end,
3+
/*
4+
// solve a vector of differential equations
5+
//vector<float> EulerMethod(vector<float> y0, float t0, float t_end,
46
float dt, dydt_func dydt)
57
{
68
vector<float> y_end;
@@ -10,7 +12,6 @@ vector<float> EulerMethod(vector<float> y0, float t0, float t_end,
1012
{
1113
throw "Bad arguments for t0 and t_end. Make sure that t0 < t_end.";
1214
}
13-
1415
if (dt <=0)
1516
{
1617
throw "Bad argument for dt: Make sure that dt > 0.";
@@ -36,3 +37,85 @@ vector<float> EulerMethod(vector<float> y0, float t0, float t_end,
3637
3738
return y_end;
3839
}
40+
*/
41+
42+
/*
43+
// solve scalar differential equation
44+
float EulerMethod(float y0, float t0, float t_end,
45+
float dt, dydt_func dydt)
46+
{
47+
// verify that t0 < t_end
48+
if (t0 >= t_end)
49+
{
50+
throw "Bad arguments for t0 and t_end. Make sure that t0 < t_end.";
51+
}
52+
53+
if (dt <=0)
54+
{
55+
throw "Bad argument for dt: Make sure that dt > 0.";
56+
}
57+
58+
// solve ODE using Euler's method
59+
float t = t0;
60+
float y = y0;
61+
62+
while (t < t_end)
63+
{
64+
// step
65+
y += dydt(t, y)*dt;
66+
t += dt;
67+
}
68+
69+
return y;
70+
}
71+
*/
72+
73+
// solve 3x3 matrix differential equation
74+
mat3 EulerMethod(mat3 M0, float t0, float t_end, float dt,
75+
mat3 dMdt)
76+
{
77+
// verify that t0 < t_end
78+
if (t0 >= t_end)
79+
{
80+
throw "Bad arguments for t0 and t_end. Make sure that t0 < t_end.";
81+
}
82+
if (dt <=0)
83+
{
84+
throw "Bad argument for dt: Make sure that dt > 0.";
85+
}
86+
87+
float t = t0;
88+
mat3 M = M0;
89+
90+
while (t < t_end)
91+
{
92+
M += dMdt*dt;
93+
t += dt;
94+
}
95+
return M;
96+
}
97+
98+
// solve vec3 differential equation
99+
vec3 EulerMethod(vec3 V0, float t0, float t_end, float dt,
100+
vec3 dV3dt)
101+
{
102+
// verify that t0 < t_end
103+
if (t0 >= t_end)
104+
{
105+
throw "Bad arguments for t0 and t_end. Make sure that t0 < t_end.";
106+
}
107+
if (dt <=0)
108+
{
109+
throw "Bad argument for dt: Make sure that dt > 0.";
110+
}
111+
112+
float t = t0;
113+
vec3 V = V0;
114+
115+
while (t < t_end)
116+
{
117+
V += dV3dt*dt;
118+
t += dt;
119+
}
120+
return V;
121+
}

ODE.hpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
#include <vector>
2+
#include <glm/glm.hpp>
23

34
using namespace std;
5+
using namespace glm;
46

5-
typedef float (*dydt_func)(float t, float y);
7+
// solve ODE for a vector of equations
8+
//typedef float (*dydt_func)(float t, float y);
9+
//vector<float> EulerMethod(vector<float> y0, float t0, float t_end,
10+
// float dt, dydt_func dydt);
611

7-
vector<float> EulerMethod(vector<float> y0, float t0, float t_end,
8-
float dt, dydt_func dydt);
12+
// solve ODE for a single equation
13+
//float EulerMethod(float y0, float t0, float t_end,
14+
// float dt, dydt_func dydt);
15+
16+
// solve ODE for a 3x3 matrix value equation
17+
// These functions do not use callback function for evaluating
18+
// the time derivative because non-static member functions cannot
19+
// be used as callback => RigidBody's member functions could not be
20+
// passed to this and therefore have to be evaluated and the
21+
// result passed to these functions.
22+
mat3 EulerMethod(mat3 M0, float t0, float t_end,
23+
float dt, mat3 dMdt);
24+
vec3 EulerMethod(vec3 V0, float t0, float t_end,
25+
float dt, vec3 dV3dt);

RigidBody.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include "RigidBody.hpp"
2+
3+
RigidBody::RigidBody()
4+
{
5+
mass = 1.0;
6+
Ibody = (mass/12.0f)*mat3(1.0f);
7+
Ibodyinv = inverse(Ibody);
8+
9+
x = vec3(0.0f, 0.0f, 2.0f);
10+
R = mat3(1.0f);
11+
P = vec3(0.0f);
12+
L = vec3(0.0f, 0.0f, 0.1f);
13+
14+
Iinv = R*Ibodyinv*transpose(R);
15+
v = P/mass;
16+
omega = Iinv * L;
17+
18+
force = vec3(0.0f, 0.0f, 0.0f);
19+
torque = vec3(0.0f);
20+
21+
size = 0.5f;
22+
}
23+
24+
// simulate one step forward
25+
// the time step in the argument in in simulation time
26+
void RigidBody::sim_step(float dt)
27+
{
28+
v = P/mass;
29+
omega = Iinv * L;
30+
31+
// the time step used by the solver is different (preferably smaller)
32+
// than the time step of the simulation
33+
// forces are constant only (for now) so time is assumed 0 to dt for every update
34+
// vec3 EulerMethod(vec3 V0, float t0, float t_end, float dt, dV3dt_func dV3dt)
35+
x = EulerMethod(x, 0, dt, 0.01f, dxdt(0, x));
36+
R = EulerMethod(R, 0, dt, 0.01f, dRdt(0, R));
37+
38+
// normalise vectors in R and make sure that they are orthogonal
39+
vec3 w = normalize(R[2]);
40+
vec3 u = normalize(cross(R[1], w));
41+
vec3 v = cross(w, u);
42+
R = mat3(u, v, w);
43+
44+
45+
P = EulerMethod(P, 0, dt, 0.01f, force);
46+
L = EulerMethod(L, 0, dt, 0.01f, torque);
47+
48+
}
49+
50+
mat3 RigidBody::dRdt(float t, mat3 R)
51+
{
52+
// dual defined in helpers.hpp
53+
return dual(omega)*R;
54+
}
55+
56+
vec3 RigidBody::dxdt(float t, vec3 V)
57+
{
58+
return v;
59+
};
60+
61+
State RigidBody::getState()
62+
{
63+
State s;
64+
s.x = x;
65+
s.R = R;
66+
s.P = P;
67+
s.L = L;
68+
return s;
69+
}
70+
71+
mat4 RigidBody::getTransformation()
72+
{
73+
mat4 S = Transform::scale(size, size, size/2.0f);
74+
mat4 T = Transform::translate(x);
75+
mat4 Rot = Transform::rotate(R);
76+
return T*Rot*S;
77+
}

RigidBody.hpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#ifndef RIGIDBODY
2+
#define RIGIDBODY
3+
4+
#include "Transform.hpp"
5+
#include <glm/glm.hpp>
6+
#include "ODE.hpp"
7+
#include "helpers.hpp"
8+
9+
using namespace glm;
10+
11+
typedef struct
12+
{
13+
vec3 x;
14+
mat3 R;
15+
vec3 P;
16+
vec3 L;
17+
} State;
18+
19+
class RigidBody
20+
{
21+
private:
22+
// constants
23+
float mass;
24+
mat3 Ibody;
25+
mat3 Ibodyinv;
26+
27+
// state variables
28+
vec3 x; // displacement of CM from origin
29+
mat3 R; // Orientation
30+
vec3 P; // Linear momentum
31+
vec3 L; // Angular momentum
32+
33+
// derived quantities
34+
mat3 Iinv;
35+
vec3 v; // linear velocity
36+
vec3 omega; // angular velocity
37+
38+
vec3 force;
39+
vec3 torque;
40+
41+
// for drawing (assuming rigid body is a cube)
42+
float size;
43+
44+
public:
45+
RigidBody();
46+
void sim_step(float dt); // simulate one step forward
47+
mat3 dRdt(float t, mat3 R);
48+
vec3 dxdt(float t, vec3 M);
49+
State getState();
50+
mat4 getTransformation(); // returns the transformation matrix from origin
51+
};
52+
53+
#endif

Transform.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
#include "Transform.hpp"
22

33
// Rotate vector about axis by an angle rad
4-
glm::mat4 Transform::rotate(glm::vec3 axis, float rad)
4+
mat4 Transform::rotate(vec3 axis, float rad)
55
{
66
// normalise axis
7-
axis = glm::normalize(axis);
7+
axis = normalize(axis);
88

99
// declare relevant matrices
10-
glm::mat3 I = glm::mat3(1.0);
11-
glm::mat3 A_dual = glm::mat3(0, axis.z, -axis.y, -axis.z, 0, axis.x, axis.y, -axis.x, 0);
10+
mat3 I = mat3(1.0);
11+
mat3 A_dual = mat3(0, axis.z, -axis.y, -axis.z, 0, axis.x, axis.y, -axis.x, 0);
1212

13-
glm::mat3 R3 = I*cosf(rad) + glm::outerProduct(axis, axis)*(1-cosf(rad)) + A_dual*sinf(rad);
14-
glm::mat4 R4 = glm::mat4(
13+
mat3 R3 = I*cosf(rad) + outerProduct(axis, axis)*(1-cosf(rad)) + A_dual*sinf(rad);
14+
mat4 R4 = mat4(
1515
R3[0].x, R3[0].y, R3[0].z, 0.0,
1616
R3[1].x, R3[1].y, R3[1].z, 0.0,
1717
R3[2].x, R3[2].y, R3[2].z, 0.0,
@@ -20,6 +20,15 @@ glm::mat4 Transform::rotate(glm::vec3 axis, float rad)
2020
return R4;
2121
}
2222

23+
mat4 Transform::rotate(mat3 R)
24+
{
25+
return mat4(
26+
R[0].x, R[0].y, R[0].z, 0.0f,
27+
R[1].x, R[1].y, R[1].z, 0.0f,
28+
R[2].x, R[2].y, R[2].z, 0.0f,
29+
0.0f, 0.0f, 0.0f, 1.0f);
30+
}
31+
2332
// Treat the xyz component of vec3 amount as scale factors
2433
mat4 Transform::scale(vec3 amount)
2534
{

Transform.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using namespace glm;
88
namespace Transform
99
{
1010
mat4 rotate (vec3 axis, float rad);
11+
mat4 rotate (mat3 R);
1112
mat4 scale (vec3 amount);
1213
mat4 scale (float sx, float sy, float sz);
1314
mat4 translate(vec3 s);

0 commit comments

Comments
 (0)