aboutsummaryrefslogtreecommitdiff
path: root/Spear/Physics/Rigid.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Spear/Physics/Rigid.hs')
-rw-r--r--Spear/Physics/Rigid.hs122
1 files changed, 122 insertions, 0 deletions
diff --git a/Spear/Physics/Rigid.hs b/Spear/Physics/Rigid.hs
new file mode 100644
index 0000000..b9c84d2
--- /dev/null
+++ b/Spear/Physics/Rigid.hs
@@ -0,0 +1,122 @@
1module Spear.Physics.Rigid
2(
3 module Spear.Physics.Types
4, RigidBody(..)
5, rigidBody
6, update
7)
8where
9
10
11import qualified Spear.Math.Matrix4 as M4
12import Spear.Math.Spatial
13import Spear.Math.Vector3 as V3
14import Spear.Physics.Types
15
16import Data.List (foldl')
17import Control.Monad.State
18
19
20data RigidBody = RigidBody
21 { mass :: Float
22 , position :: Vector3
23 , velocity :: Vector3
24 , acceleration :: Vector3
25 }
26
27
28instance Spatial RigidBody where
29
30 move v body = body { position = v + position body }
31
32 moveFwd speed body = body { position = position body + scale (-speed) unitZ }
33
34 moveBack speed body = body { position = position body + scale speed unitZ }
35
36 strafeLeft speed body = body { position = position body + scale (-speed) unitX }
37
38 strafeRight speed body = body { position = position body + scale speed unitX }
39
40 pitch angle = id
41
42 yaw angle = id
43
44 roll angle = id
45
46 pos = position
47
48 fwd _ = unitZ
49
50 up _ = unitY
51
52 right _ = unitX
53
54 transform body = M4.transform unitX unitY unitZ $ position body
55
56 setTransform transf body = body { position = M4.position transf }
57
58 setPos p body = body { position = p }
59
60
61-- | Build a 'RigidBody'.
62rigidBody :: Mass -> Position -> RigidBody
63rigidBody m x = RigidBody m x V3.zero V3.zero
64
65
66-- | Update the given 'RigidBody'.
67update :: [Force] -> Dt -> RigidBody -> RigidBody
68update forces dt body =
69 let netforce = foldl' (+) V3.zero forces
70 m = mass body
71 r1 = position body
72 v1 = velocity body
73 a1 = acceleration body
74 r2 = r1 + scale dt v1 + scale (0.5*dt*dt) a1
75 v' = v1 + scale (0.5*dt) a1
76 a2 = a1 + scale (1/m) netforce
77 v2 = v1 + scale (dt/2) (a2+a1) + scale (0.5*dt) a2
78 in
79 RigidBody m r2 v2 a2
80
81
82-- test
83gravity = vec3 0 (-10) 0
84b0 = rigidBody 50 $ vec3 0 1000 0
85
86
87debug :: IO ()
88debug = evalStateT debug' b0
89
90
91
92debug' :: StateT RigidBody IO ()
93debug' = do
94 lift . putStrLn $ "Initial body:"
95 lift . putStrLn . show' $ b0
96 lift . putStrLn $ "Falling..."
97 step $ update [gravity*50] 1
98 step $ update [gravity*50] 1
99 step $ update [gravity*50] 1
100 lift . putStrLn $ "Jumping"
101 step $ update [gravity*50, vec3 0 9000 0] 1
102 lift . putStrLn $ "Falling..."
103 step $ update [gravity*50] 1
104 step $ update [gravity*50] 1
105 step $ update [gravity*50] 1
106
107
108step :: (RigidBody -> RigidBody) -> StateT RigidBody IO ()
109step update = do
110 modify update
111 body <- get
112 lift . putStrLn . show' $ body
113
114
115show' body =
116 "mass " ++ (show $ mass body) ++
117 ", position " ++ (showVec $ position body) ++
118 ", velocity " ++ (showVec $ velocity body) ++
119 ", acceleration " ++ (showVec $ acceleration body)
120
121
122showVec v = (show $ x v) ++ ", " ++ (show $ y v) ++ ", " ++ (show $ z v)