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
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion