[Numpy-discussion] Physics Engine
Ian Mallett
geometrian at gmail.com
Wed Apr 7 22:36:03 EDT 2010
Hi,
I'm working on various projects, I think it would be great to have a
built-in physics engine to my rendering library. I would rather not rely on
a large dedicated Physics library (PyOGRE, PyODE, etc.). I thought it might
be interesting to try to make a simple soft-body physics engine with NumPy.
To this end, over the past few hours, I've constructed this per-vertex
physics object class, which plugs directly into my rendering object's
class. So far, it implements global forces, collision detection with a
horizontal plane, and length tensors:
class glLibCPUSoftPhysMesh:
def __init__(self,object):
self.object = object
self.original_vertices = np.array(object.raw_vertices)
#object.raw_vertices is the unique list of vertices
self.vertices = np.array(object.raw_vertices)
self.vertex_indices = np.array(object.indexed_vertices[0])
#object.indexed_vertices[0] is a list of indices into object.raw_vertices
self.vertex_speeds = np.zeros((self.vertices.shape[0],3))
self.delta_pos = np.zeros((self.vertices.shape[0],3))
v1s = self.original_vertices[self.vertex_indices[0::3]]
v2s = self.original_vertices[self.vertex_indices[1::3]]
v3s = self.original_vertices[self.vertex_indices[2::3]]
self.target_lengths1 = np.sum((v1s-v2s)**2.0,axis=1)**0.5
self.target_lengths2 = np.sum((v2s-v3s)**2.0,axis=1)**0.5
self.target_lengths3 = np.sum((v3s-v1s)**2.0,axis=1)**0.5
self.dampening = 0.999
def add_force(self,force):
self.vertex_speeds += np.array(force)
def add_position(self,pos):
self.delta_pos += np.array(pos)
def move(self):
#Length tensors
v1s = self.vertices[self.vertex_indices[0::3]]
v2s = self.vertices[self.vertex_indices[1::3]]
v3s = self.vertices[self.vertex_indices[2::3]]
side1 = v2s - v1s
side2 = v3s - v2s
side3 = v1s - v3s
delta_side1 = np.transpose(
((np.sum(side1**2.0,axis=1)**0.5)-self.target_lengths1,)*3 ) * side1
delta_side2 = np.transpose(
((np.sum(side2**2.0,axis=1)**0.5)-self.target_lengths2,)*3 ) * side2
delta_side3 = np.transpose(
((np.sum(side3**2.0,axis=1)**0.5)-self.target_lengths3,)*3 ) * side3
tensor = 0.01
self.vertex_speeds[self.vertex_indices[0::3]] += tensor*delta_side1
self.vertex_speeds[self.vertex_indices[1::3]] -= tensor*delta_side1
self.vertex_speeds[self.vertex_indices[1::3]] += tensor*delta_side2
self.vertex_speeds[self.vertex_indices[2::3]] -= tensor*delta_side2
self.vertex_speeds[self.vertex_indices[2::3]] += tensor*delta_side3
self.vertex_speeds[self.vertex_indices[0::3]] -= tensor*delta_side3
self.delta_pos += self.vertex_speeds
self.vertex_speeds *= self.dampening
self.vertices += self.delta_pos
self.delta_pos.fill(0.0)
def collision_detect(self):
indices = np.where(self.vertices[:,1]<0.0001)
self.vertices[indices,1] = 0.0001
self.vertex_speeds[indices] *= -0.1
def get_data(self):
return [self.vertices[self.vertex_indices].tolist()]
The code works fairly well for its complexity (and runs very quickly). I
believe it also needs angle tensors, which would be more complicated. There
are a few strange errors I can't account for (like the object very slowly
drifts, as it rests on the ground).
At the moment, I'm wondering whether a physics engine has already been done
with NumPy before, and if not, whether anyone has any interest in making
one.
Ian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20100407/65c5737a/attachment.html>
More information about the NumPy-Discussion
mailing list