Try it for yourself…
Zip of the models directory.
main.py:
# Lighting Test
from pandac.PandaModules import loadPrcFileData
loadPrcFileData("", '''
show-frame-rate-meter #t
''')
from pandac.PandaModules import *
from direct.gui.OnscreenText import OnscreenText
from flycam import Flycam
from wireGeom import wireGeom
import sys
import direct.directbase.DirectStart
font = loader.loadFont("cmss12")
def makeStatusLabel(i, str):
text = OnscreenText(
style=1, fg=(1,1,0,1), pos=(-1.3, 0.95 - (.05 * i)), font = font,
align=TextNode.ALeft, scale = .05, mayChange = 1)
text.setText (str)
return text
makeStatusLabel (0, 'Keys:')
makeStatusLabel (1, 'Camera control: ASDW for movement, mouse to look')
makeStatusLabel (2, '[1] Show Geomipterrain')
makeStatusLabel (3, '[2] Show reference Egg')
# turn on autoshaders
render.setShaderAuto()
# turn off the base.camera mousenav stuff
base.disableMouse()
# instead, we're going to use our flycam class
flycam = Flycam ()
flycam.flycamNP.setPos (250, -250, 250)
flycam.flycamNP.lookAt (0, 0, 70)
flycam.acquireInput()
flycam.acquireCamera()
base.accept("escape", sys.exit) #Escape quits
# Let's create a basic terrain
geomipterrain = GeoMipTerrain ('geomipterrain')
geomipterrain.setBlockSize (64)
geomipterrain.setNearFar (80, 100)
geomipterrain.setHeightfield ('models/heightmap.png')
geomipterrain.setAutoFlatten (GeoMipTerrain.AFMOff)
geomipterrain.setFocalPoint(flycam.flycamNP)
geomipterrain.setBruteforce(True)
geomipterrain.setMinLevel(3)
terrainRoot = geomipterrain.getRoot()
terrainRoot.setSz (100) # give us some significant height differences
terrainRoot.setPos (Point3(-512/2, -512/2, 0)) # let's re-center the terrain
terrainRoot.reparentTo (render)
# generate terrain squares
geomipterrain.generate()
# now, let's assign a texture
terrainRoot.clearTexture()
ts = TextureStage('baseColor')
tex = loader.loadTexture('models/colormap.png')
tex.setMagfilter (Texture.FTLinear)
tex.setMinfilter (Texture.FTLinearMipmapLinear)
terrainRoot.setTexture(ts, tex)
# define a shiny material so we can also see some specular lighting on our
# terrain when autoshader is on
terrainMat = Material()
terrainMat.setShininess (12.5)
terrainMat.setAmbient (VBase4 (1, 1, 1, 1))
terrainMat.setDiffuse (VBase4 (1, 1, 1, 1))
terrainMat.setEmission (VBase4 (0, 0, 0, 0))
terrainMat.setSpecular (VBase4 (1, 1, 1, 1))
terrainRoot.setMaterial (terrainMat)
# load a generic flashlight model
flashlight = loader.loadModel ('models/flashlight.egg')
# we use the bump-objs to sanity check
bumpsphere = loader.loadModel ('models/bumpyobjects.egg')
bumpsphere.reparentTo (render)
bumpsphere.setScale (10)
bumpsphere.setPos (0, 20, 70)
bumpsphere.flattenStrong()
# load a pack-in model
panda = loader.loadModel ('models/panda.egg')
panda.reparentTo (render)
panda.setScale (5)
panda.setPos (0, 40, 70)
panda.flattenStrong()
# load a reference terrain
refterrain = loader.loadModel ('models/refterrain.egg')
refterrain.reparentTo (render)
refterrain.setPos (0, 0, 50)
refterrain.setScale (256)
refterrain.flattenStrong()
refterrain.hide()
# create a node to spin around for spot light
lightspinner = render.attachNewNode('spinner')
lightSpin = lightspinner.hprInterval(10.0,Point3(-360,0,0),startHpr=Point3(0,0,0))
lightSpin.loop()
# create a directional light
dlight = render.attachNewNode(DirectionalLight('directional'))
dlight.node().setColor(VBase4(1.0, 1.0, 1.0, 1.0))
#dlight.node().setDirection( Vec3( 1, 1, -2 ) )
dlight.setPos (100, 100, 100)
dlight.lookAt (0, 0, 0) # let Panda set dir for us
render.setLight(dlight)
dflashlight = flashlight.copyTo (dlight)
dflashlight.setScale (10)
# create a spinning spotlight
slight = lightspinner.attachNewNode(Spotlight('slight'))
lens = PerspectiveLens()
slight.node().setLens(lens)
slight.node().setColor(VBase4(1, 0, 0, 1))
slight.setPos(100, 100, 200)
slight.lookAt(0, 0, 90)
render.setLight(slight)
sflashlight = flashlight.copyTo (slight)
sflashlight.setScale (10)
sflashlight.setColor (VBase4(1, 0, 0, 1))
# set an ambient light
alight = render.attachNewNode (AmbientLight('ambient'))
alight.node().setColor(VBase4(0.1, 0.1, 0.1, 1.0))
render.setLight(alight)
def updateFrame(task):
dt = ClockObject.getGlobalClock().getDt()
geomipterrain.update()
flycam.frameUpdate (dt)
return task.cont
def hideObj(what):
if what == 2:
terrainRoot.hide()
refterrain.show()
if what == 1:
terrainRoot.show()
refterrain.hide()
base.taskMgr.add(updateFrame, 'updateFrame')
base.accept ('1', hideObj, [1])
base.accept ('2', hideObj, [2])
# do it
run()
Flycam.py:
# To change this template, choose Tools | Templates
# and open the template in the editor.
import math
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.showbase import DirectObject
from direct.showbase.InputStateGlobal import inputState
from direct.task.Task import Task
from pandac.PandaModules import *
class Flycam (DirectObject.DirectObject):
def __init__ (self):
# not really a whole lot this, just create a node to manipulate
self.flycamNP = render.attachNewNode('flycam')
def acquireInput (self):
# set input watches
self.forwardControl = inputState.watch ('camforward', 'w', 'w-up')
self.reverseControl = inputState.watch ('camreverse', 's', 's-up')
self.leftControl = inputState.watch ('camleft', 'a', 'a-up')
self.rightControl = inputState.watch ('camright', 'd', 'd-up')
self.accelControl = inputState.watch ('camaccel', 'shift', 'shift-up')
self.accept ('v', self.toggleOOBE)
def releaseInput (self):
self.forwardControl.release()
self.reverseControl.release()
self.leftControl.release()
self.rightControl.release()
self.accelControl.release()
self.ignoreAll() # unregister our events
def acquireCamera (self, oobeCenter = None):
base.camera.reparentTo(self.flycamNP)
# make sure pointer is centered
base.win.movePointer(0, 400, 300)
self.oobeCenter = oobeCenter
def releaseCamera (self):
try:
if self.oobeEnabled:
self.toggleOOBE()
except:
pass
base.camera.reparentTo(render)
def toggleOOBE (self):
# first, do we have a valid nodepath for our cull center?
# todo
try:
self.oobeEnabled
except:
self.oobeEnabled = False
if self.oobeEnabled:
for cam in base.camList:
cam.node().setCullCenter(NodePath())
self.oobeEnabled = False
else:
for cam in base.camList:
cam.node().setCullCenter(self.oobeCenter)
self.oobeEnabled = True
def frameUpdate (self, dt):
inputFwd = inputState.isSet("camforward")
inputBack = inputState.isSet("camreverse")
inputLeft = inputState.isSet("camleft")
inputRight = inputState.isSet("camright")
inputAccel = inputState.isSet("camaccel")
cam_sensitivity = 0.25 * 1.5
speed = 0.35 * 8.0
strafe_speed = 0.2 * 8.0
if inputAccel:
accel = 4.0
else:
accel = 1.0
# Mouse Control
md = base.win.getPointer(0)
x = md.getX()
y = md.getY()
rotx, roty = 0, 0
if base.win.movePointer(0, 400, 300):
rotx -= (x - 400) * cam_sensitivity
roty -= (y - 300) * cam_sensitivity
if (roty < -80): roty = -80
if (roty > 80): roty = 80
self.flycamNP.setHpr(self.flycamNP.getH() + rotx, self.flycamNP.getP() + roty, 0)
forward_dir = self.flycamNP.getNetTransform().getMat().getRow3(1)
strafe_dir = self.flycamNP.getNetTransform().getMat().getRow3(0)
forward_dir.normalize()
strafe_dir.normalize()
forward_dir *= speed * accel
strafe_dir *= strafe_speed * accel
if inputFwd:
self.flycamNP.setPos(self.flycamNP.getPos() + forward_dir)
if inputBack:
self.flycamNP.setPos(self.flycamNP.getPos()-forward_dir)
if inputLeft:
self.flycamNP.setPos(self.flycamNP.getPos()-strafe_dir)
if inputRight:
self.flycamNP.setPos(self.flycamNP.getPos() + strafe_dir)