def __init__(self, mp): vdata = GeomVertexData("name_me", GeomVertexFormat.getV3c4(), Geom.UHStatic) vertex = GeomVertexWriter(vdata, "vertex") color = GeomVertexWriter(vdata, "color") primitive = GeomTristrips(Geom.UHStatic) film_size = base.cam.node().getLens().getFilmSize() x = film_size.getX() / 2.0 z = x * 256.0 / 240.0 vertex.addData3f(x, 90, z) vertex.addData3f(-x, 90, z) vertex.addData3f(x, 90, -z) vertex.addData3f(-x, 90, -z) color.addData4f(VBase4(*mp["backgroundcolor1"])) color.addData4f(VBase4(*mp["backgroundcolor1"])) color.addData4f(VBase4(*mp["backgroundcolor2"])) color.addData4f(VBase4(*mp["backgroundcolor2"])) primitive.addNextVertices(4) primitive.closePrimitive() geom = Geom(vdata) geom.addPrimitive(primitive) self.node = GeomNode("sky") self.node.addGeom(geom) base.camera.attachNewNode(self.node)
def __init__(self, mp): vdata = GeomVertexData('name_me', GeomVertexFormat.getV3c4(), Geom.UHStatic) vertex = GeomVertexWriter(vdata, 'vertex') color = GeomVertexWriter(vdata, 'color') primitive = GeomTristrips(Geom.UHStatic) film_size = base.cam.node().getLens().getFilmSize() x = film_size.getX() / 2.0 z = x * 256.0 / 240.0 vertex.addData3f(x, 90, z) vertex.addData3f(-x, 90, z) vertex.addData3f(x, 90, -z) vertex.addData3f(-x, 90, -z) color.addData4f(VBase4(*mp['backgroundcolor1'])) color.addData4f(VBase4(*mp['backgroundcolor1'])) color.addData4f(VBase4(*mp['backgroundcolor2'])) color.addData4f(VBase4(*mp['backgroundcolor2'])) primitive.addNextVertices(4) primitive.closePrimitive() geom = Geom(vdata) geom.addPrimitive(primitive) self.node = GeomNode('sky') self.node.addGeom(geom) base.camera.attachNewNode(self.node)
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.seeNode = self.render.attachNewNode("see") self.cam.reparentTo(self.seeNode) self.cam.setPos(0, 0, 5) self.fpscamera = fpscontroller.FpsController(self, self.seeNode) self.fpscamera.setFlyMode(True) self.prevPos = self.fpscamera.getPos() self.prevInto = None self.info = self.genLabelText("Position: <unknown>", 4) self.makeInstructions() self.initCollisions() self.leftColor = LVecBase4i(224, 224, 64, 255) self.rightColor = LVecBase4i(64, 224, 224, 255) self.isDrawing = False self.toggleDrawing() self.accept("escape", sys.exit) # Escape quits self.accept("enter", self.toggleDrawing) def initCollisions(self): # Initialize the collision traverser. self.cTrav = CollisionTraverser() self.cTrav.showCollisions(self.render) # self.cQueue = CollisionHandlerQueue() # Initialize the Pusher collision handler. # self.pusher = CollisionHandlerPusher() self.pusher = CollisionHandlerFloor() ### player print DirectNotifyGlobal.directNotify.getCategories() # Create a collsion node for this object. playerNode = CollisionNode("player") playerNode.addSolid(CollisionSphere(0, 0, 0, 1)) # playerNode.setFromCollideMask(BitMask32.bit(0)) # playerNode.setIntoCollideMask(BitMask32.allOn()) # Attach the collision node to the object's model. self.playerC = self.fpscamera.player.attachNewNode(playerNode) # Set the object's collision node to render as visible. self.playerC.show() # Add the 'player' collision node to the Pusher collision handler. # self.pusher.addCollider(self.playerC, self.fpscamera.player) # self.pusher.addCollider(playerC, self.fpscamera.player) # self.cTrav.addCollider(self.playerC, self.cQueue) def toggleDrawing(self): self.isDrawing = not self.isDrawing if self.isDrawing: self.drawText.setText("Enter: Turn off drawing") self.fpscamera.setFlyMode(True) self.prevPos = None self.cTrav.removeCollider(self.playerC) self.pusher.removeCollider(self.playerC) self.removeTask("updatePhysics") self.addTask(self.drawHere, "drawHere") self.geomNode = GeomNode("geomNode") self.geomNodePath = self.render.attachNewNode(self.geomNode) self.geomNodePath.setTwoSided(True) # apparently p3tinydisplay needs this self.geomNodePath.setColorOff() # Create a collision node for this object. self.floorCollNode = CollisionNode("geom") # self.floorCollNode.setFromCollideMask(BitMask32.bit(0)) # self.floorCollNode.setIntoCollideMask(BitMask32.allOn()) # Attach the collision node to the object's model. floorC = self.geomNodePath.attachNewNode(self.floorCollNode) # Set the object's collision node to render as visible. floorC.show() # self.pusher.addCollider(floorC, self.geomNodePath) self.newVertexData() self.newGeom() else: self.drawText.setText("Enter: Turn on drawing") self.removeTask("drawHere") if self.prevPos: self.completePath() self.fpscamera.setFlyMode(True) self.drive.setPos(self.fpscamera.getPos()) self.cTrav.addCollider(self.playerC, self.pusher) self.pusher.addCollider(self.playerC, self.fpscamera.player) self.taskMgr.add(self.updatePhysics, "updatePhysics") def newVertexData(self): fmt = GeomVertexFormat.getV3c4() # fmt = GeomVertexFormat.getV3n3c4() self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, "vertex") # self.normalWriter = GeomVertexWriter(self.vertexData, 'normal') self.colorWriter = GeomVertexWriter(self.vertexData, "color") def newGeom(self): self.triStrips = GeomTristrips(Geom.UHDynamic) self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.triStrips) def makeInstructions(self): OnscreenText(text="Draw Path by Walking", style=1, fg=(1, 1, 0, 1), pos=(0.5, -0.95), scale=0.07) self.drawText = self.genLabelText("", 0) self.genLabelText("Walk (W/S/A/D), Jump=Space, Look=PgUp/PgDn", 1) self.genLabelText(" (hint, go backwards with S to see your path immediately)", 2) self.genLabelText("ESC: Quit", 3) def genLabelText(self, text, i): return OnscreenText(text=text, pos=(-1.3, 0.95 - 0.05 * i), fg=(1, 1, 0, 1), align=TextNode.ALeft, scale=0.05) def drawHere(self, task): pos = self.fpscamera.getPos() self.info.setText( "Position: {0}, {1}, {2} at {3} by {4}".format( int(pos.x * 100) / 100.0, int(pos.y * 100) / 100.0, int(pos.z) / 100.0, self.fpscamera.getHeading(), self.fpscamera.getLookAngle(), ) ) prevPos = self.prevPos if not prevPos: self.prevPos = pos elif (pos - prevPos).length() > 1: self.drawQuadTo(prevPos, pos, 2) row = self.vertexWriter.getWriteRow() numPrims = self.triStrips.getNumPrimitives() if numPrims == 0: primVerts = row else: primVerts = row - self.triStrips.getPrimitiveEnd(numPrims - 1) if primVerts >= 4: self.triStrips.closePrimitive() if row >= 256: print "Packing and starting anew" newGeom = True self.geom.unifyInPlace(row, False) else: newGeom = False self.completePath() if newGeom: self.newVertexData() self.newGeom() if not newGeom: self.triStrips.addConsecutiveVertices(row - 2, 2) else: self.drawQuadTo(prevPos, pos, 2) self.leftColor[1] += 63 self.rightColor[2] += 37 self.prevPos = pos return task.cont def drawLineTo(self, pos, color): self.vertexWriter.addData3f(pos.x, pos.y, pos.z) # self.normalWriter.addData3f(0, 0, 1) self.colorWriter.addData4i(color) self.triStrips.addNextVertices(1) def drawQuadTo(self, a, b, width): """ a (to) b are vectors defining a line bisecting a new quad. """ into = b - a if abs(into.x) + abs(into.y) < 1: if not self.prevInto: return into = self.prevInto print into else: into.normalize() # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space if self.vertexWriter.getWriteRow() == 0: self.drawQuadRow(a, into, width) self.drawQuadRow(b, into, width) self.prevInto = into def drawQuadRow(self, a, into, width): """ a defines a point, with 'into' being the normalized direction. """ # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z) aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z) row = self.vertexWriter.getWriteRow() self.vertexWriter.addData3f(aLeft) self.vertexWriter.addData3f(aRight) # self.normalWriter.addData3f(Vec3(0, 0, 1)) # self.normalWriter.addData3f(Vec3(0, 0, 1)) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) self.triStrips.addConsecutiveVertices(row, 2) def completePath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() tris = self.triStrips.decompose() p = 0 vertexReader = GeomVertexReader(self.vertexData, "vertex") for i in range(tris.getNumPrimitives()): v0 = tris.getPrimitiveStart(i) ve = tris.getPrimitiveEnd(i) if v0 < ve: vertexReader.setRow(tris.getVertex(v0)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p + 1, p + 2) p += 3 self.floorCollNode.addSolid(floorMesh) def updatePhysics(self, task): pos = self.fpscamera.getPos() self.info.setText( "Position: {0}, {1}, {2}".format(int(pos.x * 100) / 100.0, int(pos.y * 100) / 100.0, int(pos.z) / 100.0) ) return task.cont
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.seeNode = self.render.attachNewNode('see') self.cam.reparentTo(self.seeNode) self.cam.setPos(0, 0, 5) self.fpscamera = fpscontroller.FpsController(self, self.seeNode) self.fpscamera.setFlyMode(True) self.fpscamera.setMouseLook(True) self.prevPos = self.fpscamera.getPos() self.prevInto = None self.makeInstructions() self.info = self.genLabelText("Position: <unknown>", 2) self.initCollisions() self.leftColor = LVecBase4i(224, 224, 64, 255) self.rightColor = LVecBase4i(64, 224, 224, 255) self.isDrawing = False self.toggleDrawing() self.accept("escape", sys.exit) #Escape quits self.accept("enter", self.toggleDrawing) def initCollisions(self): # Initialize the collision traverser. self.cTrav = CollisionTraverser() self.cTrav.showCollisions(self.render) # Initialize the Pusher collision handler. self.pusher = CollisionHandlerFloor() ### player # Create a collsion node for this object. playerNode = CollisionNode('player') playerNode.addSolid(CollisionSphere(0, 0, 0, 1)) # Attach the collision node to the object's model. self.playerC = self.fpscamera.player.attachNewNode(playerNode) # Set the object's collision node to render as visible. self.playerC.show() def toggleDrawing(self): self.isDrawing = not self.isDrawing if self.isDrawing: self.instructionText.setText( 'Enter: Generate Tunnel from Movement') self.fpscamera.setFlyMode(True) self.prevPos = None # self.cTrav.remosveCollider(self.playerC) self.removeTask('updatePhysics') self.addTask(self.drawHere, 'drawHere') self.geomNode = GeomNode('geomNode') self.geomNodePath = self.render.attachNewNode(self.geomNode) self.geomNodePath.setTwoSided(True) # apparently p3tinydisplay needs this self.geomNodePath.setColorOff() # Create a collision node for this object. self.floorCollNode = CollisionNode('geom') # Attach the collision node to the object's model. floorC = self.geomNodePath.attachNewNode(self.floorCollNode) # Set the object's collision node to render as visible. floorC.show() self.newVertexData() self.newGeom() else: self.instructionText.setText('Enter: Record Movement for Tunnel') self.removeTask('drawHere') if self.prevPos: #self.completePath() self.completeTunnelPath() self.fpscamera.setFlyMode(True) self.drive.setPos(self.fpscamera.getPos()) self.cTrav.addCollider(self.playerC, self.pusher) self.pusher.addCollider(self.playerC, self.fpscamera.player) self.taskMgr.add(self.updatePhysics, 'updatePhysics') def newVertexData(self): fmt = GeomVertexFormat.getV3c4() # fmt = GeomVertexFormat.getV3n3c4() self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') # self.normalWriter = GeomVertexWriter(self.vertexData, 'normal') self.colorWriter = GeomVertexWriter(self.vertexData, 'color') def newGeom(self): self.triStrips = GeomTristrips(Geom.UHDynamic) self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.triStrips) def makeInstructions(self): OnscreenText(text="Draw Path by Walking (WSAD/space/mouselook)", style=1, fg=(1, 1, 0, 1), pos=(0.5, -0.95), scale=.07) self.genLabelText("ESC: Quit", 0) self.instructionText = self.genLabelText("", 1) def genLabelText(self, text, i): return OnscreenText(text=text, pos=(-1.3, .95 - .05 * i), fg=(1, 1, 0, 1), align=TextNode.ALeft, scale=.05) def drawHere(self, task): pos = self.fpscamera.getPos() self.info.setText("Position: {0}, {1}, {2} at {3} by {4}".format( int(pos.x * 100) / 100., int(pos.y * 100) / 100., int(pos.z) / 100., self.fpscamera.getHeading(), self.fpscamera.getLookAngle())) prevPos = self.prevPos if not prevPos: self.prevPos = pos elif (pos - prevPos).length() >= 1: # self.extendPathQuad(prevPos, pos, 2) self.extendPathTunnel(prevPos, pos, 3) self.leftColor[1] += 63 self.rightColor[2] += 37 self.prevPos = pos return task.cont def extendPathQuad(self, prevPos, pos, width): self.drawQuadTo(prevPos, pos, width) row = self.vertexWriter.getWriteRow() numPrims = self.triStrips.getNumPrimitives() if numPrims == 0: primVerts = row else: primVerts = row - self.triStrips.getPrimitiveEnd(numPrims - 1) if primVerts >= 4: self.triStrips.closePrimitive() if row >= 256: print "Packing and starting anew" newGeom = True self.geom.unifyInPlace(row, False) else: newGeom = False self.completeQuadPath() if newGeom: self.newVertexData() self.newGeom() if newGeom: self.drawQuadTo(prevPos, pos, width) else: self.triStrips.addConsecutiveVertices(row - 2, 2) def extendPathTunnel(self, prevPos, pos, width): self.drawTunnelTo(prevPos, pos, width) def drawLineTo(self, pos, color): self.vertexWriter.addData3f(pos.x, pos.y, pos.z) # self.normalWriter.addData3f(0, 0, 1) self.colorWriter.addData4i(color) self.triStrips.addNextVertices(1) return 1 def drawQuadTo(self, a, b, width): """ a (to) b are vectors defining a line bisecting a new quad. """ into = (b - a) if abs(into.x) + abs(into.y) < 1: # ensure that if we jump in place, we don't get a thin segment if not self.prevInto: return into = self.prevInto else: into.normalize() # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space if self.vertexWriter.getWriteRow() == 0: self.drawQuadRow(a, into, width) verts = self.drawQuadRow(b, into, width) self.prevInto = into return verts def drawQuadRow(self, a, into, width): """ a defines a point, with 'into' being the normalized direction. """ # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z) aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z) row = self.vertexWriter.getWriteRow() self.vertexWriter.addData3f(aLeft) self.vertexWriter.addData3f(aRight) # self.normalWriter.addData3f(Vec3(0, 0, 1)) # self.normalWriter.addData3f(Vec3(0, 0, 1)) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) self.triStrips.addConsecutiveVertices(row, 2) return 2 def drawTunnelTo(self, a, b, width): """ a (to) b are vectors defining a line bisecting a new tunnel segment. """ into = (b - a) if abs(into.x) + abs(into.y) < 1: # ensure that if we jump in place, we don't get a thin segment if not self.prevInto: return into = self.prevInto else: into.normalize() # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space if self.vertexWriter.getWriteRow() == 0: self.drawTunnelBoundary(a, into, width) row = self.vertexWriter.getWriteRow() verts = self.drawTunnelBoundary(b, into, width) totalVerts = self.drawTunnelRow(row, verts) self.prevInto = into return totalVerts def drawTunnelBoundary(self, a, into, width): """ a defines a point, with 'into' being the normalized direction. """ aLowLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z) aLowRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z) aHighRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z + width * 3) aHighLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z + width * 3) self.vertexWriter.addData3f(aLowLeft) self.vertexWriter.addData3f(aLowRight) self.vertexWriter.addData3f(aHighRight) self.vertexWriter.addData3f(aHighLeft) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) return 4 def drawTunnelRowX(self, row, verts): # BOTTOM: bottom-left, new-bottom-left, bottom-right, new-bottom-right self.triStrips.addConsecutiveVertices(row - verts + 0, 1) self.triStrips.addConsecutiveVertices(row + 0, 1) self.triStrips.addConsecutiveVertices(row - verts + 1, 1) self.triStrips.addConsecutiveVertices(row + 1, 1) self.triStrips.closePrimitive() # RIGHT: (new-bottom-right) bottom-right, new-top-right, top-right self.triStrips.addConsecutiveVertices(row + 1, 1) self.triStrips.addConsecutiveVertices(row - verts + 1, 1) self.triStrips.addConsecutiveVertices(row + 2, 1) self.triStrips.addConsecutiveVertices(row - verts + 2, 1) self.triStrips.closePrimitive() # TOP: top-left, new top-right, new top-left self.triStrips.addConsecutiveVertices(row - verts + 2, 1) self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row + 2, 1) self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.closePrimitive() # LEFT: (new top-left) new bottom-left, top-left, bottom-left, new-bottom-left self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.addConsecutiveVertices(row + 0, 1) self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row - verts + 0, 1) self.triStrips.closePrimitive() return verts * 4 def drawTunnelRow(self, row, verts): # # clockwise for the inside of the tunnel # # TOP: new-top-left, top-left, new-top-right, top-right # self.triStrips.addConsecutiveVertices(row + 3, 1) # self.triStrips.addConsecutiveVertices(row - verts + 3, 1) # self.triStrips.addConsecutiveVertices(row + 2, 1) # self.triStrips.addConsecutiveVertices(row - verts + 2, 1) # # RIGHT: new-bottom-right, bottom-right # self.triStrips.addConsecutiveVertices(row + 1, 1) # self.triStrips.addConsecutiveVertices(row - verts + 1, 1) # # BOTTOM: new-bottom-left, bottom-left # self.triStrips.addConsecutiveVertices(row, 1) # self.triStrips.addConsecutiveVertices(row - verts, 1) # # LEFT: new top-left, top-left # self.triStrips.addConsecutiveVertices(row + 3, 1) # self.triStrips.addConsecutiveVertices(row - verts + 3, 1) # TOP: new-top-left, top-left, new-top-right, top-right self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.addConsecutiveVertices(row - verts + 2, 1) self.triStrips.addConsecutiveVertices(row + 2, 1) # RIGHT: new-bottom-right, bottom-right self.triStrips.addConsecutiveVertices(row - verts + 1, 1) self.triStrips.addConsecutiveVertices(row + 1, 1) # BOTTOM: new-bottom-left, bottom-left self.triStrips.addConsecutiveVertices(row - verts, 1) self.triStrips.addConsecutiveVertices(row, 1) # LEFT: new top-left, top-left self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.closePrimitive() return verts * 4 def completeQuadPath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() vertexReader = GeomVertexReader(self.vertexData, 'vertex') tris = self.triStrips.decompose() print "Decomposed prims:", tris.getNumPrimitives() p = 0 for i in range(tris.getNumPrimitives()): v0 = tris.getPrimitiveStart(i) ve = tris.getPrimitiveEnd(i) if v0 < ve: vertexReader.setRow(tris.getVertex(v0)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p + 1, p + 2) p += 3 self.floorCollNode.addSolid(floorMesh) def completeTunnelPath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() vertexReader = GeomVertexReader(self.vertexData, 'vertex') print "Original prims:", self.triStrips.getNumPrimitives() p = 0 for i in range(self.triStrips.getNumPrimitives()): v0 = self.triStrips.getPrimitiveStart(i) ve = self.triStrips.getPrimitiveEnd(i) j = v0 + 4 # add the bottom triangles vertexReader.setRow(self.triStrips.getVertex(j)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(self.triStrips.getVertex(j + 1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(self.triStrips.getVertex(j + 2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p + 1, p + 2) vertexReader.setRow(self.triStrips.getVertex(j + 3)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p + 1, p + 3, p + 2) p += 4 # this adds every triangle, but is not appropriate for a closed path # tris = self.triStrips.decompose() # print "Decomposed prims:",tris.getNumPrimitives() # p = 0 # for i in range(tris.getNumPrimitives()): # v0 = tris.getPrimitiveStart(i) # ve = tris.getPrimitiveEnd(i) # if v0 < ve: # vertexReader.setRow(tris.getVertex(v0)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # vertexReader.setRow(tris.getVertex(v0+1)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # vertexReader.setRow(tris.getVertex(v0+2)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # floorMesh.addTriangle(p, p+1, p+2) # p += 3 self.floorCollNode.addSolid(floorMesh) def updatePhysics(self, task): pos = self.fpscamera.getPos() self.info.setText("Position: {0}, {1}, {2}".format( int(pos.x * 100) / 100., int(pos.y * 100) / 100., int(pos.z) / 100.)) return task.cont
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 MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.seeNode = self.render.attachNewNode('see') self.cam.reparentTo(self.seeNode) self.cam.setPos(0, 0, 5) self.fpscamera = fpscontroller.FpsController(self, self.seeNode) self.fpscamera.setFlyMode(True) self.prevPos = self.fpscamera.getPos() self.prevInto = None self.info = self.genLabelText("Position: <unknown>", 4) self.makeInstructions() self.initCollisions() self.leftColor = LVecBase4i(224, 224, 64, 255) self.rightColor = LVecBase4i(64, 224, 224, 255) self.isDrawing = False self.toggleDrawing() self.accept("escape", sys.exit) #Escape quits self.accept("enter", self.toggleDrawing) def initCollisions(self): # Initialize the collision traverser. self.cTrav = CollisionTraverser() self.cTrav.showCollisions(self.render) # self.cQueue = CollisionHandlerQueue() # Initialize the Pusher collision handler. #self.pusher = CollisionHandlerPusher() self.pusher = CollisionHandlerFloor() ### player print DirectNotifyGlobal.directNotify.getCategories() # Create a collsion node for this object. playerNode = CollisionNode('player') playerNode.addSolid(CollisionSphere(0, 0, 0, 1)) # playerNode.setFromCollideMask(BitMask32.bit(0)) # playerNode.setIntoCollideMask(BitMask32.allOn()) # Attach the collision node to the object's model. self.playerC = self.fpscamera.player.attachNewNode(playerNode) # Set the object's collision node to render as visible. self.playerC.show() # Add the 'player' collision node to the Pusher collision handler. #self.pusher.addCollider(self.playerC, self.fpscamera.player) #self.pusher.addCollider(playerC, self.fpscamera.player) # self.cTrav.addCollider(self.playerC, self.cQueue) def toggleDrawing(self): self.isDrawing = not self.isDrawing if self.isDrawing: self.drawText.setText("Enter: Turn off drawing") self.fpscamera.setFlyMode(True) self.prevPos = None self.cTrav.removeCollider(self.playerC) self.pusher.removeCollider(self.playerC) self.removeTask('updatePhysics') self.addTask(self.drawHere, 'drawHere') self.geomNode = GeomNode('geomNode') self.geomNodePath = self.render.attachNewNode(self.geomNode) self.geomNodePath.setTwoSided(True) # apparently p3tinydisplay needs this self.geomNodePath.setColorOff() # Create a collision node for this object. self.floorCollNode = CollisionNode('geom') # self.floorCollNode.setFromCollideMask(BitMask32.bit(0)) # self.floorCollNode.setIntoCollideMask(BitMask32.allOn()) # Attach the collision node to the object's model. floorC = self.geomNodePath.attachNewNode(self.floorCollNode) # Set the object's collision node to render as visible. floorC.show() #self.pusher.addCollider(floorC, self.geomNodePath) self.newVertexData() self.newGeom() else: self.drawText.setText("Enter: Turn on drawing") self.removeTask('drawHere') if self.prevPos: self.completePath() self.fpscamera.setFlyMode(True) self.drive.setPos(self.fpscamera.getPos()) self.cTrav.addCollider(self.playerC, self.pusher) self.pusher.addCollider(self.playerC, self.fpscamera.player) self.taskMgr.add(self.updatePhysics, 'updatePhysics') def newVertexData(self): fmt = GeomVertexFormat.getV3c4() # fmt = GeomVertexFormat.getV3n3c4() self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') # self.normalWriter = GeomVertexWriter(self.vertexData, 'normal') self.colorWriter = GeomVertexWriter(self.vertexData, 'color') def newGeom(self): self.triStrips = GeomTristrips(Geom.UHDynamic) self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.triStrips) def makeInstructions(self): OnscreenText(text="Draw Path by Walking", style=1, fg=(1, 1, 0, 1), pos=(0.5, -0.95), scale=.07) self.drawText = self.genLabelText("", 0) self.genLabelText("Walk (W/S/A/D), Jump=Space, Look=PgUp/PgDn", 1) self.genLabelText( " (hint, go backwards with S to see your path immediately)", 2) self.genLabelText("ESC: Quit", 3) def genLabelText(self, text, i): return OnscreenText(text=text, pos=(-1.3, .95 - .05 * i), fg=(1, 1, 0, 1), align=TextNode.ALeft, scale=.05) def drawHere(self, task): pos = self.fpscamera.getPos() self.info.setText("Position: {0}, {1}, {2} at {3} by {4}".format( int(pos.x * 100) / 100., int(pos.y * 100) / 100., int(pos.z) / 100., self.fpscamera.getHeading(), self.fpscamera.getLookAngle())) prevPos = self.prevPos if not prevPos: self.prevPos = pos elif (pos - prevPos).length() > 1: self.drawQuadTo(prevPos, pos, 2) row = self.vertexWriter.getWriteRow() numPrims = self.triStrips.getNumPrimitives() if numPrims == 0: primVerts = row else: primVerts = row - self.triStrips.getPrimitiveEnd(numPrims - 1) if primVerts >= 4: self.triStrips.closePrimitive() if row >= 256: print "Packing and starting anew" newGeom = True self.geom.unifyInPlace(row, False) else: newGeom = False self.completePath() if newGeom: self.newVertexData() self.newGeom() if not newGeom: self.triStrips.addConsecutiveVertices(row - 2, 2) else: self.drawQuadTo(prevPos, pos, 2) self.leftColor[1] += 63 self.rightColor[2] += 37 self.prevPos = pos return task.cont def drawLineTo(self, pos, color): self.vertexWriter.addData3f(pos.x, pos.y, pos.z) # self.normalWriter.addData3f(0, 0, 1) self.colorWriter.addData4i(color) self.triStrips.addNextVertices(1) def drawQuadTo(self, a, b, width): """ a (to) b are vectors defining a line bisecting a new quad. """ into = (b - a) if abs(into.x) + abs(into.y) < 1: if not self.prevInto: return into = self.prevInto print into else: into.normalize() # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space if self.vertexWriter.getWriteRow() == 0: self.drawQuadRow(a, into, width) self.drawQuadRow(b, into, width) self.prevInto = into def drawQuadRow(self, a, into, width): """ a defines a point, with 'into' being the normalized direction. """ # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z) aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z) row = self.vertexWriter.getWriteRow() self.vertexWriter.addData3f(aLeft) self.vertexWriter.addData3f(aRight) # self.normalWriter.addData3f(Vec3(0, 0, 1)) # self.normalWriter.addData3f(Vec3(0, 0, 1)) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) self.triStrips.addConsecutiveVertices(row, 2) def completePath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() tris = self.triStrips.decompose() p = 0 vertexReader = GeomVertexReader(self.vertexData, 'vertex') for i in range(tris.getNumPrimitives()): v0 = tris.getPrimitiveStart(i) ve = tris.getPrimitiveEnd(i) if v0 < ve: vertexReader.setRow(tris.getVertex(v0)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p + 1, p + 2) p += 3 self.floorCollNode.addSolid(floorMesh) def updatePhysics(self, task): pos = self.fpscamera.getPos() self.info.setText("Position: {0}, {1}, {2}".format( int(pos.x * 100) / 100., int(pos.y * 100) / 100., int(pos.z) / 100.)) return task.cont
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.seeNode = self.render.attachNewNode('see') self.cam.reparentTo(self.seeNode) self.cam.setPos(0, 0, 5) self.fpscamera = fpscontroller.FpsController(self, self.seeNode) self.fpscamera.setFlyMode(True) self.fpscamera.setMouseLook(True) self.prevPos = self.fpscamera.getPos() self.prevInto = None self.makeInstructions() self.info = self.genLabelText("Position: <unknown>", 2) self.initCollisions() self.leftColor = LVecBase4i(224, 224, 64, 255) self.rightColor = LVecBase4i(64, 224, 224, 255) self.isDrawing = False self.toggleDrawing() self.accept("escape", sys.exit) #Escape quits self.accept("enter", self.toggleDrawing) def initCollisions(self): # Initialize the collision traverser. self.cTrav = CollisionTraverser() self.cTrav.showCollisions(self.render) # Initialize the Pusher collision handler. self.pusher = CollisionHandlerFloor() ### player # Create a collsion node for this object. playerNode = CollisionNode('player') playerNode.addSolid(CollisionSphere(0, 0, 0, 1)) # Attach the collision node to the object's model. self.playerC = self.fpscamera.player.attachNewNode(playerNode) # Set the object's collision node to render as visible. self.playerC.show() def toggleDrawing(self): self.isDrawing = not self.isDrawing if self.isDrawing: self.instructionText.setText('Enter: Generate Tunnel from Movement') self.fpscamera.setFlyMode(True) self.prevPos = None # self.cTrav.remosveCollider(self.playerC) self.removeTask('updatePhysics') self.addTask(self.drawHere, 'drawHere') self.geomNode = GeomNode('geomNode') self.geomNodePath = self.render.attachNewNode(self.geomNode) self.geomNodePath.setTwoSided(True) # apparently p3tinydisplay needs this self.geomNodePath.setColorOff() # Create a collision node for this object. self.floorCollNode = CollisionNode('geom') # Attach the collision node to the object's model. floorC = self.geomNodePath.attachNewNode(self.floorCollNode) # Set the object's collision node to render as visible. floorC.show() self.newVertexData() self.newGeom() else: self.instructionText.setText('Enter: Record Movement for Tunnel') self.removeTask('drawHere') if self.prevPos: #self.completePath() self.completeTunnelPath() self.fpscamera.setFlyMode(True) self.drive.setPos(self.fpscamera.getPos()) self.cTrav.addCollider(self.playerC, self.pusher) self.pusher.addCollider(self.playerC, self.fpscamera.player) self.taskMgr.add(self.updatePhysics, 'updatePhysics') def newVertexData(self): fmt = GeomVertexFormat.getV3c4() # fmt = GeomVertexFormat.getV3n3c4() self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') # self.normalWriter = GeomVertexWriter(self.vertexData, 'normal') self.colorWriter = GeomVertexWriter(self.vertexData, 'color') def newGeom(self): self.triStrips = GeomTristrips(Geom.UHDynamic) self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.triStrips) def makeInstructions(self): OnscreenText(text="Draw Path by Walking (WSAD/space/mouselook)", style=1, fg=(1,1,0,1), pos=(0.5,-0.95), scale = .07) self.genLabelText("ESC: Quit", 0) self.instructionText = self.genLabelText("", 1) def genLabelText(self, text, i): return OnscreenText(text = text, pos = (-1.3, .95-.05*i), fg=(1,1,0,1), align = TextNode.ALeft, scale = .05) def drawHere(self, task): pos = self.fpscamera.getPos() self.info.setText("Position: {0}, {1}, {2} at {3} by {4}".format(int(pos.x*100)/100., int(pos.y*100)/100., int(pos.z)/100., self.fpscamera.getHeading(), self.fpscamera.getLookAngle())) prevPos = self.prevPos if not prevPos: self.prevPos = pos elif (pos - prevPos).length() >= 1: # self.extendPathQuad(prevPos, pos, 2) self.extendPathTunnel(prevPos, pos, 3) self.leftColor[1] += 63 self.rightColor[2] += 37 self.prevPos = pos return task.cont def extendPathQuad(self, prevPos, pos, width): self.drawQuadTo(prevPos, pos, width) row = self.vertexWriter.getWriteRow() numPrims = self.triStrips.getNumPrimitives() if numPrims == 0: primVerts = row else: primVerts = row - self.triStrips.getPrimitiveEnd(numPrims-1) if primVerts >= 4: self.triStrips.closePrimitive() if row >= 256: print "Packing and starting anew" newGeom = True self.geom.unifyInPlace(row, False) else: newGeom = False self.completeQuadPath() if newGeom: self.newVertexData() self.newGeom() if newGeom: self.drawQuadTo(prevPos, pos, width) else: self.triStrips.addConsecutiveVertices(row - 2, 2) def extendPathTunnel(self, prevPos, pos, width): self.drawTunnelTo(prevPos, pos, width) def drawLineTo(self, pos, color): self.vertexWriter.addData3f(pos.x, pos.y, pos.z) # self.normalWriter.addData3f(0, 0, 1) self.colorWriter.addData4i(color) self.triStrips.addNextVertices(1) return 1 def drawQuadTo(self, a, b, width): """ a (to) b are vectors defining a line bisecting a new quad. """ into = (b - a) if abs(into.x) + abs(into.y) < 1: # ensure that if we jump in place, we don't get a thin segment if not self.prevInto: return into = self.prevInto else: into.normalize() # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space if self.vertexWriter.getWriteRow() == 0: self.drawQuadRow(a, into, width) verts = self.drawQuadRow(b, into, width) self.prevInto = into return verts def drawQuadRow(self, a, into, width): """ a defines a point, with 'into' being the normalized direction. """ # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z) aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z) row = self.vertexWriter.getWriteRow() self.vertexWriter.addData3f(aLeft) self.vertexWriter.addData3f(aRight) # self.normalWriter.addData3f(Vec3(0, 0, 1)) # self.normalWriter.addData3f(Vec3(0, 0, 1)) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) self.triStrips.addConsecutiveVertices(row, 2) return 2 def drawTunnelTo(self, a, b, width): """ a (to) b are vectors defining a line bisecting a new tunnel segment. """ into = (b - a) if abs(into.x) + abs(into.y) < 1: # ensure that if we jump in place, we don't get a thin segment if not self.prevInto: return into = self.prevInto else: into.normalize() # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space if self.vertexWriter.getWriteRow() == 0: self.drawTunnelBoundary(a, into, width) row = self.vertexWriter.getWriteRow() verts = self.drawTunnelBoundary(b, into, width) totalVerts = self.drawTunnelRow(row, verts) self.prevInto = into return totalVerts def drawTunnelBoundary(self, a, into, width): """ a defines a point, with 'into' being the normalized direction. """ aLowLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z) aLowRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z) aHighRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z + width * 3) aHighLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z + width * 3) self.vertexWriter.addData3f(aLowLeft) self.vertexWriter.addData3f(aLowRight) self.vertexWriter.addData3f(aHighRight) self.vertexWriter.addData3f(aHighLeft) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) self.colorWriter.addData4i(self.leftColor) self.colorWriter.addData4i(self.rightColor) return 4 def drawTunnelRowX(self, row, verts): # BOTTOM: bottom-left, new-bottom-left, bottom-right, new-bottom-right self.triStrips.addConsecutiveVertices(row - verts + 0, 1) self.triStrips.addConsecutiveVertices(row + 0, 1) self.triStrips.addConsecutiveVertices(row - verts + 1, 1) self.triStrips.addConsecutiveVertices(row + 1, 1) self.triStrips.closePrimitive() # RIGHT: (new-bottom-right) bottom-right, new-top-right, top-right self.triStrips.addConsecutiveVertices(row + 1, 1) self.triStrips.addConsecutiveVertices(row - verts + 1, 1) self.triStrips.addConsecutiveVertices(row + 2, 1) self.triStrips.addConsecutiveVertices(row - verts + 2, 1) self.triStrips.closePrimitive() # TOP: top-left, new top-right, new top-left self.triStrips.addConsecutiveVertices(row - verts + 2, 1) self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row + 2, 1) self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.closePrimitive() # LEFT: (new top-left) new bottom-left, top-left, bottom-left, new-bottom-left self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.addConsecutiveVertices(row + 0, 1) self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row - verts + 0, 1) self.triStrips.closePrimitive() return verts * 4 def drawTunnelRow(self, row, verts): # # clockwise for the inside of the tunnel # # TOP: new-top-left, top-left, new-top-right, top-right # self.triStrips.addConsecutiveVertices(row + 3, 1) # self.triStrips.addConsecutiveVertices(row - verts + 3, 1) # self.triStrips.addConsecutiveVertices(row + 2, 1) # self.triStrips.addConsecutiveVertices(row - verts + 2, 1) # # RIGHT: new-bottom-right, bottom-right # self.triStrips.addConsecutiveVertices(row + 1, 1) # self.triStrips.addConsecutiveVertices(row - verts + 1, 1) # # BOTTOM: new-bottom-left, bottom-left # self.triStrips.addConsecutiveVertices(row, 1) # self.triStrips.addConsecutiveVertices(row - verts, 1) # # LEFT: new top-left, top-left # self.triStrips.addConsecutiveVertices(row + 3, 1) # self.triStrips.addConsecutiveVertices(row - verts + 3, 1) # TOP: new-top-left, top-left, new-top-right, top-right self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.addConsecutiveVertices(row - verts + 2, 1) self.triStrips.addConsecutiveVertices(row + 2, 1) # RIGHT: new-bottom-right, bottom-right self.triStrips.addConsecutiveVertices(row - verts + 1, 1) self.triStrips.addConsecutiveVertices(row + 1, 1) # BOTTOM: new-bottom-left, bottom-left self.triStrips.addConsecutiveVertices(row - verts, 1) self.triStrips.addConsecutiveVertices(row, 1) # LEFT: new top-left, top-left self.triStrips.addConsecutiveVertices(row - verts + 3, 1) self.triStrips.addConsecutiveVertices(row + 3, 1) self.triStrips.closePrimitive() return verts * 4 def completeQuadPath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() vertexReader = GeomVertexReader(self.vertexData, 'vertex') tris = self.triStrips.decompose() print "Decomposed prims:",tris.getNumPrimitives() p = 0 for i in range(tris.getNumPrimitives()): v0 = tris.getPrimitiveStart(i) ve = tris.getPrimitiveEnd(i) if v0 < ve: vertexReader.setRow(tris.getVertex(v0)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0+1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0+2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p+1, p+2) p += 3 self.floorCollNode.addSolid(floorMesh) def completeTunnelPath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() vertexReader = GeomVertexReader(self.vertexData, 'vertex') print "Original prims:",self.triStrips.getNumPrimitives() p = 0 for i in range(self.triStrips.getNumPrimitives()): v0 = self.triStrips.getPrimitiveStart(i) ve = self.triStrips.getPrimitiveEnd(i) j = v0 + 4 # add the bottom triangles vertexReader.setRow(self.triStrips.getVertex(j)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(self.triStrips.getVertex(j+1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(self.triStrips.getVertex(j+2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p+1, p+2) vertexReader.setRow(self.triStrips.getVertex(j+3)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p+1, p+3, p+2) p += 4 # this adds every triangle, but is not appropriate for a closed path # tris = self.triStrips.decompose() # print "Decomposed prims:",tris.getNumPrimitives() # p = 0 # for i in range(tris.getNumPrimitives()): # v0 = tris.getPrimitiveStart(i) # ve = tris.getPrimitiveEnd(i) # if v0 < ve: # vertexReader.setRow(tris.getVertex(v0)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # vertexReader.setRow(tris.getVertex(v0+1)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # vertexReader.setRow(tris.getVertex(v0+2)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # floorMesh.addTriangle(p, p+1, p+2) # p += 3 self.floorCollNode.addSolid(floorMesh) def updatePhysics(self, task): pos = self.fpscamera.getPos() self.info.setText("Position: {0}, {1}, {2}".format(int(pos.x*100)/100., int(pos.y*100)/100., int(pos.z)/100.)) return task.cont