def collide(self): for a in self.actors: a.collision_prepare() for i, ai in enumerate(self.actors): if isinstance(ai, ParticleActor): ai.collision_self() for j, aj in enumerate(self.actors): if isinstance(aj, ParticleActor): continue if i == j: continue info = spatial.Info(ai.spatial_grid, aj.spatial_mesh, i == j) mask = info.triangle != -1 active = np.flatnonzero(mask) # active vertex idx if np.any(mask): # and not isinstance(ai, StaticActor): triangle = info.triangle[active] bary = info.bary[active] velocity = aj.velocity[aj.mesh.faces[triangle]] velocity = np.einsum('vtc,vt->vc', velocity, bary) relative_velocity = ai.velocity[active] - velocity friction = 1e-2 stiffness = 1e1 force = info.depth[active][:, None] * info.normal[ active] * stiffness - relative_velocity * friction assert not np.any(np.isnan(force)) np.add.at(ai.force, active, force) corners = aj.mesh.faces[triangle] for i in range(3): np.add.at(aj.force, corners[:, i], -bary[:, [i]] * force)
def test_collision(): meshes = [ icosphere(0.5, refinement=3), icosphere(0.5, [0.95, 0, 0], refinement=3) ] lengthscale = 0.2 grids = [spatial.Grid3d(m.vertices, lengthscale) for m in meshes] ctmeshes = [ spatial.Mesh(m.vertices, m.vertex_normals(), m.faces, 0.1, 0) for m in meshes ] for i, mi in enumerate(meshes): for j, mj in enumerate(meshes): print(i, j) info = spatial.Info(grids[i], ctmeshes[j], i == j) mask = info.triangle != -1 print(info.triangle[mask]) print(info.depth[mask])