def drawLeaf(nodePath, vdata, pos=Vec3(0, 0, 0), vecList=[Vec3(0, 0, 1), Vec3(1, 0, 0), Vec3(0, -1, 0)], scale=0.125): #use the vectors that describe the direction the branch grows to make the right #rotation matrix newCs = Mat4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) newCs.setRow(0, vecList[2]) #right newCs.setRow(1, vecList[1]) #up newCs.setRow(2, vecList[0]) #forward newCs.setRow(3, Vec3(0, 0, 0)) newCs.setCol(3, Vec4(0, 0, 0, 1)) axisAdj = Mat4.scaleMat(scale) * newCs * Mat4.translateMat(pos) #orginlly made the leaf out of geometry but that didnt look good #I also think there should be a better way to handle the leaf texture other than #hardcoding the filename leafModel = loader.loadModel('models/shrubbery') leafTexture = loader.loadTexture('models/material-10-cl.png') leafModel.reparentTo(nodePath) leafModel.setTexture(leafTexture, 1) leafModel.setTransform(TransformState.makeMat(axisAdj))
def _trackballTask(self, task): if not self.mouseDown: return Task.cont if (base.mouseWatcherNode.hasMouse()): mpos = base.mouseWatcherNode.getMouse() if mpos == self.lastMousePos: return Task.cont mDelta = mpos - self.clickPos heading = -mDelta.x * 100 + self.initialHpr.x pitch = mDelta.y * 100 + self.initialHpr.y if pitch > 90: pitch = 90 elif pitch < -90: pitch = -90 trans1 = Mat4.translateMat(self.focus) rotx = Mat4.rotateMat(heading, Vec3(0, 0, 1)) roty = Mat4.rotateMat(pitch, Vec3(1, 0, 0)) trans2 = Mat4.translateMat(0, -self.initialTranslation, 0) rotation = trans2 * roty * rotx * trans1 base.camera.setMat(rotation) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera) self.lastMousePos = Vec2(mpos) return Task.cont
def mousePressed(self, event): self.parent.beginTransformation() lens = base.cam.node().getLens() scale = Mat4.scaleMat(self.path.getScale(base.camera)) descale = Mat4() descale.invertAffineFrom(scale) mvMat = descale * self.path.getMat(base.camera) origin = Point3(mvMat.xformPoint(Point3())) dir = Vec3(mvMat.xformVec(Vec3(0, 0, 1))) xprod = dir.cross(origin) planeNorm = xprod.cross(dir) planeNorm.normalize() d = planeNorm.dot(origin) self.dir = dir self.origin = origin self.planeNorm = planeNorm self.d = d self.lens = lens self.fromCam = base.camera.getMat(self.parent.path) * scale transl = self.mouse2Vec(event.pos) self.origin = transl + self.origin
def __occlusion_mesh(self, pos): tgt = self.car.gfx.nodepath.get_pos() occl = self.__closest_occl(pos, tgt) if not occl: return None car_vec = self.car.logic.car_vec rot_mat_left = Mat4() rot_mat_left.setRotateMat(90, (0, 0, 1)) car_vec_left = rot_mat_left.xformVec(car_vec._vec) # access to a protected member tgt_left = tgt + car_vec_left pos_left = pos + car_vec_left occl_left = self.__closest_occl(pos_left, tgt_left) if not occl_left: return None rot_mat_right = Mat4() rot_mat_right.setRotateMat(-90, (0, 0, 1)) car_vec_right = rot_mat_right.xformVec(car_vec._vec) # access to a protected member car_vec_right += (0, 0, 2) tgt_right = tgt + car_vec_right pos_right = pos + car_vec_right phys_root = self.eng.phys_mgr.root occl_right = phys_root.ray_test_closest(tgt_right, pos_right) occl_right = self.__closest_occl(pos_right, tgt_right) if not occl_right: return None return occl
def check_mouse1drag(self): """ this function uses a collision sphere to track the rotational mouse motion :return: author: weiwei date: 20200315 """ curm1pos = self.get_world_mouse1() if curm1pos is None: if self.lastm1pos is not None: self.lastm1pos = None return if self.lastm1pos is None: # first time click self.lastm1pos = curm1pos return curm1vec = Vec3(curm1pos - self.lookatpos_pdv3) lastm1vec = Vec3(self.lastm1pos - self.lookatpos_pdv3) curm1vec.normalize() lastm1vec.normalize() rotatevec = curm1vec.cross(lastm1vec) if rotatevec.length() > 1e-9: # avoid zero length rotateangle = curm1vec.signedAngleDeg(lastm1vec, rotatevec) rotateangle = rotateangle * self.camdist * 5000 if rotateangle > .02 or rotateangle < -.02: rotmat = Mat4(self.base.cam.getMat()) posvec = Vec3(self.base.cam.getPos()) rotmat.setRow(3, Vec3(0, 0, 0)) self.base.cam.setMat(rotmat * Mat4.rotateMat(rotateangle, rotatevec)) self.base.cam.setPos(Mat3.rotateMat(rotateangle, rotatevec). \ xform(posvec - self.lookatpos_pdv3) + self.lookatpos_pdv3) self.lastm1pos = self.get_world_mouse1() self.update_trackplane()
def update(self, pb_camera): self.set_mat(self.Z2Y * Mat4(*pb_camera.pose_mat)) mat = np.asarray(pb_camera.proj_mat).reshape(4, 4) m22, m32 = -mat[2, 2], -mat[3, 2] zfar = (2.0 * m32) / (2.0 * m22 - 2.0) znear = ((m22 - 1.0) * zfar) / (m22 + 1.0) self._lens.set_near_far(znear, zfar) self._lens.set_user_mat(self.Z2Y * Mat4(*pb_camera.proj_mat))
def rotsToMat4(x, y, z): rotx = Mat4(1, 0, 0, 0, 0, cos(x), -sin(x), 0, 0, sin(x), cos(x), 0, 0, 0, 0, 1) roty = Mat4(cos(y), 0, sin(y), 0, 0, 1, 0, 0, -sin(y), 0, cos(y), 0, 0, 0, 0, 1) rotz = Mat4(cos(z), -sin(z), 0, 0, sin(z), cos(z), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) swapyz = Mat4.rotateMat(90, Vec3(-1, 0, 0)) return rotx * roty * rotz * swapyz
def transform(self, xform): transl = Mat4(Mat4.identMat()) transl.setRow(3, xform.getRow3(3)) self.path.setMat(render, transl * self.originalMat) self._fixScale() xform.setRow(3, Vec3()) for client, originalMat in self.clients: #client.setMat(self.path, originalMat * xform) client.setMat(originalMat * xform * transl * self.originalMat)
def update(self): """ Updates the commonly used resources, mostly the shader inputs """ update = self._input_ubo.update_input # Get the current transform matrix of the camera view_mat = Globals.render.get_transform(self._showbase.cam).get_mat() # Compute the view matrix, but with a z-up coordinate system update("view_mat_z_up", view_mat * Mat4.convert_mat(CS_zup_right, CS_yup_right)) # Compute the view matrix without the camera rotation view_mat_billboard = Mat4(view_mat) view_mat_billboard.set_row(0, Vec3(1, 0, 0)) view_mat_billboard.set_row(1, Vec3(0, 1, 0)) view_mat_billboard.set_row(2, Vec3(0, 0, 1)) update("view_mat_billboard", view_mat_billboard) update("camera_pos", self._showbase.camera.get_pos(Globals.render)) # Compute last view projection mat curr_vp = self._input_ubo.get_input("view_proj_mat_no_jitter") update("last_view_proj_mat_no_jitter", curr_vp) curr_vp = Mat4(curr_vp) curr_vp.invert_in_place() update("last_inv_view_proj_mat_no_jitter", curr_vp) proj_mat = Mat4(self._showbase.camLens.get_projection_mat()) # Set the projection matrix as an input, but convert it to the correct # coordinate system before. proj_mat_zup = Mat4.convert_mat(CS_yup_right, CS_zup_right) * proj_mat update("proj_mat", proj_mat_zup) # Set the inverse projection matrix update("inv_proj_mat", invert(proj_mat_zup)) # Remove jitter and set the new view projection mat proj_mat.set_cell(1, 0, 0.0) proj_mat.set_cell(1, 1, 0.0) update("view_proj_mat_no_jitter", view_mat * proj_mat) # Store the frame delta update("frame_delta", Globals.clock.get_dt()) update("smooth_frame_delta", 1.0 / max(1e-5, Globals.clock.get_average_frame_rate())) update("frame_time", Globals.clock.get_frame_time()) # Store the current film offset, we use this to compute the pixel-perfect # velocity, which is otherwise not possible. Usually this is always 0 # except when SMAA and reprojection is enabled update("current_film_offset", self._showbase.camLens.get_film_offset()) max_clip_length = 1 if self._pipeline.plugin_mgr.is_plugin_enabled("smaa"): max_clip_length = self._pipeline.plugin_mgr.instances["smaa"].history_length update("temporal_index", Globals.clock.get_frame_count() % max_clip_length) update("frame_index", Globals.clock.get_frame_count())
def _computeMVP(self): projMat = Mat4.convertMat(CSYupRight, base.camLens.getCoordinateSystem( )) * base.camLens.getProjectionMat() transformMat = TransformState.makeMat( Mat4.convertMat(base.win.getGsg().getInternalCoordinateSystem(), CSZupRight)) modelViewMat = transformMat.invertCompose(render.getTransform( base.cam)).getMat() self.lastMVP = modelViewMat * projMat
def computeMVP(self): projMat = Mat4.convertMat( CSYupRight, self.lens.getCoordinateSystem()) * self.lens.getProjectionMat() transformMat = TransformState.makeMat( Mat4.convertMat(base.win.getGsg().getInternalCoordinateSystem(), CSZupRight)) modelViewMat = transformMat.invertCompose( render.getTransform(self.cameraNode)).getMat() self.mvp = UnalignedLMatrix4f(modelViewMat * projMat)
def __init__(self, viewedmatrix, relativematrix): from panda3d.core import Mat4, Mat3 self.viewedmatrix = viewedmatrix assert relativematrix is not None self.relmat = Mat4( relativematrix.get_proxy("NodePath").getMat().getUpper3()) self.relmatinv = Mat4(self.relmat) self.relmatinv.invertInPlace() self.relpos = relativematrix.get_proxy("NodePath").getPos()
def _computeMVP(self): """ Computes the current mvp. Actually, this is the worldViewProjectionMatrix, but for convience it's called mvp. """ camLens = self.showbase.camLens projMat = Mat4.convertMat( CSYupRight, camLens.getCoordinateSystem()) * camLens.getProjectionMat() transformMat = TransformState.makeMat( Mat4.convertMat(self.showbase.win.getGsg().getInternalCoordinateSystem(), CSZupRight)) modelViewMat = transformMat.invertCompose( self.showbase.render.getTransform(self.showbase.cam)).getMat() return UnalignedLMatrix4f(modelViewMat * projMat)
def beginTransformation(self): self.originalMat = Mat4(Mat4.identMat()) self.originalMat.setRow(3, self.path.getMat(render).getRow(3)) self.originalMatInv = Mat4() self.originalMatInv.invertAffineFrom(self.originalMat) for i in xrange(len(self.clients)): print 'Their matrix * My matrix' print self.clients[i][0].getMat(self.path) * self.path.getMat() print 'Total matrix:' print self.clients[i][0].getMat() #self.clients[i][1] = self.clients[i][0].getMat(self.path) self.clients[i][1] = (self.clients[i][0].getMat() * self.originalMatInv)
def drawLeaf(self, pos=Vec3(0, 0, 0), quat=None, scale=0.125): """ this draws leafs when we reach an end """ #use the vectors that describe the direction the branch grows to make #the right rotation matrix newCs = Mat4() quat.extractToMatrix(newCs) axisAdj = Mat4.scaleMat(scale) * newCs * Mat4.translateMat(pos) leafModel = NodePath("leaf") self.leafModel.instanceTo(leafModel) leafModel.reparentTo(self.leaves) leafModel.setTransform(TransformState.makeMat(axisAdj))
def _computeAdditionalData(self): """ Internal method to recompute the spotlight MVP """ self.ghostCameraNode.setPos(self.position) transMat = TransformState.makeMat( Mat4.convertMat(Globals.base.win.getGsg().getInternalCoordinateSystem(), CSZupRight)) converterMat = Mat4.convertMat(CSYupRight, self.ghostLens.getCoordinateSystem()) * self.ghostLens.getProjectionMat() modelViewMat = transMat.invertCompose( Globals.render.getTransform(self.ghostCameraNode)).getMat() self.mvp = modelViewMat * converterMat
def _computeMVP(self): """ Computes the current mvp. Actually, this is the worldViewProjectionMatrix, but for convience it's called mvp. """ camLens = self.showbase.camLens projMat = Mat4.convertMat( CSYupRight, camLens.getCoordinateSystem()) * camLens.getProjectionMat() transformMat = TransformState.makeMat( Mat4.convertMat( self.showbase.win.getGsg().getInternalCoordinateSystem(), CSZupRight)) modelViewMat = transformMat.invertCompose( self.showbase.render.getTransform(self.showbase.cam)).getMat() return UnalignedLMatrix4f(modelViewMat * projMat)
def move_city(self, task): # moves the city, using the transformation matrix # first, get the current transformation matrix # getTransform() returns a TransformState, which is a higher level # abstraction of our matrix # getMat() retrieves the inner matrix. the returned matrix is const # though oldmat = self.cityModel.getTransform().getMat() # oldmat ist a const Mat4, we need one we can manipulate newmat = Mat4(oldmat) # the matrices in Panda3d are suitable for row-vector multiplication, that is # vector * Matrix (same as opengl). the bottom row (3) is therefore the # translation in xyzt order # # replace it with a different one, we want to move the value of # time, which is the number of seconds passed since starting this task newmat.setRow(3, Vec4(1 - task.time, 3, 0, 1)) # we need to create a new TransformState from the matrix, and set it # to apply the transformation self.cityModel.setTransform(TransformState.makeMat(newmat)) return Task.cont
def stop_camera(self): mat = Mat4(camera.getMat()) mat.invertInPlace() base.mouseInterfaceNode.setMat(mat) base.enableMouse() self.taskMgr.remove("SpinCameraTaskX") self.taskMgr.remove("SpinCameraTaskY")
def mouseMoved(self, event): transl = Vec3(self.mouse2Vec(event.pos)) transl.normalize() angle = self.dir.signedAngleDeg(transl, self.planeNorm) axis = Vec3() setattr(axis, self.dim, 1) self.parent.transform(Mat4.rotateMatNormaxis(angle, axis))
def recurseScene(curnode, scene_members, data_cache, M, texture_cache, col_inst=None): M = numpy.dot(M, curnode.matrix) for node in curnode.children: if isinstance(node, collada.scene.Node): recurseScene(node, scene_members, data_cache, M, texture_cache, col_inst=col_inst) elif isinstance(node, collada.scene.GeometryNode) or isinstance(node, collada.scene.ControllerNode): if isinstance(node, collada.scene.GeometryNode): geom = node.geometry else: geom = node.controller.geometry materialnodesbysymbol = {} for mat in node.materials: materialnodesbysymbol[mat.symbol] = mat for prim in geom.primitives: if len(prim) > 0: mat = materialnodesbysymbol.get(prim.material) matstate = None if mat is not None: matstate = data_cache['material2state'].get(mat.target) if matstate is None: matstate = getStateFromMaterial(mat.target, texture_cache, col_inst) if geom.double_sided: matstate = matstate.addAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullNone)) data_cache['material2state'][mat.target] = matstate mat4 = Mat4(*M.T.flatten().tolist()) primgeom = data_cache['prim2geom'].get(prim) if primgeom is None: primgeom = getGeomFromPrim(prim, matstate) data_cache['prim2geom'][prim] = primgeom scene_members.append((primgeom, matstate, mat4))
def draw_leaf(nodePath, vdata, pos=Vec3(0, 0, 0), vecList=[Vec3(0, 0, 1), Vec3(1, 0, 0), Vec3(0, -1, 0)], scale=0.125): # use the vectors that describe the direction the branch grows to make the right # rotation matrix newCs = Mat4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) newCs.setRow(0, vecList[2]) # right newCs.setRow(1, vecList[1]) # up newCs.setRow(2, vecList[0]) # forward newCs.setRow(3, Vec3(0, 0, 0)) newCs.setCol(3, Vec4(0, 0, 0, 1)) try: axisAdj = Mat4.scaleMat(scale) * newCs * Mat4.translateMat(pos) except TypeError, e: print e print scale, pos
def rotmat(theta, axis_1=0, axis_2=3): m = np.eye(4) m[axis_1, axis_1] = np.cos(theta) m[axis_1, axis_2] = -np.sin(theta) m[axis_2, axis_1] = np.sin(theta) m[axis_2, axis_2] = np.cos(theta) return Mat4(*m.flatten())
def append_mesh(self, root_path, name, mesh_path, scale=None, frame=None, no_cache=None): """Append a mesh node to the group. Arguments: root_path {str} -- path to the group's root node name {str} -- node name within a group mesh_path {str} -- path to the mesh file on disk Keyword Arguments: scale {Vec3} -- mesh scale (default: {None}) frame {tuple} -- local frame position and quaternion (default: {None}) no_cache {bool} -- use cache to load a model (default: {None}) """ mesh = self.loader.loadModel(mesh_path, noCache=no_cache) if mesh_path.lower().endswith('.dae'): # converting from Y-up to Z-up axes when import from dae mesh.set_mat(Mat4.yToZUpMat()) if scale is not None: mesh.set_scale(Vec3(*scale)) if sum([s < 0 for s in scale]) % 2 != 0: # reverse the cull order in case of negative scale values mesh.set_attrib(CullFaceAttrib.make_reverse()) self.append_node(root_path, name, mesh, frame)
def is_drifting(self): car_vec = self.car_vec rot_mat_left = Mat4() rot_mat_left.setRotateMat(90, (0, 0, 1)) car_vec_left = rot_mat_left.xformVec(car_vec._vec) # access to a protected member rot_mat_right = Mat4() rot_mat_right.setRotateMat(-90, (0, 0, 1)) car_vec_right = rot_mat_right.xformVec(car_vec._vec) # access to a protected member vel = self.mediator.phys.vehicle.get_chassis().get_linear_velocity() vel.normalize() car_dot_vel_l = car_vec_left.dot(vel) car_dot_vel_r = car_vec_right.dot(vel) car_dot_vel = max(car_dot_vel_l, car_dot_vel_r) return car_dot_vel > .1
def _createInputHandles(self): """ Defines various inputs to be used in the shader passes. Most inputs use pta-arrays, so updating them is faster than using setShaderInput all the time. """ self.cameraPosition = PTAVecBase3f.emptyArray(1) self.currentViewMat = PTALMatrix4f.emptyArray(1) self.currentProjMatInv = PTALMatrix4f.emptyArray(1) self.lastMVP = PTALMatrix4f.emptyArray(1) self.currentMVP = PTALMatrix4f.emptyArray(1) self.frameIndex = PTAInt.emptyArray(1) self.frameDelta = PTAFloat.emptyArray(1) self.renderPassManager.registerStaticVariable("lastMVP", self.lastMVP) self.renderPassManager.registerStaticVariable("currentMVP", self.currentMVP) self.renderPassManager.registerStaticVariable("frameIndex", self.frameIndex) self.renderPassManager.registerStaticVariable("cameraPosition", self.cameraPosition) self.renderPassManager.registerStaticVariable("mainCam", self.showbase.cam) self.renderPassManager.registerStaticVariable("mainRender", self.showbase.render) self.renderPassManager.registerStaticVariable("frameDelta", self.frameDelta) self.renderPassManager.registerStaticVariable("currentViewMat", self.currentViewMat) self.renderPassManager.registerStaticVariable("currentProjMatInv", self.currentProjMatInv) self.renderPassManager.registerStaticVariable("zeroVec2", Vec2(0)) self.renderPassManager.registerStaticVariable("zeroVec3", Vec3(0)) self.renderPassManager.registerStaticVariable("zeroVec4", Vec4(0)) self.transformMat = TransformState.makeMat(Mat4.convertMat(CSYupRight, CSZupRight))
def load(self): self.root = NodePath('PartyCog-%d' % self.id) self.root.reparentTo(self.parentNode) path = 'phase_13/models/parties/cogPinata_' self.actor = Actor( path + 'actor', { 'idle': path + 'idle_anim', 'down': path + 'down_anim', 'up': path + 'up_anim', 'bodyHitBack': path + 'bodyHitBack_anim', 'bodyHitFront': path + 'bodyHitFront_anim', 'headHitBack': path + 'headHitBack_anim', 'headHitFront': path + 'headHitFront_anim' }) self.actor.setBlend( frameBlend=config.GetBool('interpolate-animations', True)) self.actor.reparentTo(self.root) self.temp_transform = Mat4() self.head_locator = self.actor.attachNewNode('temphead') self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75) self.bodyColl.setTangible(1) self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' % self.id) self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.bodyCollNode.addSolid(self.bodyColl) self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode) self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5) self.headColl.setTangible(1) self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' % self.id) self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.headCollNode.addSolid(self.headColl) self.headCollNodePath = self.root.attachNewNode(self.headCollNode) self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0) self.arm1Coll.setTangible(1) self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' % self.id) self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm1CollNode.addSolid(self.arm1Coll) self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode) self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0) self.arm2Coll.setTangible(1) self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' % self.id) self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm2CollNode.addSolid(self.arm2Coll) self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode) splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound( 'AA_wholepie_only.ogg') self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg') self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole') self.hole.setTransparency(True) self.hole.setP(-90.0) self.hole.setScale(3) self.hole.setBin('ground', 3) self.hole.reparentTo(self.parentNode)
def getMat4_scale_unit_quad_to_image_aspect_ratio_forrowvecs( image_width_pixels, image_height_pixels): # the height stays constant (height of 1 in world coords) quad_scalex = float(image_width_pixels) quad_scalez = float(image_height_pixels) return Mat4(quad_scalex * 1., 0, 0, 0, 0, 1, 0, 0, 0, 0, quad_scalez * 1., 0, 0, 0, 0, 1)
def __init__(self): """ Creates a new ShadowSource. After the creation, a lens can be added with setupPerspectiveLens or setupOrtographicLens. """ self.index = self._generateUID() DebugObject.__init__(self, "ShadowSource-" + str(self.index)) ShaderStructElement.__init__(self) self.valid = False self.camera = Camera("ShadowSource-" + str(self.index)) self.camera.setActive(False) self.cameraNode = NodePath(self.camera) self.cameraNode.reparentTo(Globals.render.find("RPCameraDummys")) self.cameraNode.hide() self.resolution = 512 self.atlasPos = Vec2(0) self.doesHaveAtlasPos = False self.sourceIndex = 0 self.mvp = UnalignedLMatrix4f() self.sourceIndex = -1 self.nearPlane = 0.0 self.farPlane = 1000.0 self.converterYUR = None self.transforMat = TransformState.makeMat( Mat4.convertMat( Globals.base.win.getGsg().getInternalCoordinateSystem(), CSZupRight))
class PbCameraNode(NodePath): """Pybullet-compatible camera node wrapper """ Z2Y = Mat4(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1) def __init__(self, render: NodePath): self._camera = Camera('pb_camera') self._lens = MatrixLens() self._camera.set_lens(self._lens) super().__init__(self._camera) self.reparent_to(render) def set_active(self, active: bool): self._camera.set_active(active) def is_active(self): return self._camera.is_active() def update(self, pb_camera): self.set_mat(self.Z2Y * Mat4(*pb_camera.pose_mat)) mat = np.asarray(pb_camera.proj_mat).reshape(4, 4) m22, m32 = -mat[2, 2], -mat[3, 2] zfar = (2.0 * m32) / (2.0 * m22 - 2.0) znear = ((m22 - 1.0) * zfar) / (m22 + 1.0) self._lens.set_near_far(znear, zfar) self._lens.set_user_mat(self.Z2Y * Mat4(*pb_camera.proj_mat))
def update_scene(self, scene_graph, materials_only): """Update a scene using scene_graph description Arguments: scene_graph {SceneGraph} -- scene description materials_only {bool} -- update only shape materials """ for uid, pb_node in scene_graph.nodes.items(): node = NodePath(f'pb_node_{uid:03d}') for pb_shape in pb_node.shapes: filename = shape_filename(pb_shape) if not filename: continue shape = self._loader.load_model(filename) shape.set_mat(Mat4(*pb_shape.pose.matrix)) shape.reparent_to(node) if shape.has_material: shape.set_material(PbMaterial(pb_shape.material), 1) texture_id = pb_shape.material.diffuse_texture if texture_id > -1: texture = scene_graph.texture(texture_id) shape.set_texture(texture.filename) node.flatten_light() node.reparent_to(self.scene) self._node_dict[uid] = node
def __init__(self): """ Creates a new ShadowSource. After the creation, a lens can be added with setupPerspectiveLens or setupOrtographicLens. """ self.index = self._generateUID() DebugObject.__init__(self, "ShadowSource-" + str(self.index)) ShaderStructElement.__init__(self) self.valid = False self.camera = Camera("ShadowSource-" + str(self.index)) self.camera.setActive(False) self.cameraNode = NodePath(self.camera) self.cameraNode.reparentTo(Globals.render.find("RPCameraDummys")) self.cameraNode.hide() self.resolution = 512 self.atlasPos = Vec2(0) self.doesHaveAtlasPos = False self.sourceIndex = 0 self.mvp = UnalignedLMatrix4f() self.sourceIndex = -1 self.nearPlane = 0.0 self.farPlane = 1000.0 self.converterYUR = None self.transforMat = TransformState.makeMat( Mat4.convertMat(Globals.base.win.getGsg().getInternalCoordinateSystem(), CSZupRight))
def __init__(self): """ Constructs a new Light, subclasses have to call this """ DebugObject.__init__(self, "AbstractLight") ShaderStructElement.__init__(self) self.debugNode = NodePath("LightDebug") self.visualizationNumSteps = 32 self.dataNeedsUpdate = False self.castShadows = False self.debugEnabled = False self.bounds = OmniBoundingVolume() self.shadowSources = [] self.lightType = self.getLightType() self.position = Vec3(0) self.color = Vec3(1) self.posterIndex = -1 self.radius = 10.0 self.typeName = "" self.sourceIndexes = PTAInt.emptyArray(6) self.attached = False self.shadowResolution = 512 self.index = -1 self.iesProfile = -1 self.iesProfileName = None self.mvp = Mat4() # A light can have up to 6 sources for i in range(6): self.sourceIndexes[i] = -1
def getMat4_scale_quad_for_texture_pixels_to_match_screen_resolution(): # a single unit takes an amount of pixels of the p3d window # by convention here, the height of what the initial fixed camera # displays is exactly 2, i.e. the distance d((0,0,-1), (0,0,1)) pixels_per_unit = get_pixels_per_unit() return Mat4(1. / pixels_per_unit, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1. / pixels_per_unit, 0, 0, 0, 0, 1)
def set_perspective_lens(self, fov, near_plane, far_plane, pos, direction): transform_mat = Mat4.translate_mat(-pos) temp_lens = PerspectiveLens(fov, fov) temp_lens.set_film_offset(0, 0) temp_lens.set_near_far(near_plane, far_plane) temp_lens.set_view_vector(direction, LVector3.up()) self.set_matrix_lens(transform_mat * temp_lens.get_projection_mat())
def pandaMatrice(self,mat): mat = mat.transpose().reshape((16,)) # print mat,len(mat),mat.shape pMat = Mat4(mat[0],mat[1],mat[2],mat[3], mat[4],mat[5],mat[6],mat[7], mat[8],mat[9],mat[10],mat[11], mat[12],mat[13],mat[14],mat[15],) return pMat
def __init__(self): self.instructionText = addInstructions(0.95, '[ESC]: Leave Mouselook mode.') self.eventDispatcher = EventDispatcher() self.cameraMode = None self.clickPos = Vec2() self.lastMousePos = Vec2() self.focus = Vec3() self.mouseDown = False self.initialPos = Vec3() self.initialHpr = Vec3() self.initialMat = None # Disable the built-in mouse camera control (it sucks). base.disableMouse() self.setCameraMode(TRACKBALL) # Set the camera's initial position. base.camera.setPosHpr(0, 12, 30, 180, -70, 0) # Turn off events generated with modifier buttons, e.g. 'shift-a' # This is to keep keyboard control working after you alt-tab out # of the app. base.mouseWatcherNode.setModifierButtons(ModifierButtons()) base.buttonThrowers[0].node().setModifierButtons(ModifierButtons()) # This is a diagonal matrix that keeps track of movement key # state. The first three diagonal entries can be 1, 0, or -1. self.mouseLookTransMat = Mat4.scaleMat(Vec3(0.0, 0.0, 0.0)) # Keep track of how many movement keys are currently pressed. This # lets us short-circuit past a lot of math when no keys are held. self.keysHeld = 0 # Handle events for the movement keys. for key, value in key2MatArgs.items(): self.accept(key, self._moveKeyHandler, value) self.accept('escape', self._escKeyHandler) self.accept('m', self._mKeyHandler) self.accept('mouse1', self._mouseDownHandler, [1]) self.accept('mouse1-up', self._mouseUpHandler, [1]) self.accept('mouse2', self._mouseDownHandler, [2]) self.accept('mouse2-up', self._mouseUpHandler, [2]) self.accept('wheel_up', self._mouseWheelHandler, [1]) self.accept('wheel_down', self._mouseWheelHandler, [-1]) self.modButtons = ModifierButtons() self.modButtons.addButton(KeyboardButton.control()) self.accept('control', self.modButtons.buttonDown, [KeyboardButton.control()]) self.accept('control-up', self.modButtons.buttonUp, [KeyboardButton.control()]) self.accept(base.win.getWindowEvent(), self._windowHandler)
def set_perspective_lens(self, fov, near_plane, far_plane, pos, direction): transform_mat = Mat4.translate_mat(-pos) temp_lens = PerspectiveLens(fov, fov) temp_lens.set_film_offset(0, 0) temp_lens.set_near_far(near_plane, far_plane) temp_lens.set_view_vector(direction, LVector3.up()) self.set_matrix_lens(transform_mat * temp_lens.get_projection_mat()) hexahedron = temp_lens.make_bounds() center = (hexahedron.get_min() + hexahedron.get_max()) * 0.5 self._bounds = BoundingSphere(pos + center, (hexahedron.get_max() - center).length())
def computeMVP(self): """ Computes the modelViewProjection matrix for the lens. Actually, this is the worldViewProjection matrix, but for convenience it is called mvp. """ projMat = self.converterYUR transformMat = TransformState.makeMat( Mat4.convertMat(Globals.base.win.getGsg().getInternalCoordinateSystem(), CSZupRight)) modelViewMat = transformMat.invertCompose( Globals.render.getTransform(self.cameraNode)).getMat() self.mvp = UnalignedLMatrix4f(modelViewMat * projMat)
def drawLeaf(nodePath,vdata,pos=Vec3(0,0,0),vecList=[Vec3(0,0,1), Vec3(1,0,0),Vec3(0,-1,0)], scale=0.125): #use the vectors that describe the direction the branch grows to make the right #rotation matrix newCs=Mat4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) newCs.setRow(0, vecList[2]) #right newCs.setRow(1, vecList[1]) #up newCs.setRow(2, vecList[0]) #forward newCs.setRow(3, Vec3(0,0,0)) newCs.setCol(3,Vec4(0,0,0,1)) axisAdj=Mat4.scaleMat(scale)*newCs*Mat4.translateMat(pos) #orginlly made the leaf out of geometry but that didnt look good #I also think there should be a better way to handle the leaf texture other than #hardcoding the filename leafModel=loader.loadModel('models/shrubbery') leafTexture=loader.loadTexture('models/material-10-cl.png') leafModel.reparentTo(nodePath) leafModel.setTexture(leafTexture,1) leafModel.setTransform(TransformState.makeMat(axisAdj))
def do_update(self): """ Updates the commonly used resources, mostly the shader inputs """ update = self._input_ubo.update_input # Get the current transform matrix of the camera view_mat = Globals.render.get_transform(self._showbase.cam).get_mat() # Compute the view matrix, but with a z-up coordinate system update("view_mat_z_up", view_mat * Mat4.convert_mat(CS_zup_right, CS_yup_right)) # Compute the view matrix without the camera rotation view_mat_billboard = Mat4(view_mat) view_mat_billboard.set_row(0, Vec3(1, 0, 0)) view_mat_billboard.set_row(1, Vec3(0, 1, 0)) view_mat_billboard.set_row(2, Vec3(0, 0, 1)) update("view_mat_billboard", view_mat_billboard) update("camera_pos", self._showbase.camera.get_pos(Globals.render)) update("last_view_proj_mat_no_jitter", self._input_ubo.get_input("view_proj_mat_no_jitter")) proj_mat = Mat4(self._showbase.camLens.get_projection_mat()) # Set the projection matrix as an input, but convert it to the correct # coordinate system before. proj_mat_zup = Mat4.convert_mat(CS_yup_right, CS_zup_right) * proj_mat update("proj_mat", proj_mat_zup) # Set the inverse projection matrix update("inv_proj_mat", invert(proj_mat_zup)) # Remove jitter and set the new view projection mat proj_mat.set_cell(1, 0, 0.0) proj_mat.set_cell(1, 1, 0.0) update("view_proj_mat_no_jitter", view_mat * proj_mat) # Store the frame delta update("frame_delta", Globals.clock.get_dt()) update("frame_time", Globals.clock.get_frame_time())
def mousePressed(self, event): self.parent.beginTransformation() self.lens = base.cam.node().getLens() scale = Mat4.scaleMat(self.path.getScale(base.camera)) descale = Mat4() descale.invertAffineFrom(scale) mvMat = descale * self.path.getMat(base.camera) self.origin = Point3(mvMat.xformPoint(Point3())) self.planeNorm = Vec3(mvMat.xformVec(Vec3(0, 0, 1))) self.planeNorm.normalize() self.d = self.planeNorm.dot(self.origin) self.fromCam = base.camera.getMat(self.parent.path) * scale self.dir = Vec3(self.mouse2Vec(event.pos)) self.dir.normalize()
def __init__(self, pipeline): DebugObject.__init__(self, "ProjectedWaterGrid") self.debug("Creating water grid") self.waterLevel = 0.0 self.model = Globals.loader.loadModel("Data/InternalModels/ScreenSpaceGrid.bam") self.model.reparentTo(Globals.base.render) self.model.node().setFinal(True) self.model.node().setBounds(OmniBoundingVolume()) self.model.setTwoSided(True) self.model.setShaderInput("waterHeight", self.waterLevel) self.model.setMat(Mat4.identMat()) self.model.clearTransform() foam = Globals.loader.loadTexture("Data/Textures/WaterFoam.png") self.model.setShaderInput("waterFoam", foam) self.manager = WaterManager() self.manager.setup() self.manager.update() self.model.setShaderInput("waterHeightfield", self.manager.getDisplacementTexture()) self.model.setShaderInput("waterNormal", self.manager.getNormalTexture()) # Set texture filter modes for tex in [foam, self.manager.getDisplacementTexture(), self.manager.getNormalTexture()]: tex.setWrapU(SamplerState.WMRepeat) tex.setWrapU(SamplerState.WMRepeat) tex.setMinfilter(SamplerState.FTLinearMipmapLinear) tex.setMagfilter(SamplerState.FTLinearMipmapLinear) self.pipeline = pipeline self.pipeline.setEffect(self.model, "Effects/Water/ProjectedWater.effect", { # "transparent": True "castShadows": False # "tesselated": True }) # pipeline.convertToPatches(self.model) pipeline.showbase.addTask(self.updateTask, "updateWater")
def rebuildMatrixCache(self): """ Computes values frequently used to compute the mvp """ self.converterYUR = Mat4.convertMat(CSYupRight, self.lens.getCoordinateSystem()) * self.lens.getProjectionMat()
def mouseMoved(self, event): transl = self.fromCam.xformVec(self.mouse2Vec(event.pos)) self.parent.transform(Mat4.translateMat(transl))
def rotsToMat4(x, y, z): rotx = Mat4(1,0,0,0,0,cos(x),-sin(x),0,0,sin(x),cos(x),0,0,0,0,1); roty = Mat4(cos(y),0,sin(y),0,0,1,0,0,-sin(y),0,cos(y),0,0,0,0,1); rotz = Mat4(cos(z),-sin(z),0,0,sin(z),cos(z),0,0,0,0,1,0,0,0,0,1); swapyz = Mat4.rotateMat(90, Vec3(-1,0,0)) return rotx * roty * rotz * swapyz
def update(self): """ Updates the commonly used resources, mostly the shader inputs """ update = self._input_ubo.update_input # Get the current transform matrix of the camera view_mat = Globals.render.get_transform(self._showbase.cam).get_mat() # Compute the view matrix, but with a z-up coordinate system update("view_mat_z_up", view_mat * Mat4.convert_mat(CS_zup_right, CS_yup_right)) # Compute the view matrix without the camera rotation view_mat_billboard = Mat4(view_mat) view_mat_billboard.set_row(0, Vec3(1, 0, 0)) view_mat_billboard.set_row(1, Vec3(0, 1, 0)) view_mat_billboard.set_row(2, Vec3(0, 0, 1)) update("view_mat_billboard", view_mat_billboard) update("camera_pos", self._showbase.camera.get_pos(Globals.render)) # Compute last view projection mat curr_vp = self._input_ubo.get_input("view_proj_mat_no_jitter") update("last_view_proj_mat_no_jitter", curr_vp) curr_vp = Mat4(curr_vp) curr_vp.invert_in_place() curr_inv_vp = curr_vp update("last_inv_view_proj_mat_no_jitter", curr_inv_vp) proj_mat = Mat4(self._showbase.camLens.get_projection_mat()) # Set the projection matrix as an input, but convert it to the correct # coordinate system before. proj_mat_zup = Mat4.convert_mat(CS_yup_right, CS_zup_right) * proj_mat update("proj_mat", proj_mat_zup) # Set the inverse projection matrix update("inv_proj_mat", invert(proj_mat_zup)) # Remove jitter and set the new view projection mat proj_mat.set_cell(1, 0, 0.0) proj_mat.set_cell(1, 1, 0.0) update("view_proj_mat_no_jitter", view_mat * proj_mat) # Store the frame delta update("frame_delta", Globals.clock.get_dt()) update("smooth_frame_delta", 1.0 / max(1e-5, Globals.clock.get_average_frame_rate())) update("frame_time", Globals.clock.get_frame_time()) # Store the current film offset, we use this to compute the pixel-perfect # velocity, which is otherwise not possible. Usually this is always 0 # except when SMAA and reprojection is enabled update("current_film_offset", self._showbase.camLens.get_film_offset()) update("frame_index", Globals.clock.get_frame_count()) # Compute frustum corners in the order BL, BR, TL, TR ws_frustum_directions = Mat4() vs_frustum_directions = Mat4() inv_proj_mat = Globals.base.camLens.get_projection_mat_inv() view_mat_inv = Mat4(view_mat) view_mat_inv.invert_in_place() for i, point in enumerate(((-1, -1), (1, -1), (-1, 1), (1, 1))): result = inv_proj_mat.xform(Vec4(point[0], point[1], 1.0, 1.0)) vs_dir = result.xyz.normalized() vs_frustum_directions.set_row(i, Vec4(vs_dir, 1)) ws_dir = view_mat_inv.xform(Vec4(result.xyz, 0)) ws_frustum_directions.set_row(i, ws_dir) update("vs_frustum_directions", vs_frustum_directions) update("ws_frustum_directions", ws_frustum_directions)
def __init__(self): load_prc_file_data("", "win-size 512 512") # load_prc_file_data("", "window-type offscreen") load_prc_file_data("", "model-cache-dir") load_prc_file_data("", "model-cache-textures #f") load_prc_file_data("", "textures-power-2 none") load_prc_file_data("", "alpha-bits 0") load_prc_file_data("", "print-pipe-types #f") # Construct render pipeline self.render_pipeline = RenderPipeline() self.render_pipeline.mount_mgr.config_dir = "config/" self.render_pipeline.set_empty_loading_screen() self.render_pipeline.create(self) self.setup_scene() # Disable model caching BamCache.get_global_ptr().cache_models = False self.update_queue = [] self.start_listen() # Render initial frames for i in range(10): self.taskMgr.step() last_update = 0.0 self.scene_node = None current_lights = [] current_envprobes = [] # Wait for updates while True: # Update once in a while curr_time = time.time() if curr_time > last_update + 1.0: last_update = curr_time self.taskMgr.step() if self.update_queue: if self.scene_node: self.scene_node.remove_node() # Only take the latest packet payload = self.update_queue.pop(0) print("RENDERING:", payload) scene = loader.loadModel(Filename.from_os_specific(payload["scene"])) for light in scene.find_all_matches("**/+PointLight"): light.remove_node() for light in scene.find_all_matches("**/+Spotlight"): light.remove_node() # Find camera main_cam = scene.find("**/Camera") if main_cam: transform_mat = main_cam.get_transform(render).get_mat() transform_mat = Mat4.convert_mat(CS_zup_right, CS_yup_right) * transform_mat base.camera.set_mat(transform_mat) else: print("WARNING: No camera found") base.camera.set_pos(0, -3.5, 0) base.camera.look_at(0, -2.5, 0) base.camLens.set_fov(64.0) self.scene_node = scene scene.reparent_to(render) # Render scene for i in range(8): self.taskMgr.step() dest_path = Filename.from_os_specific(payload["dest"]) print("Saving screenshot to", dest_path) self.win.save_screenshot(dest_path) self.notify_about_finish(int(payload["pingback_port"]))
def handleDragging(self, task): """ Does the actual work of manipulating objects, once the needed attributes have been setup by handleManipulationSetup(). """ if not self.isDragging: return task.done mPos3D = Point3(0.0) # # This section handles the actual translating rotating or scale after it's been set up in mouse1SetupManip...() # ONLY one operation is preformed per frame if self.currTransformOperation == self.transformOpEnum.trans: # 1st translation, rotation's section is at next elif if self.getMousePlaneIntersect(mPos3D, self.currPlaneColNorm): # get the difference between the last mouse and this frames mouse selectedNewPos = mPos3D - self.interFrameMousePosition # store this frames mouse self.interFrameMousePosition = mPos3D # add the difference to the selected object's pos self.selected.setPos(render, self.selected.getPos(render).x + self.currTransformDir.x * selectedNewPos.x, self.selected.getPos(render).y + self.currTransformDir.y * selectedNewPos.y, self.selected.getPos(render).z + self.currTransformDir.z * selectedNewPos.z) self.grabModelNP.setPos(render, self.selected.getPos(render)) elif self.currTransformOperation == self.transformOpEnum.rot: # 2nd rotation, followed finally by scaling # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal) mPos = base.mouseWatcherNode.getMouse() #rotMag = 0.0 if self.currTransformDir == Vec3( 0.0, 0.0, 1.0): rotMag = (mPos.x - self.interFrameMousePosition.x) * 1000 else: rotMag = (self.interFrameMousePosition.y - mPos.y) * 1000 initPos = self.selected.getPos() initPar = self.selected.getParent() self.selected.wrtReparentTo(render) self.selected.setMat(self.selected.getMat() * Mat4.rotateMat(rotMag, self.currTransformDir)) self.selected.wrtReparentTo(initPar) self.selected.setPos(initPos) self.interFrameMousePosition = Point3(mPos.x, mPos.y, 0.0) elif self.currTransformOperation == self.transformOpEnum.scale: # 3rd and final is scaling mPos = base.mouseWatcherNode.getMouse() # TODO: make dragging away from the object larger and to the object smaller (not simply left right up down) # td The problem with this MAY come if negative, mirrored, scaling is implemented. # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal) if self.currTransformDir == Point3( 0.0, 0.0, 1.0): sclMag = (mPos.y - self.interFrameMousePosition.y) * 5.5 elif self.currTransformDir == Point3( 0.0, 1.0, 0.0): sclMag = (mPos.x - self.interFrameMousePosition.x) * 5.5 else: sclMag = (self.interFrameMousePosition.x - mPos.x) * 5.5 # This is the line that prevents scaling past the origin. Flipping the faces doesn't seem to work. if -0.0001 < sclMag < 0.0001: sclMag = 0.000001 # create a dummy node to parent to and position such that applying scale to it will scale selected properly dummy = self.levitorNP.attachNewNode('dummy') initScl = dummy.getScale() # Don't forget the parent. Selected needs put back in place initPar = self.selected.getParent() initPos = self.selected.getPos() self.selected.wrtReparentTo(dummy) dummy.setScale(initScl.x + sclMag * self.currTransformDir.x, initScl.y + sclMag * self.currTransformDir.y, initScl.z + sclMag * self.currTransformDir.z) # reset selected's parent then destroy dummy self.selected.wrtReparentTo(initPar) self.selected.setPos(initPos) dummy.removeNode() dummy = None self.interFrameMousePosition = Point3( mPos.x, mPos.y, 0.0) else: self.notify.error("Err: Dragging with invalid curTransformOperation enum in handleDragging") return task.cont # ended by handleM1Up(), the mouse1-up event handler
def _mouseWheelHandler(self, arg): deltY = base.camera.getPos().length() * arg * 0.15 transl = Mat4.translateMat(0, deltY, 0) base.camera.setMat(transl * base.camera.getMat()) self.eventDispatcher.dispatchEvent(EVT_CAMERA_MOVE, base.camera)