class MyApp(ShowBase): def __init__(self, markerImage='marker.jpg', calib_file='test.npz'): ShowBase.__init__(self) base.disableMouse() self.marker = cv2.imread(markerImage) self.marker = cv2.flip(self.marker, 0) self.kp_marker, self.des_marker = getDes(self.marker) if useCamera: self.cap = cv2.VideoCapture(0) ret, frame = self.cap.read() else: ret, frame = True, cv2.imread("sample_0.jpg") if ret: self.frame = frame self.criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) with np.load(calib_file) as calib_File: self.K = calib_File['mtx'] self.D = calib_File['coef'] (h, w) = frame.shape[0:2] print w, h far = 100 near = 0.1 fovx, fovy, f, (cx, cy), a = cv2.calibrationMatrixValues( self.K, (w, h), w, h) print fovx, fovy, f, cx, cy base.camLens.setFilmSize(w, h) base.camLens.setFilmOffset(w * 0.5 - cx, h * 0.5 - cy) base.camLens.setFocalLength(f) base.camLens.setFov(fovx, fovy) base.camLens.setNearFar(near, far) #base.camLens.setCoordinateSystem(4) base.camLens.setCoordinateSystem(4) #base.camLens.setViewVector(Vec3(0,0,1), Vec3(0,1,0)) #self.render.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullCounterClockwise)) self.tex = Texture("detect") #self.buff.getTexture() self.tex.setCompression(Texture.CMOff) self.tex.setup2dTexture(w, h, Texture.TUnsignedByte, Texture.FRgb) self.b = OnscreenImage(parent=render2d, image=self.tex) base.cam.node().getDisplayRegion(0).setSort(20) self.taskMgr.add(self.updateFrameTask, "UpdateCameraFrameTask") self.modelroot = NodePath('ARRootNode') self.modelroot.reparentTo(self.render) ''' self.x = self.loader.loadModel("models/box") self.x.reparentTo(self.modelroot) self.x.setScale(3, 0.1, 0.1) self.x.setPos(0, -0.05, -0.05) self.x.setColor(1,0,0,1,1) self.y = self.loader.loadModel("models/box") self.y.reparentTo(self.modelroot) self.y.setScale(0.1, 3, 0.1) self.y.setPos(-0.05, 0, -0.05) self.y.setColor(0,1,0,1,1) self.z = self.loader.loadModel("models/box") self.z.reparentTo(self.modelroot) self.z.setScale(0.1, 0.1, 3) self.z.setPos(-0.05, -0.05, 0) self.z.setColor(0,0,1,1,1) ''' self.panda = NodePath('PandaRoot') self.panda.reparentTo(self.modelroot) # Load and transform the panda actor. self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.003, 0.003, 0.003) self.pandaActor.reparentTo(self.panda) self.pandaActor.loop("walk") self.pandaActor.setH(180) #self.pandaMotion = MopathInterval("Panda Path", self.panda, "Interval Name") self.pathCurve = createNurbsCurve() for i in range(0, 30): self.pathCurve.addPoint( (random.uniform(1, 7), random.uniform(1, 7), 0)) ''' self.pathCurve.addPoint((1, 5, 0)) self.pathCurve.addPoint((5, 5, 0)) self.pathCurve.addPoint((5, 1, 0)) self.pathCurve.addPoint((1, 1, 0)) ''' curveNode = self.pathCurve.getNodepath() self.myMopath = Mopath() self.myMopath.loadNodePath(curveNode) self.myMopath.fFaceForward = True myInterval = MopathInterval(self.myMopath, self.panda, duration=100, name="Name") myInterval.loop() # This task runs for two seconds, then prints done def updateFrameTask(self, task): if useCamera: ret, frame = self.cap.read() else: ret, frame = True, self.frame if ret: frame = cv2.flip(frame, 0) kp_frame, des_frame = getDes(frame) matches = getMatches(self.des_marker, des_frame) if not matches or len(matches) < 5: return task.cont pattern_points = [self.kp_marker[pt.trainIdx].pt for pt in matches] pattern_points = np.array([(x / 50.0, y / 50.0, 0) for x, y in pattern_points], dtype=np.float32) image_points = np.array( [kp_frame[pt.queryIdx].pt for pt in matches], dtype=np.float32) #ret, rvecs, tvecs = cv2.solvePnP(pattern_points, image_points, self.K, None) rvecs, tvecs, inliers = cv2.solvePnPRansac(pattern_points, image_points, self.K, None) #print "Tadam!",rvecs, tvecs #img_pts, jac = cv2.projectPoints(axis, rvecs, tvecs, camera_matrix, dist_coefs) #draw_lines(image, img_pts) T = tvecs.ravel() R = rvecs.ravel() RotM, _ = cv2.Rodrigues(R) RotM = RotM.T RotM = Mat3( RotM[0, 0], RotM[0, 1], RotM[0, 2], RotM[1, 0], RotM[1, 1], RotM[1, 2], # RotM[2,0],RotM[2,1],RotM[2,2]) -RotM[2, 0], -RotM[2, 1], -RotM[2, 2]) self.modelroot.setMat(Mat4(RotM, Vec3(T[0], T[1], T[2]))) self.tex.setRamImage(frame) self.b.setImage(image=self.tex, parent=render2d) self.camera.setPos(0, 0, 0) self.camera.setHpr(0, 0, 0) self.camera.setScale(1, 1, 1) return task.cont
class Effect: baseWidth = 0 baseHeight = 0 effectWidth = 1 effectHeight = 1 effectTargetMS = 143 noSampling = False tex = None loadedFormat = None # Animation variables internalFrameIndex = 1 startIndex = 1 endIndex = 1 loopEffect = False # XML variables tree = None frames = None colors = None tweens = None compositeFrames = None # Nodes consumedNodesList = None # Accessible object (nodePath) effectCameraNodePath = None effectCardNodePath = None # Constant value; Unit comparison for card size; basis is from cure, which is [140x110] cardDimensionBasis = [-5.0, 5.0, 0.0, 10.0, 140.0, 110.0] pixelScaleX = cardDimensionBasis[4] / (cardDimensionBasis[1] - cardDimensionBasis[0]) pixelScaleZ = cardDimensionBasis[5] / (cardDimensionBasis[3] - cardDimensionBasis[2]) effectIsCentered = True effectAdjustment = [0, 0, 0] def __init__(self, effectFileName, parent=None, loop=False, effectIsCentered=True, effectAdjustment=[0, 0, 0]): self.effectAdjustment = effectAdjustment self.loopEffect = loop self.effectIsCentered = effectIsCentered self.loadedFormat = None if effectFileName != None: effectFileNameSplit = effectFileName.split(".") self.loadedFormat = effectFileNameSplit[len(effectFileNameSplit) - 2] # Get value at penultimate index if self.loadedFormat == effectFileNameSplit[0]: self.loadedFormat = None # Get rid of bad format name. pass # Load texture; supply alpha channel if it doesn't exist. p = transparencyKey(effectFileName) self.tex = Texture() self.tex.setup2dTexture(p.getXSize(), p.getYSize(), Texture.TUnsignedByte, Texture.FRgba) self.tex.load(p) if self.loadedFormat != None: try: self.tree = etree.parse("./" + GAME + "/effects/" + self.loadedFormat + "/sprite.xml") except IOError: self.loadedFormat = None pass if self.loadedFormat != None: root = self.tree.getroot() self.frames = root.find(".//frames") self.colors = root.find(".//colors") self.tweens = root.find(".//motion-tweens") self.compositeFrames = root.find(".//composite-frames") self.baseWidth = 0 if root.attrib.get("base-width") == None else float(root.attrib.get("base-width")) self.baseHeight = 0 if root.attrib.get("base-height") == None else float(root.attrib.get("base-height")) self.effectWidth = 1 if root.attrib.get("frame-width") == None else float(root.attrib.get("frame-width")) self.effectHeight = 1 if root.attrib.get("frame-height") == None else float(root.attrib.get("frame-height")) self.effectTargetMS = 143 if root.attrib.get("target-ms") == None else float(root.attrib.get("target-ms")) self.startIndex = 1 if root.attrib.get("target-start") == None else int(root.attrib.get("target-start")) self.endIndex = 1 if root.attrib.get("target-end") == None else int(root.attrib.get("target-end")) self.noSampling = False if root.attrib.get("no-sampling") == None else bool(root.attrib.get("no-sampling")) if self.noSampling == True: self.tex.setMagfilter(Texture.FTNearest) self.tex.setMinfilter(Texture.FTNearest) cm = CardMaker("card-" + effectFileName) cardDeltaX = self.effectWidth / self.pixelScaleX cardDeltaZ = self.effectHeight / self.pixelScaleZ if self.effectIsCentered == True: cm.setFrame(0, 0, 0, 0) deltaX = (cardDeltaX / 2.0) - (-cardDeltaX / 2.0) deltaY = 0 deltaZ = (cardDeltaZ / 2.0) - (-cardDeltaZ / 2.0) # occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, (-cardDeltaZ/2.0)), Point3((-cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (-cardDeltaZ/2.0))) else: cm.setFrame(0, 0, 0, 0) deltaX = (cardDeltaX / 2.0) - (-cardDeltaX / 2.0) deltaY = 0 deltaZ = cardDeltaZ - 0 # occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, 0), Point3((-cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, 0)) self.effectCardNodePath = render.attachNewNode(cm.generate()) self.effectCardNodePath.setBillboardPointEye() self.effectCardNodePath.reparentTo(parent) # occluder_nodepath = self.effectCardNodePath.attachNewNode(occluder) # self.effectCardNodePath.setOccluder(occluder_nodepath) emptyNode = NodePath("effect-parent-translator") emptyNode.reparentTo(self.effectCardNodePath) if effectIsCentered == True: emptyNode.setPos( -deltaX / 2.0 + self.effectAdjustment[0], 0 + self.effectAdjustment[1], deltaZ / 2.0 + self.effectAdjustment[2], ) else: emptyNode.setPos( -deltaX / 2.0 + self.effectAdjustment[0], 0 + self.effectAdjustment[1], deltaZ + self.effectAdjustment[2], ) # emptyNode.place() emptyNode.setSx(float(deltaX) / self.effectWidth) emptyNode.setSz(float(deltaZ) / self.effectHeight) self.effectCameraNodePath = emptyNode if parent != None: self.effectCardNodePath.reparentTo(parent) else: self.effectCardNodePath.reparentTo(render) # self.effectCardNodePath.place() self.effectCardNodePath.setBin("fixed", 40) self.effectCardNodePath.setDepthTest(False) self.effectCardNodePath.setDepthWrite(False) pass def getSequence(self): sequence = Sequence() for x in range(self.startIndex, self.endIndex, 1): sequence.append(Func(self.pandaRender)) sequence.append(Func(self.advanceFrame)) sequence.append(Wait(self.effectTargetMS * 0.001)) sequence.append(Func(self.clearNodesForDrawing)) sequence.append(Func(self.advanceFrame)) sequence.append(Wait(self.effectTargetMS * 0.001)) return sequence pass def hasEffectFinished(self): if self.internalFrameIndex > self.endIndex and self.loopEffect == False: return True else: return False pass def advanceFrame(self): if self.internalFrameIndex < self.endIndex: self.internalFrameIndex += 1 elif self.internalFrameIndex == self.endIndex and self.loopEffect == True: self.internalFrameIndex = self.startIndex else: self.internalFrameIndex = self.endIndex + 1 self.clearNodesForDrawing() pass def clearNodesForDrawing(self): if False: self.effectCameraNodePath.analyze() if self.consumedNodesList != None and self.consumedNodesList != []: for consumedNode in self.consumedNodesList: consumedNode.removeNode() self.consumedNodesList = [] pass def pandaRender(self): frameList = [] for node in self.compositeFrames.getiterator("composite-frame"): if node.tag == "composite-frame" and node.attrib.get("id") == str(self.internalFrameIndex): for frameCallNode in node: for frameNode in self.frames.getiterator("frame"): if frameNode.tag == "frame" and frameNode.attrib.get("id") == frameCallNode.attrib.get("id"): offsetX = ( 0 if frameCallNode.attrib.get("offset-x") == None else float(frameCallNode.attrib.get("offset-x")) ) offsetY = ( 0 if frameCallNode.attrib.get("offset-y") == None else float(frameCallNode.attrib.get("offset-y")) ) tweenId = frameCallNode.attrib.get("tween") frameInTween = ( 0 if frameCallNode.attrib.get("frame-in-tween") == None else int(frameCallNode.attrib.get("frame-in-tween")) ) addWidth = 0 if frameNode.attrib.get("w") == None else float(frameNode.attrib.get("w")) addHeight = 0 if frameNode.attrib.get("h") == None else float(frameNode.attrib.get("h")) sInPixels = 0 if frameNode.attrib.get("s") == None else float(frameNode.attrib.get("s")) tInPixels = 0 if frameNode.attrib.get("t") == None else float(frameNode.attrib.get("t")) swInPixels = sInPixels + addWidth thInPixels = tInPixels + addHeight s = sInPixels / self.baseWidth t = 1 - ( tInPixels / self.baseHeight ) # Complemented to deal with loading image upside down. S = swInPixels / self.baseWidth T = 1 - ( thInPixels / self.baseHeight ) # Complemented to deal with loading image upside down. blend = ( "overwrite" if frameCallNode.attrib.get("blend") == None else frameCallNode.attrib.get("blend") ) scaleX = ( 1 if frameCallNode.attrib.get("scale-x") == None else float(frameCallNode.attrib.get("scale-x")) ) scaleY = ( 1 if frameCallNode.attrib.get("scale-y") == None else float(frameCallNode.attrib.get("scale-y")) ) color = Color(1, 1, 1, 1) tweenHasColor = False frameCallHasColor = False frameCallColorName = frameCallNode.attrib.get("color-name") if frameCallColorName != None: # Get color at frame call as first resort. frameCallHasColor = True for colorNode in self.colors.getiterator("color"): if colorNode.tag == "color" and colorNode.attrib.get("name") == frameCallColorName: R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r")) G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g")) B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b")) A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a")) color = Color(R, G, B, A) break # leave for loop when we find the correct color pass if tweenId != None and tweenId != "0": # Get color at tween frame as second resort. thisTween = None frameLength = 1 advancementFunction = "linear" foundTween = False pointList = [] colorList = [] for tweenNode in self.tweens.getiterator("motion-tween"): if tweenNode.tag == "motion-tween" and tweenNode.attrib.get("id") == tweenId: foundTween = True frameLength = ( 1 if tweenNode.attrib.get("length-in-frames") == None else tweenNode.attrib.get("length-in-frames") ) advancementFunction = ( "linear" if tweenNode.attrib.get("advancement-function") == None else tweenNode.attrib.get("advancement-function") ) for pointOrColorNode in tweenNode.getiterator(): if pointOrColorNode.tag == "point": pX = ( 0 if pointOrColorNode.attrib.get("x") == None else float(pointOrColorNode.attrib.get("x")) ) pY = ( 0 if pointOrColorNode.attrib.get("y") == None else float(pointOrColorNode.attrib.get("y")) ) pointList.append(Point(pX, pY, 0)) elif pointOrColorNode.tag == "color-state": colorName = ( "white" if pointOrColorNode.attrib.get("name") == None else pointOrColorNode.attrib.get("name") ) for colorNode in self.colors.getiterator("color"): if ( colorNode.tag == "color" and colorNode.attrib.get("name") == colorName ): R = ( 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r")) ) G = ( 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g")) ) B = ( 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b")) ) A = ( 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a")) ) colorList.append(Color(R, G, B, A)) break # leave for loop when we find the correct color reference pass # Run through all child nodes of selected tween break # Exit after finding correct tween pass if foundTween: thisTween = Tween(frameLength, advancementFunction, pointList, colorList) offset = thisTween.XYFromFrame(frameInTween) offsetFromTweenX = int(offset.X) offsetFromTweenY = int(offset.Y) offsetX += int(offset.X) offsetY += int(offset.Y) if thisTween.hasColorComponent(): tweenHasColor = True if frameCallHasColor == False: color = thisTween.colorFromFrame(frameInTween) pass if ( frameNode.attrib.get("color-name") != None and frameCallHasColor == False and tweenHasColor == False ): # Get color at frame definition as last resort. for colorNode in colors.getiterator("color"): if colorNode.tag == "color" and colorNode.attrib.get( "name" ) == frameNode.attrib.get("color-name"): R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r")) G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g")) B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b")) A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a")) color = Color(R, G, B, A) break # leave for loop when we find the correct color pass rotationZ = ( 0 if frameCallNode.attrib.get("rotation-z") == None else float(frameCallNode.attrib.get("rotation-z")) ) frameList.append( Frame( Bound(offsetX, offsetY, addWidth, addHeight), s, t, S, T, blend, scaleX, scaleY, color, rotationZ, ) ) pass break # Leave once we've found the appropriate frame # Prepare tracking list of consumed nodes. self.clearNodesForDrawing() # Make an identifier to tack onto primitive names in Panda3d's scene graph. frameIndexForName = 1 # Loop through loaded frames that make up composite frame. for loadedFrame in frameList: # For debugging purposes, print the object. if False: loadedFrame.printAsString() # Set up place to store primitive 3d object; note: requires vertex data made by GeomVertexData squareMadeByTriangleStrips = GeomTristrips(Geom.UHDynamic) # Set up place to hold 3d data and for the following coordinates: # square's points (V3: x, y, z), # the colors at each point of the square (c4: r, g, b, a), and # for the UV texture coordinates at each point of the square (t2: S, T). vertexData = GeomVertexData( "square-" + str(frameIndexForName), GeomVertexFormat.getV3c4t2(), Geom.UHDynamic ) vertex = GeomVertexWriter(vertexData, "vertex") color = GeomVertexWriter(vertexData, "color") texcoord = GeomVertexWriter(vertexData, "texcoord") # Add the square's data # Upper-Left corner of square vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A) texcoord.addData2f(loadedFrame.s, loadedFrame.T) # Upper-Right corner of square vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A) texcoord.addData2f(loadedFrame.S, loadedFrame.T) # Lower-Left corner of square vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A) texcoord.addData2f(loadedFrame.s, loadedFrame.t) # Lower-Right corner of square vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A) texcoord.addData2f(loadedFrame.S, loadedFrame.t) # Pass data to primitive squareMadeByTriangleStrips.addNextVertices(4) squareMadeByTriangleStrips.closePrimitive() square = Geom(vertexData) square.addPrimitive(squareMadeByTriangleStrips) # Pass primtive to drawing node drawPrimitiveNode = GeomNode("square-" + str(frameIndexForName)) drawPrimitiveNode.addGeom(square) # Pass node to scene (effect camera) nodePath = self.effectCameraNodePath.attachNewNode(drawPrimitiveNode) # Linear dodge: if loadedFrame.blendMode == "darken": nodePath.setAttrib( ColorBlendAttrib.make( ColorBlendAttrib.MAdd, ColorBlendAttrib.OOneMinusFbufferColor, ColorBlendAttrib.OOneMinusIncomingColor, ) ) pass elif loadedFrame.blendMode == "multiply": nodePath.setAttrib( ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OFbufferColor, ColorBlendAttrib.OZero) ) pass elif loadedFrame.blendMode == "color-burn": nodePath.setAttrib( ColorBlendAttrib.make( ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OOneMinusIncomingColor ) ) pass elif loadedFrame.blendMode == "linear-burn": nodePath.setAttrib( ColorBlendAttrib.make( ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OIncomingColor ) ) pass elif loadedFrame.blendMode == "lighten": nodePath.setAttrib( ColorBlendAttrib.make( ColorBlendAttrib.MMax, ColorBlendAttrib.OIncomingColor, ColorBlendAttrib.OFbufferColor ) ) pass elif loadedFrame.blendMode == "color-dodge": nodePath.setAttrib( ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOne) ) pass elif loadedFrame.blendMode == "linear-dodge": nodePath.setAttrib( ColorBlendAttrib.make( ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOneMinusIncomingColor ) ) pass else: # Overwrite: nodePath.setAttrib( ColorBlendAttrib.make( ColorBlendAttrib.MAdd, ColorBlendAttrib.OIncomingAlpha, ColorBlendAttrib.OOneMinusIncomingAlpha ) ) pass nodePath.setDepthTest(False) # Apply texture nodePath.setTexture(self.tex) # Apply translation, then rotation, then scaling to node. nodePath.setPos( ( loadedFrame.bound.X + loadedFrame.bound.Width / 2.0, 1, -loadedFrame.bound.Y - loadedFrame.bound.Height / 2.0, ) ) nodePath.setR(loadedFrame.rotationZ) nodePath.setScale(loadedFrame.scaleX, 1, loadedFrame.scaleY) nodePath.setTwoSided(True) self.consumedNodesList.append(nodePath) frameIndexForName = frameIndexForName + 1 # Loop continues on through each frame called in the composite frame. pass
class Effect: baseWidth = 0 baseHeight = 0 effectWidth = 1 effectHeight = 1 effectTargetMS = 143 noSampling = False tex = None loadedFormat = None # Animation variables internalFrameIndex = 1 startIndex = 1 endIndex = 1 loopEffect = False # XML variables tree = None frames = None colors = None tweens = None compositeFrames = None # Nodes consumedNodesList = None # Accessible object (nodePath) effectCameraNodePath = None effectCardNodePath = None # Constant value; Unit comparison for card size; basis is from cure, which is [140x110] cardDimensionBasis = [-5.0, 5.0, 0.0, 10.0, 140.0, 110.0] pixelScaleX = cardDimensionBasis[4]/(cardDimensionBasis[1]-cardDimensionBasis[0]) pixelScaleZ = cardDimensionBasis[5]/(cardDimensionBasis[3]-cardDimensionBasis[2]) effectIsCentered = True effectAdjustment = [0, 0, 0] def __init__(self, effectFileName, parent=None, loop=False, effectIsCentered=True, effectAdjustment=[0, 0, 0]): self.effectAdjustment = effectAdjustment self.loopEffect = loop self.effectIsCentered = effectIsCentered self.loadedFormat = None if effectFileName != None: effectFileNameSplit = effectFileName.split('.') self.loadedFormat = effectFileNameSplit[len(effectFileNameSplit)-2] # Get value at penultimate index if self.loadedFormat == effectFileNameSplit[0]: self.loadedFormat = None # Get rid of bad format name. pass # Load texture; supply alpha channel if it doesn't exist. p = transparencyKey(effectFileName) self.tex = Texture() self.tex.setup2dTexture(p.getXSize(), p.getYSize(), Texture.TUnsignedByte, Texture.FRgba) self.tex.load(p) if self.loadedFormat != None: try: self.tree = etree.parse("./"+GAME+"/effects/"+self.loadedFormat+"/sprite.xml") except IOError: self.loadedFormat = None pass if self.loadedFormat != None: root = self.tree.getroot() self.frames = root.find('.//frames') self.colors = root.find('.//colors') self.tweens = root.find('.//motion-tweens') self.compositeFrames = root.find('.//composite-frames') self.baseWidth = 0 if root.attrib.get("base-width") == None else float(root.attrib.get("base-width")) self.baseHeight = 0 if root.attrib.get("base-height") == None else float(root.attrib.get("base-height")) self.effectWidth = 1 if root.attrib.get("frame-width") == None else float(root.attrib.get("frame-width")) self.effectHeight = 1 if root.attrib.get("frame-height") == None else float(root.attrib.get("frame-height")) self.effectTargetMS = 143 if root.attrib.get("target-ms") == None else float(root.attrib.get("target-ms")) self.startIndex = 1 if root.attrib.get("target-start") == None else int(root.attrib.get("target-start")) self.endIndex = 1 if root.attrib.get("target-end") == None else int(root.attrib.get("target-end")) self.noSampling = False if root.attrib.get("no-sampling") == None else bool(root.attrib.get("no-sampling")) if self.noSampling==True: self.tex.setMagfilter(Texture.FTNearest) self.tex.setMinfilter(Texture.FTNearest) cm = CardMaker('card-'+effectFileName) cardDeltaX = self.effectWidth / self.pixelScaleX cardDeltaZ = self.effectHeight / self.pixelScaleZ if self.effectIsCentered == True: cm.setFrame(0, 0, 0, 0) deltaX = (cardDeltaX/2.0) - (-cardDeltaX/2.0) deltaY = 0 deltaZ = (cardDeltaZ/2.0) - (-cardDeltaZ/2.0) #occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, (-cardDeltaZ/2.0)), Point3((-cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (-cardDeltaZ/2.0))) else: cm.setFrame(0, 0, 0, 0) deltaX = (cardDeltaX/2.0) - (-cardDeltaX/2.0) deltaY = 0 deltaZ = cardDeltaZ - 0 #occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, 0), Point3((-cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, 0)) self.effectCardNodePath = render.attachNewNode(cm.generate()) self.effectCardNodePath.setBillboardPointEye() self.effectCardNodePath.reparentTo(parent) #occluder_nodepath = self.effectCardNodePath.attachNewNode(occluder) #self.effectCardNodePath.setOccluder(occluder_nodepath) emptyNode = NodePath('effect-parent-translator') emptyNode.reparentTo(self.effectCardNodePath) if effectIsCentered == True: emptyNode.setPos(-deltaX/2.0+self.effectAdjustment[0], 0+self.effectAdjustment[1], deltaZ/2.0+self.effectAdjustment[2]) else: emptyNode.setPos(-deltaX/2.0+self.effectAdjustment[0], 0+self.effectAdjustment[1], deltaZ+self.effectAdjustment[2]) #emptyNode.place() emptyNode.setSx(float(deltaX)/self.effectWidth) emptyNode.setSz(float(deltaZ)/self.effectHeight) self.effectCameraNodePath = emptyNode if parent != None: self.effectCardNodePath.reparentTo(parent) else: self.effectCardNodePath.reparentTo(render) #self.effectCardNodePath.place() self.effectCardNodePath.setBin("fixed", 40) self.effectCardNodePath.setDepthTest(False) self.effectCardNodePath.setDepthWrite(False) pass def getSequence(self): sequence = Sequence() for x in range(self.startIndex, self.endIndex, 1): sequence.append(Func(self.pandaRender)) sequence.append(Func(self.advanceFrame)) sequence.append(Wait(self.effectTargetMS * 0.001)) sequence.append(Func(self.clearNodesForDrawing)) sequence.append(Func(self.advanceFrame)) sequence.append(Wait(self.effectTargetMS * 0.001)) return sequence pass def hasEffectFinished(self): if self.internalFrameIndex > self.endIndex and self.loopEffect == False: return True else: return False pass def advanceFrame(self): if self.internalFrameIndex < self.endIndex: self.internalFrameIndex += 1 elif self.internalFrameIndex == self.endIndex and self.loopEffect == True: self.internalFrameIndex = self.startIndex else: self.internalFrameIndex = self.endIndex + 1 self.clearNodesForDrawing() pass def clearNodesForDrawing(self): if False: self.effectCameraNodePath.analyze() if self.consumedNodesList != None and self.consumedNodesList != []: for consumedNode in self.consumedNodesList: consumedNode.removeNode() self.consumedNodesList = [] pass def pandaRender(self): frameList = [] for node in self.compositeFrames.getiterator('composite-frame'): if node.tag == "composite-frame" and node.attrib.get("id") == str(self.internalFrameIndex): for frameCallNode in node: for frameNode in self.frames.getiterator('frame'): if frameNode.tag == "frame" and frameNode.attrib.get("id") == frameCallNode.attrib.get("id"): offsetX = 0 if frameCallNode.attrib.get("offset-x") == None else float(frameCallNode.attrib.get("offset-x")) offsetY = 0 if frameCallNode.attrib.get("offset-y") == None else float(frameCallNode.attrib.get("offset-y")) tweenId = frameCallNode.attrib.get("tween") frameInTween = 0 if frameCallNode.attrib.get("frame-in-tween") == None else int(frameCallNode.attrib.get("frame-in-tween")) addWidth = 0 if frameNode.attrib.get("w") == None else float(frameNode.attrib.get("w")) addHeight = 0 if frameNode.attrib.get("h") == None else float(frameNode.attrib.get("h")) sInPixels = 0 if frameNode.attrib.get("s") == None else float(frameNode.attrib.get("s")) tInPixels = 0 if frameNode.attrib.get("t") == None else float(frameNode.attrib.get("t")) swInPixels = sInPixels + addWidth thInPixels = tInPixels + addHeight s = (sInPixels / self.baseWidth) t = 1 - (tInPixels / self.baseHeight) # Complemented to deal with loading image upside down. S = (swInPixels / self.baseWidth) T = 1 - (thInPixels / self.baseHeight) # Complemented to deal with loading image upside down. blend = "overwrite" if frameCallNode.attrib.get("blend") == None else frameCallNode.attrib.get("blend") scaleX = 1 if frameCallNode.attrib.get("scale-x") == None else float(frameCallNode.attrib.get("scale-x")) scaleY = 1 if frameCallNode.attrib.get("scale-y") == None else float(frameCallNode.attrib.get("scale-y")) color = Color(1,1,1,1) tweenHasColor = False frameCallHasColor = False frameCallColorName = frameCallNode.attrib.get("color-name") if frameCallColorName != None: # Get color at frame call as first resort. frameCallHasColor = True for colorNode in self.colors.getiterator('color'): if colorNode.tag == 'color' and colorNode.attrib.get("name") == frameCallColorName: R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r")) G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g")) B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b")) A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a")) color = Color(R, G, B, A) break # leave for loop when we find the correct color pass if tweenId != None and tweenId != "0": # Get color at tween frame as second resort. thisTween = None frameLength = 1 advancementFunction = "linear" foundTween = False pointList = [] colorList = [] for tweenNode in self.tweens.getiterator('motion-tween'): if tweenNode.tag == "motion-tween" and tweenNode.attrib.get("id") == tweenId: foundTween = True frameLength = 1 if tweenNode.attrib.get("length-in-frames") == None else tweenNode.attrib.get("length-in-frames") advancementFunction = "linear" if tweenNode.attrib.get("advancement-function") == None else tweenNode.attrib.get("advancement-function") for pointOrColorNode in tweenNode.getiterator(): if pointOrColorNode.tag == "point": pX = 0 if pointOrColorNode.attrib.get("x") == None else float(pointOrColorNode.attrib.get("x")) pY = 0 if pointOrColorNode.attrib.get("y") == None else float(pointOrColorNode.attrib.get("y")) pointList.append(Point(pX, pY, 0)) elif pointOrColorNode.tag == "color-state": colorName = "white" if pointOrColorNode.attrib.get("name") == None else pointOrColorNode.attrib.get("name") for colorNode in self.colors.getiterator('color'): if colorNode.tag == 'color' and colorNode.attrib.get("name") == colorName: R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r")) G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g")) B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b")) A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a")) colorList.append(Color(R, G, B, A)) break # leave for loop when we find the correct color reference pass # Run through all child nodes of selected tween break # Exit after finding correct tween pass if foundTween: thisTween = Tween(frameLength, advancementFunction, pointList, colorList) offset = thisTween.XYFromFrame(frameInTween); offsetFromTweenX = int(offset.X); offsetFromTweenY = int(offset.Y); offsetX += int(offset.X); offsetY += int(offset.Y); if thisTween.hasColorComponent(): tweenHasColor = True; if frameCallHasColor == False: color = thisTween.colorFromFrame(frameInTween); pass if frameNode.attrib.get("color-name") != None and frameCallHasColor == False and tweenHasColor == False: # Get color at frame definition as last resort. for colorNode in colors.getiterator('color'): if colorNode.tag == 'color' and colorNode.attrib.get("name") == frameNode.attrib.get("color-name"): R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r")) G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g")) B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b")) A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a")) color = Color(R, G, B, A) break # leave for loop when we find the correct color pass rotationZ = 0 if frameCallNode.attrib.get("rotation-z") == None else float(frameCallNode.attrib.get("rotation-z")) frameList.append(Frame(Bound(offsetX, offsetY, addWidth, addHeight), s, t, S, T, blend, scaleX, scaleY, color, rotationZ)) pass break # Leave once we've found the appropriate frame # Prepare tracking list of consumed nodes. self.clearNodesForDrawing() # Make an identifier to tack onto primitive names in Panda3d's scene graph. frameIndexForName = 1 # Loop through loaded frames that make up composite frame. for loadedFrame in frameList: # For debugging purposes, print the object. if False: loadedFrame.printAsString() # Set up place to store primitive 3d object; note: requires vertex data made by GeomVertexData squareMadeByTriangleStrips = GeomTristrips(Geom.UHDynamic) # Set up place to hold 3d data and for the following coordinates: # square's points (V3: x, y, z), # the colors at each point of the square (c4: r, g, b, a), and # for the UV texture coordinates at each point of the square (t2: S, T). vertexData = GeomVertexData('square-'+str(frameIndexForName), GeomVertexFormat.getV3c4t2(), Geom.UHDynamic) vertex = GeomVertexWriter(vertexData, 'vertex') color = GeomVertexWriter(vertexData, 'color') texcoord = GeomVertexWriter(vertexData, 'texcoord') # Add the square's data # Upper-Left corner of square vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A) texcoord.addData2f(loadedFrame.s, loadedFrame.T) # Upper-Right corner of square vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A) texcoord.addData2f(loadedFrame.S, loadedFrame.T) # Lower-Left corner of square vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A) texcoord.addData2f(loadedFrame.s, loadedFrame.t) # Lower-Right corner of square vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0) color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A) texcoord.addData2f(loadedFrame.S, loadedFrame.t) # Pass data to primitive squareMadeByTriangleStrips.addNextVertices(4) squareMadeByTriangleStrips.closePrimitive() square = Geom(vertexData) square.addPrimitive(squareMadeByTriangleStrips) # Pass primtive to drawing node drawPrimitiveNode=GeomNode('square-'+str(frameIndexForName)) drawPrimitiveNode.addGeom(square) # Pass node to scene (effect camera) nodePath = self.effectCameraNodePath.attachNewNode(drawPrimitiveNode) # Linear dodge: if loadedFrame.blendMode == "darken": nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOneMinusFbufferColor, ColorBlendAttrib.OOneMinusIncomingColor)) pass elif loadedFrame.blendMode == "multiply": nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OFbufferColor, ColorBlendAttrib.OZero)) pass elif loadedFrame.blendMode == "color-burn": nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OOneMinusIncomingColor)) pass elif loadedFrame.blendMode == "linear-burn": nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OIncomingColor)) pass elif loadedFrame.blendMode == "lighten": nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MMax, ColorBlendAttrib.OIncomingColor, ColorBlendAttrib.OFbufferColor)) pass elif loadedFrame.blendMode == "color-dodge": nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOne)) pass elif loadedFrame.blendMode == "linear-dodge": nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOneMinusIncomingColor)) pass else: # Overwrite: nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OIncomingAlpha, ColorBlendAttrib.OOneMinusIncomingAlpha)) pass nodePath.setDepthTest(False) # Apply texture nodePath.setTexture(self.tex) # Apply translation, then rotation, then scaling to node. nodePath.setPos((loadedFrame.bound.X + loadedFrame.bound.Width / 2.0, 1, -loadedFrame.bound.Y - loadedFrame.bound.Height / 2.0)) nodePath.setR(loadedFrame.rotationZ) nodePath.setScale(loadedFrame.scaleX, 1, loadedFrame.scaleY) nodePath.setTwoSided(True) self.consumedNodesList.append(nodePath) frameIndexForName = frameIndexForName + 1 # Loop continues on through each frame called in the composite frame. pass