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.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
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