-
Notifications
You must be signed in to change notification settings - Fork 1
/
elements.py
106 lines (83 loc) · 3.13 KB
/
elements.py
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
from math_utils import *
from vector3 import *
gravity = -9.81
drag = 0.1
class point_mass:
def __init__(self, ident, pos, vel, color, mass, static=False):
self.ident = ident
self.pos = pos
self.vel = vel
self.color = color
self.mass = mass
self.static = static
self.accel = vec3()
def get_dist_to(self, thing):
return (self.pos - thing.pos).mag()
def direction_to(self, thing):
return (thing.pos - self.pos).normalized()
def clear_accel(self):
self.accel = vec3()
def apply_force(self, force):
self.accel += force/self.mass
def apply_gravity(self):
self.apply_force(vec3(0, self.mass * gravity, 0))
def apply_drag(self):
self.apply_force(self.vel.normalized() * -1 * self.vel.mag()**2 * drag)
def update_vel(self, dt):
if not self.static:
self.vel += self.accel * dt
def update_pos(self, dt):
if not self.static:
self.pos += self.vel * dt
class link:
def __init__(self, ident, p1, p2, color, k=5000, link_type="beam"):
self.ident = ident
self.p1 = p1
self.p2 = p2
self.color = color
self.k = k
self.link_type = link_type
self.neutral_length = p1.get_dist_to(p2)
self.pos = (p1.pos + p2.pos)/2
def apply_force(self):
p1 = self.p1
p2 = self.p2
dist = p1.get_dist_to(p2)
if self.link_type == "beam" and not dist == self.neutral_length:
p1.apply_force(p1.direction_to(p2) * self.k * (dist - self.neutral_length))
p2.apply_force(p2.direction_to(p1) * self.k * (dist - self.neutral_length))
elif self.link_type == "rope" and dist > self.neutral_length:
p1.apply_force(p1.direction_to(p2) * self.k * (dist - self.neutral_length))
p2.apply_force(p2.direction_to(p1) * self.k * (dist - self.neutral_length))
def calc_force(self):
p1 = self.p1
p2 = self.p2
dist = p1.get_dist_to(p2)
if self.link_type == "beam" and not dist == self.neutral_length:
return self.k * (dist - self.neutral_length)
elif self.link_type == "rope" and dist > self.neutral_length:
return self.k * (dist - self.neutral_length)
else:
return 0
class ground:
def __init__(self, height, color, elasticity, k):
self.height = height
self.color = color
self.elasticity = elasticity
self.k = k
def apply_force(self, points, dt):
for p in points:
# normal force
if p.pos.y < self.height:
p.apply_force(vec3(0, p.mass * p.vel.y * -1 * (self.elasticity+1)/dt, 0))
p.apply_force(vec3(0, p.mass * -gravity, 0))
# friction
if p.pos.y <= self.height:
p.apply_force(vec3(p.vel.x, 0, p.vel.z) * p.mass * gravity * self.k)
class const_force:
def __init__(self, ident, point, force):
self.ident = ident
self.point = point
self.force = force
def apply(self):
self.point.apply_force(self.force)