def update_geom(self): geom = self.node.modify_geom(0) vdata = geom.modify_vertex_data() vwriter = GeomVertexRewriter(vdata, InternalName.get_vertex()) #TODO: refactor with above code !!! delta = self.body.parent.get_local_position() if self.orbit.is_periodic(): epoch = self.context.time.time_full - self.orbit.period step = self.orbit.period / (self.nbOfPoints - 1) else: #TODO: Properly calculate orbit start and end time epoch = self.orbit.get_time_of_perihelion() - self.orbit.period * 5.0 step = self.orbit.period * 10.0 / (self.nbOfPoints - 1) for i in range(self.nbOfPoints): time = epoch + step * i pos = self.orbit.get_position_at(time) - delta vwriter.setData3f(*pos)
def rain(self, task): # animate level self.flood() # Animate Rain speed = 1.0 vertex = GeomVertexRewriter(self.rain_vdata, 'vertex') color = GeomVertexWriter(self.rain_vdata, 'color') moving = np.random.choice([0, 1], size=(self.n_points, self.n_points), p=[999 / 1000, 1. / 1000]) moved = 0 for j in range(self.n_points): for i in range(self.n_points): # rain v = vertex.getData3f() # start falling if v[2] == self.n_points: if moving[j][i] == 1 and self.raining == True: self.rz[j][i] -= speed vertex.setData3f(v[0], v[1], self.rz[j][i]) color.setData4f(0.3, 0.3, 1, 1) moved += 1 else: vertex.setData3f(v[0], v[1], v[2]) color.setData4f(0.3, 0.3, 1, 0) # keep falling elif self.rz[j][i] > self.lz[j][i]: if self.rz[j][i] - speed > self.lz[j][i]: self.rz[j][i] -= speed else: self.rz[j][i] = self.lz[j][i] vertex.setData3f(v[0], v[1], self.rz[j][i]) if self.rz[j][i] > self.wz[j][i]: color.setData4f(0.3, 0.3, 1, 1) else: color.setData4f(0.3, 0.3, 1, 0) moved += 1 # stop falling else: # handle rolling drops v = list(map(int, v)) moved += self.rolling_drops(v, vertex, color, moved, i, j) if moved == 0: self.flooding = False return task.done return task.cont
def wave(self, task): # Compute physic step_np1 = self.water_physic() self.H += 0.1 * (np.mean(step_np1) - self.H) # render wave vertex = GeomVertexRewriter(self.water_vdata, 'vertex') normal = GeomVertexRewriter(self.water_vdata, 'normal') for j in range(0, self.n_points, self.details): for i in range(0, self.n_points, self.details): self.wz[j][i] = step_np1[j // self.details][i // self.details] v = vertex.getData3f() if j != 0 and i != 0 and j != self.n_points - self.details and \ i != self.n_points - self.details: vertex.setData3f(v[0], v[1], self.wz[j][i]) n = np.array([v[0], v[1], self.wz[j][i]]) else: vertex.setData3f(v[0], v[1], self.H) n = np.array([v[0], v[1], self.H]) norm = n / np.linalg.norm(n) normal.setData3f(norm[0], norm[1], norm[2]) # Extend Water Borders vertex = GeomVertexRewriter(self.water_border_vdata, 'vertex') normal = GeomVertexRewriter(self.water_border_vdata, 'normal') for i in range(0, 8, 2): v = vertex.getData3f() vertex.setData3f(v[0], v[1], self.H) n = np.array([v[0], v[1], self.H]) norm = n / np.linalg.norm(n) normal.setData3f(norm[0], norm[1], norm[2]) v = vertex.getData3f() vertex.setData3f(v[0], v[1], 0) n = np.array([v[0], v[1], 1e-12]) norm = n / np.linalg.norm(n) normal.setData3f(norm[0], norm[1], norm[2]) # handle last puddles self.handle_last_puddles() return task.cont
def flood(self, task=None): # Animate Water Surface step_np1 = self.water_physic() vertex = GeomVertexRewriter(self.water_vdata, 'vertex') normal = GeomVertexRewriter(self.water_vdata, 'normal') for j in range(0, self.n_points, self.details): for i in range(0, self.n_points, self.details): # Flood if j != 0 and i != 0 and j != self.n_points - self.details and \ i != self.n_points - self.details: self.wz[j][i] = step_np1[j // self.details][i // self.details] else: self.wz[j][i] = self.H # borders condition v = vertex.getData3f() vertex.setData3f(v[0], v[1], self.wz[j][i]) n = np.array([v[0], v[1], self.wz[j][i]]) norm = n / np.linalg.norm(n) normal.setData3f(norm[0], norm[1], norm[2]) # Extend Water Borders vertex = GeomVertexRewriter(self.water_border_vdata, 'vertex') normal = GeomVertexRewriter(self.water_border_vdata, 'normal') for i in range(0, 8, 2): v = vertex.getData3f() vertex.setData3f(v[0], v[1], self.H) n = np.array([v[0], v[1], self.H]) norm = n / np.linalg.norm(n) normal.setData3f(norm[0], norm[1], norm[2]) v = vertex.getData3f() vertex.setData3f(v[0], v[1], 0) n = np.array([v[0], v[1], 1e-12]) norm = n / np.linalg.norm(n) normal.setData3f(norm[0], norm[1], norm[2]) # animate level if self.flooding == True and self.flush == False and self.H < self.n_points: self.H += self.dt elif self.flush == True and self.H > 1: self.H -= self.dt # handle last puddles #self.handle_last_puddles() if task: return task.cont
def __init__(self, objinit, cdtype="triangle", mass=.3, restitution=0, allowdeactivation=False, allowccd=True, friction=.2, dynamic=True, name="rbd"): """ :param objinit: could be itself (copy), or an instance of collision model :param type: triangle or convex :param mass: :param restitution: bounce parameter :param friction: :param dynamic: only applicable to triangle type, if an object does not move with force, it is not dynamic :param name: author: weiwei date: 20190626, 20201119 """ super().__init__(name) if isinstance(objinit, gm.GeometricModel): if objinit._objtrm is None: raise ValueError("Only applicable to models with a trimesh!") self.com = objinit.objtrm.center_mass self.setMass(mass) self.setRestitution(restitution) self.setFriction(friction) self.setLinearDamping(.3) self.setAngularDamping(.3) if allowdeactivation: self.setDeactivationEnabled(True) self.setLinearSleepThreshold(0.001) self.setAngularSleepThreshold(0.001) else: self.setDeactivationEnabled(False) if allowccd: # continuous collision detection self.setCcdMotionThreshold(1e-6) self.setCcdSweptSphereRadius(0.0005) gnd = objinit.objpdnp.getChild(0).find("+GeomNode") geom = copy.deepcopy(gnd.node().getGeom(0)) vdata = geom.modifyVertexData() vertrewritter = GeomVertexRewriter(vdata, 'vertex') while not vertrewritter.isAtEnd(): # shift local coordinate to geom to correctly update dynamic changes v = vertrewritter.getData3f() vertrewritter.setData3f(v[0] - self.com[0], v[1] - self.com[1], v[2] - self.com[2]) geomtf = gnd.getTransform() if cdtype is "triangle": geombmesh = BulletTriangleMesh() geombmesh.addGeom(geom) bulletshape = BulletTriangleMeshShape(geombmesh, dynamic=dynamic) bulletshape.setMargin(1e-6) self.addShape(bulletshape, geomtf) elif cdtype is "convex": bulletshape = BulletConvexHullShape() # TODO: compute a convex hull? bulletshape.addGeom(geom, geomtf) bulletshape.setMargin(1e-6) self.addShape(bulletshape, geomtf) else: raise NotImplementedError pdmat4 = geomtf.getMat() pdv3 = pdmat4.xformPoint(Vec3(self.com[0], self.com[1], self.com[2])) homomat = dh.pdmat4_to_npmat4(pdmat4) pos = dh.pdv3_to_npv3(pdv3) homomat[:3, 3] = pos # update center to com self.setTransform(TransformState.makeMat(dh.npmat4_to_pdmat4(homomat))) elif isinstance(objinit, BDBody): self.com = objinit.com.copy() self.setMass(objinit.getMass()) self.setRestitution(objinit.restitution) self.setFriction(objinit.friction) self.setLinearDamping(.3) self.setAngularDamping(.3) if allowdeactivation: self.setDeactivationEnabled(True) self.setLinearSleepThreshold(0.001) self.setAngularSleepThreshold(0.001) else: self.setDeactivationEnabled(False) if allowccd: self.setCcdMotionThreshold(1e-6) self.setCcdSweptSphereRadius(0.0005) self.setTransform(TransformState.makeMat(dh.npmat4_to_pdmat4(objinit.gethomomat()))) self.addShape(objinit.getShape(0), objinit.getShapeTransform(0))