Sorry, never did publish the source for this and now it seems I’ve lost most assets for this demo.
I do have a backup of the code, but I don’t think the ideas I had back then are actually any good, but well… here you go:
main.py
from panda3d.core import loadPrcFileData
from direct.showbase.AppRunnerGlobal import appRunner
if appRunner:
path=appRunner.p3dFilename.getDirname()+'/config.cfg'
else: #for testing
path='config.cfg'
try:
f = open(path, 'r')
for line in f:
if not line.startswith('#'):
loadPrcFileData('',line)
except IOError:
print "No config file, using default"
from panda3d.core import WindowProperties
from panda3d.core import ConfigVariableInt
cfg_win_size=ConfigVariableInt('win-size', '640 480')
wp = WindowProperties.getDefault()
wp.setSize(cfg_win_size.getWord(0),cfg_win_size.getWord(1))
wp.setTitle('wezu Terrain Demo v0.3')
WindowProperties.setDefault(wp)
from panda3d.core import *
from direct.showbase.DirectObject import DirectObject
import direct.directbase.DirectStart
from direct.task import Task
from direct.actor.Actor import Actor
from CameraControll import CameraControll
from PlayerCharacter import PlayerCharacter
from PlayerControll import PlayerControll
from direct.filter.CommonFilters import CommonFilters
from direct.gui.OnscreenImage import OnscreenImage
from direct.filter.FilterManager import FilterManager
class World(DirectObject):
def __init__(self):
render.setShaderAuto()
base.setBackgroundColor(1, 1, 1)
base.camLens.setFar(35)
cfg_shadow_size=ConfigVariableInt('shadow-map-size', 1024)
cfg_tex_size=ConfigVariableInt('terrain-texture-size', 2048)
cfg_use_normal_map=ConfigVariableInt('use-normal-mapping', 1)
self.useNormal=cfg_use_normal_map #hack ;/
cfg_soft_shadows=ConfigVariableInt('soft-shadws', 1)
cfg_use_shadows=ConfigVariableInt('use-shadows', 1)
self.useShadow=cfg_use_shadows #hack ;/
maker = CardMaker( 'sky_card' )
maker.setFrame( -15, 15, -10, 22 )
self.sky = render.attachNewNode(maker.generate())
sky_texture=loader.loadTexture('sky.png')
sky_texture.setWrapV(Texture.WMClamp )
self.sky.setTexture(TextureStage('ts2'), sky_texture )
self.sky.setBin('background', 1)
self.sky.setDepthWrite(0)
self.sky.setBillboardPointWorld()
self.sky.setLightOff()
self.sky.hide(BitMask32.bit(1))
self.player=PlayerCharacter("kasia_model", "kasia_run", "kasia_idle", 0.06)
PlayerControll(self.player, 50)
self.terrain=loader.loadModel("terrain1")
#self.terrain=loader.loadModel("plane")
self.terrain.reparentTo(render)
self.terrain.setTransparency(TransparencyAttrib.MAlpha )
self.terrain.hide(BitMask32.bit(1))
taskMgr.add(self.update, 'updateTask',sort=2)
fbprops = FrameBufferProperties()
fbprops.setColorBits(1)
fbprops.setAlphaBits(0)
fbprops.setDepthBits(0)
fbprops.setStencilBits(0)
fbprops.setAccumBits(0)
fbprops.setBackBuffers(0)
colorTexture=Texture()
normalTexture=Texture()
shadowTexture=Texture()
altRender=NodePath("bufferRender")
altRenderN=NodePath("bufferRenderN")
#make the buffer
mainWindow=base.win
altBuffer=mainWindow.makeTextureBuffer("modulate_tex_buffer", cfg_tex_size, cfg_tex_size, colorTexture,False, fbprops)
self.altCam=base.makeCamera(win=altBuffer)
self.altCam.reparentTo(altRender)
self.altCam.setPos(0,0,2)
self.altCam.setP(-90)
self.lens = OrthographicLens()
self.lens.setFilmSize(8, 8)
self.altCam.node().setLens(self.lens)
#self.altCam.node().showFrustum()
colorTexture.setWrapU(Texture.WMBorderColor )
colorTexture.setWrapV(Texture.WMBorderColor )
colorTexture.setBorderColor(Vec4(1,1,1,0))
#print cfg_use_normal_map
if(cfg_use_normal_map.getValue ()==1):
altBufferN=mainWindow.makeTextureBuffer("normal_tex_buffer", cfg_tex_size, cfg_tex_size,normalTexture, False, fbprops)
self.altCamN=base.makeCamera(altBufferN)
self.altCamN.reparentTo(altRenderN)
self.altCamN.setPos(0,0,2)
self.altCamN.setP(-90)
self.altCamN.node().setLens(self.lens)
#altBuffer.getTexture().setAlphaFilename('mask4.png')
normalTexture.setWrapU(Texture.WMBorderColor )
normalTexture.setWrapV(Texture.WMBorderColor )
normalTexture.setBorderColor(Vec4(.5, .5, 1, 1))
#view the buffer
#base.bufferViewer.toggleEnable()
#base.bufferViewer.setPosition("llcorner")
#base.bufferViewer.setCardSize(.5, 0.0)
#texture
self.grass1=loader.loadModel("grass1_plane")
self.grass1.reparentTo(altRender)
self.grass2=loader.loadModel("grass2_plane")
self.grass2.reparentTo(altRender)
self.rock1=loader.loadModel("rock1_plane")
self.rock1.reparentTo(altRender)
self.rock2=loader.loadModel("rock2_plane")
self.rock2.reparentTo(altRender)
self.road1=loader.loadModel("road1_plane")
self.road1.reparentTo(altRender)
self.road2=loader.loadModel("road2_plane")
self.road2.reparentTo(altRender)
self.snow=loader.loadModel("snow_plane")
self.snow.reparentTo(altRender)
#normal texture
if(cfg_use_normal_map.getValue ()==1):
self.grass1N=loader.loadModel("grass1_plane")
self.grass1N.setTexture(self.grass1N.findTextureStage('Tex20'),loader.loadTexture('grass_normal.jpg'),1)
self.grass1N.reparentTo(altRenderN)
self.grass2N=loader.loadModel("grass2_plane")
self.grass2N.setTexture(self.grass2N.findTextureStage('Tex20'),loader.loadTexture('grass2_normal.jpg'),1)
self.grass2N.reparentTo(altRenderN)
self.rock1N=loader.loadModel("rock1_plane")
self.rock1N.setTexture(self.rock1N.findTextureStage('Tex20'),loader.loadTexture('rock_normal.jpg'),1)
self.rock1N.reparentTo(altRenderN)
self.rock2N=loader.loadModel("rock2_plane")
self.rock2N.setTexture(self.rock2N.findTextureStage('Tex20'),loader.loadTexture('rock2_normal.jpg'),1)
self.rock2N.reparentTo(altRenderN)
self.road1N=loader.loadModel("road1_plane")
self.road1N.setTexture(self.road1N.findTextureStage('Tex20'),loader.loadTexture('sand_normal.jpg'),1)
self.road1N.reparentTo(altRenderN)
self.road2N=loader.loadModel("road2_plane")
self.road2N.setTexture(self.road2N.findTextureStage('Tex20'),loader.loadTexture('coble_normal.jpg'),1)
self.road2N.reparentTo(altRenderN)
self.snowN=loader.loadModel("snow_plane")
self.snowN.setTexture(self.snowN.findTextureStage('Tex20'),loader.loadTexture('snow_normal.jpg'),1)
self.snowN.reparentTo(altRenderN)
#Create a buffer for storing the shadow texture,
#the higher the buffer size the better quality the shadow.
if(cfg_use_shadows.getValue ()==1):
self.shadowBuffer = base.win.makeTextureBuffer("Shadow Buffer",cfg_shadow_size, cfg_shadow_size,shadowTexture, False, fbprops)
self.shadowBuffer.setClearColorActive(True)
self.shadowBuffer.setClearColor((0,0,0,1))
self.shadowCamera = base.makeCamera(self.shadowBuffer)
self.shadowCamera.reparentTo(render)
self.shadow_lens = PerspectiveLens()
self.shadow_lens.setFov(100)
self.shadow_lens.setNearFar(1,6)
self.shadowCamera.node().setLens(self.shadow_lens)
self.shadowCamera.node().setCameraMask(BitMask32.bit(1))
#Make everything rendered by the shadow camera grey:
self.initial = NodePath('initial')
self.initial.setColor(.75,.75,.75,1,1)
self.initial.setTextureOff(2)
self.initial.setMaterialOff(2)
self.initial.setLightOff(2)
self.shadowCamera.node().setInitialState(self.initial.getState())
self.shadowCamera.setP(-90)
#self.shadowCamera.node().showFrustum()
if(cfg_soft_shadows.getValue()==1):
self.filters = CommonFilters(self.shadowBuffer,self.shadowCamera)
self.filters.setBlurSharpen(.2)
if(cfg_use_shadows.getValue ()==1):
shadowTexture.setWrapU(Texture.WMBorderColor )
shadowTexture.setWrapV(Texture.WMBorderColor )
shadowTexture.setBorderColor(Vec4(0,0,0,1))
shadow_ts=TextureStage('shadow')
shadow_ts.setMode(TextureStage.MBlend)
self.terrain.projectTexture(shadow_ts , shadowTexture, self.shadowCamera)
if(cfg_use_normal_map.getValue ()==1):
normal_ts = TextureStage('ts')
normal_ts.setMode(TextureStage.MNormal)
self.terrain.projectTexture(normal_ts , normalTexture, self.altCam)
color_ts=TextureStage('color')
color_ts.setMode(TextureStage.MModulate)
self.terrain.projectTexture(color_ts , colorTexture, self.altCam)
#fog
fog=loader.loadTexture('mask7.png')
fog.setBorderColor(Vec4(1, 1, 1, 0))
fog.setWrapU(Texture.WMBorderColor)
fog.setWrapV(Texture.WMBorderColor)
fog_ts=TextureStage('ts')
fog_ts.setMode(TextureStage.MModulate)
#self.terrain.projectTexture(fog_ts, fog, self.altCam)
#light
alight = AmbientLight('alight')
alnp = render.attachNewNode(alight)
alight.setColor(Vec4(.3, .3, .35, 1))
render.setLight(alnp)
self.pLight = PointLight('plight')
self.pLight.setColor(VBase4(.6, .6, .6, 1))
self.pLight.setAttenuation(Point3(0, 0.1, 0.08))
self.pLightNode = self.player.PC.attachNewNode(self.pLight)
self.pLightNode.setPos(0,-15,50)
render.setLight(self.pLightNode)
#self.spot=Spotlight('spot')
#self.spot.setColor(VBase4(.8, .8, .8, 1))
#self.spot= self.player.PC.attachNewNode(self.spot)
#self.spot.setP(-90)
#self.spot.setPos(0,0,120)
#self.spot.node().getLens().setNearFar(100,180)
#self.spot.node().getLens().setFov(60)
#self.spot.node().setShadowCaster(True,1024,1024)
#self.spot.node().showFrustum()
#render.setLight(self.spot)
#self.player.PC.setLightOff(self.spot)
dlight = DirectionalLight('dlight')
dlight.setColor(VBase4(.8, .8, .8, 1))
dlnp = render.attachNewNode(dlight)
dlnp.setHpr(0, -90, 0)
render.setLight(dlnp)
#collisions
self.picker = CollisionTraverser()
self.pq = CollisionHandlerQueue()
self.pointerGroundRay = CollisionRay()
self.pointerGroundRay.setOrigin(0,0,1000)
self.pointerGroundRay.setDirection(0,0,-1)
self.pointerGroundCol = CollisionNode('pointerRay')
self.pointerGroundCol.addSolid(self.pointerGroundRay)
self.pointerGroundCol.setIntoCollideMask(BitMask32(0))
self.pointerGroundColNp = self.player.PC.attachNewNode(self.pointerGroundCol)
self.picker.addCollider(self.pointerGroundColNp, self.pq)
CameraControll(self.player,20, -1, self.lens)
#print "Buffer properties", altBuffer.getFbProperties()
#print isinstance(altBuffer, ParasiteBuffer)
#self.accept('x', altBuffer.saveScreenshot, ['test2.png'])
manager = FilterManager(altBuffer, self.altCam)
tex = Texture()
quad = manager.renderSceneInto(colortex=tex)
quad.setShader(Shader.load("myfilter.sha"))
quad.setShaderInput("tex", tex)
quad.setShaderInput("mask", fog)
def update(self, task):
z=0
self.picker.traverse(render)
if self.pq.getNumEntries() > 0:
self.pq.sortEntries()
z=self.pq.getEntry(0).getSurfacePoint(render).getZ()
x = self.player.getX()
y = self.player.getY()
self.altCam.setPos(x,y,2)
if(self.useNormal.getValue()==1):
self.altCamN.setPos(x,y,2)
self.player.updateZ(z)
self.sky.setPos(x,y,base.camera.getZ(render))
if(self.useShadow.getValue ()==1):
self.shadowCamera.setPos(x,y-1,z+5)
return task.cont
w = World()
run()
PlayerControll.py
from panda3d.core import *
from direct.showbase.DirectObject import DirectObject
from direct.task import Task
class PlayerControll(DirectObject):
def __init__(self, player,moveSpeed=10, turnSpeed=100, forward_key="w", back_key="s", left_key="a", right_key="d"):
self.keyMap = {"left":0, "right":0, "forward":0, "back":0}
self.accept(left_key, self.setKey, ["left",1])
self.accept(right_key, self.setKey, ["right",1])
self.accept(forward_key, self.setKey, ["forward",1])
self.accept(back_key, self.setKey, ["back",1])
self.accept(left_key+"-up", self.setKey, ["left",0])
self.accept(right_key+"-up", self.setKey, ["right",0])
self.accept(forward_key+"-up", self.setKey, ["forward",0])
self.accept(back_key+"-up", self.setKey, ["back",0])
self.moveSpeed=moveSpeed
self.turnSpeed=turnSpeed
self.player=player
self.isMoving=False
taskMgr.add(self.moveTask, 'moveTask',sort=-101)
def setKey(self, key, value):
self.keyMap[key] = value
if(self.keyMap["forward"]+self.keyMap["back"]==0):
self.player.stop()
def moveTask(self, task):
if (self.keyMap["left"]!=0):
self.player.turn(globalClock.getDt()*self.turnSpeed)
if (self.keyMap["right"]!=0):
self.player.turn(-globalClock.getDt()*self.turnSpeed)
if (self.keyMap["forward"]!=0):
self.player.move(globalClock.getDt()*self.moveSpeed)
if (self.keyMap["back"]!=0):
self.player.move(-globalClock.getDt()*self.moveSpeed)
return task.cont
PlayerCharacter.py
from panda3d.core import *
from direct.actor.Actor import Actor
class PlayerCharacter():
def __init__(self, model_name, walk_anim, idle_anim, scale=1, pos=(0, 0, 0)):
self.PC = Actor(model_name,{"walk": walk_anim, "idle": idle_anim})
self.PC.setBlend(frameBlend = True)
self.PC.setPos(pos)
self.PC.setScale(scale)
self.PC.reparentTo(render)
self.PC.loop("idle")
def move(self, how_far):
self.PC.setY(self.PC, -how_far)
rate=1
if(how_far<0):
rate=-1
self.PC.setPlayRate(rate, "walk")
if(self.PC.getCurrentAnim()!="walk"):
self.PC.loop("walk")
def stop(self):
self.PC.loop("idle")
def turn(self, how_much):
self.PC.setH(self.PC.getH()+ how_much)
def updateZ(self, z):
self.PC.setZ(z)
def getPos(self):
return self.PC.getPos()
def getX(self):
return self.PC.getX()
def getY(self):
return self.PC.getY()
def getZ(self):
return self.PC.getZ()
CameraControll.py
from panda3d.core import *
from direct.showbase.DirectObject import DirectObject
from direct.task import Task
class CameraControll(DirectObject):
def __init__(self, parent, max_zoom=90, min_zoom=2, terrain_lens=None, offset=(0, -5, .6), speed=200, main_key="mouse3", zoom_in="wheel_up", zoom_out="wheel_down"):
base.disableMouse()
base.camera.setPos(offset)
self.cameraNode = NodePath(PandaNode("cameraNode"))
self.cameraNode.reparentTo(render)
base.camera.reparentTo(self.cameraNode)
self.parent=parent
self.isIdle=True
self.speed=speed
self.zoomfactor=base.camera.getY()
self.maxZoom=max_zoom
self.minZoom=min_zoom
self.terrain_lens=terrain_lens
self.accept(zoom_in, self.zoom, [1])
self.accept(zoom_out, self.zoom, [-1])
self.accept(main_key, self.rotateCamera)
taskMgr.add(self.cameraTask, 'cameraTask')
def rotateCamera(self):
if (self.isIdle):
centerx = base.win.getProperties().getXSize()/2
centery = base.win.getProperties().getYSize()/2
base.win.movePointer(0,centerx,centery)
self.isIdle=False
else:
self.isIdle=True
def zoom(self, out):
self.zoomfactor=self.zoomfactor+out
if self.zoomfactor<self.minZoom and self.zoomfactor>-self.maxZoom:
base.camera.setY(base.camera, out)
if not(self.terrain_lens==None):
size=-base.camera.getY()
if(size<6):
size=6
#print size
self.terrain_lens.setFilmSize(size, size)
else:
self.zoomfactor=self.zoomfactor-out
def cameraTask(self, task):
if base.mouseWatcherNode.hasMouse():
mpos = base.mouseWatcherNode.getMouse()
if (not self.isIdle):
self.cameraNode.setH(self.cameraNode.getH()+mpos.getX()*globalClock.getDt()*-self.speed)
self.cameraNode.setP(self.cameraNode.getP()+mpos.getY()*globalClock.getDt()*self.speed)
if self.cameraNode.getP()>40:
self.cameraNode.setP(40)
if self.cameraNode.getP()<-80:
self.cameraNode.setP(-80)
self.cameraNode.setPos(self.parent.getPos())
return task.cont
myfilter.sha
//Cg
void vshader(
float4 vtx_position : POSITION,
float2 vtx_texcoord0 : TEXCOORD0,
out float4 l_position : POSITION,
out float2 l_texcoord0 : TEXCOORD0,
uniform float4 texpad_tex,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
l_texcoord0 = vtx_position.xz * texpad_tex.xy + texpad_tex.xy;
}
void fshader(float2 l_texcoord0 : TEXCOORD0,
out float4 o_color : COLOR,
uniform sampler2D k_tex : TEXUNIT0,
uniform sampler2D k_mask : TEXUNIT1)
{
float4 c = tex2D(k_tex, l_texcoord0);
float4 a = tex2D(k_mask, l_texcoord0);
o_color = float4(c.x, c.y, c.z, a.a);
}