Here’s a great example of using LOD nodes. I cannot post the models I used from here at work since FTP is disallowed by our firewall. I will post the models in ZIP format to my website tonight. Thanks once again to David for helping me understand the concept (discourse.panda3d.org/viewtopic.php?t=2623).
This example is simple. I create 4 torus models as follows:
ID Facets TexSize Filename LOD-Range
1 32x256 1024 Torus_32_256.bam.pz 0-2
2 16x128 512 Torus_16_128.bam.pz 2-3
3 8x64 56 Torus_08_064.bam.pz 3-4
4 4x32 64 Torus_04_032.bam.pz 4-inf
Then I create a single NodePath that handles all four of these models and switches them in and out according to the specified LOD range. All you do is use the trackball to zoom in/out and watch the different resolution models being switched. Use the ‘w’ key to toggle wireframe on and off. Look at the wireframe to easily see the geometry differences, shaded to seel the texture differences.
Enjoy!
Paul
# LODNodeTest1.py
""" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Description: DESCRIPTION_GOES_HERE
$Author: pleopard $
$Modtime: 04/17/07 1:15p $
$Revision: 1 $
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ """
# Standard imports
import sys
# Panda imports
from direct.gui.OnscreenText import OnscreenText
from direct.showbase import DirectObject
from direct.showbase.DirectObject import DirectObject
import direct.directbase.DirectStart
from direct.task import Task
from pandac.PandaModules import *
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def CreateTextLabel(\
text,
color,
i,
xStart=-1.3,
yStart=0.95,
yOffset = 0.1,
tFont=None
):
if tFont==None:
return OnscreenText(\
text = text,
pos = (xStart, yStart-yOffset*i),
fg=color,
mayChange = True,
align=TextNode.ALeft
)
else:
return OnscreenText(\
text = text,
pos = (xStart, yStart-yOffset*i),
fg=color,
mayChange = True,
align=TextNode.ALeft,
font=tFont
)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
class World(DirectObject):
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def __init__(self):
# *** Setup text displays
textXStart=-1.3
textYStart=0.95
textYOffset=0.1
self.mTitleDisplay = \
CreateTextLabel(
"LOD Node Test",
(1.0,1.0,0.0,1.0),
1,
textXStart,
textYStart,
textYOffset
)
self.mMessageDisplay = \
CreateTextLabel(
'> ',
(0.0,1.0,0.0,1.0),
2,
textXStart,
textYStart,
textYOffset
)
# *** Setup world dimensions
maxWorldDim = 1000
worldDims = [maxWorldDim,maxWorldDim,maxWorldDim]
base.camLens.setNearFar(0.1,2.5*maxWorldDim)
# *** Setup lighting
lightLevel=0.7
lightPos=(0.0,-10.0,10.0)
lightHpr=(0.0,-26.0,0.0)
dlight = DirectionalLight('dlight')
dlight.setColor(VBase4(lightLevel, lightLevel, lightLevel, 1))
dlnp = render.attachNewNode(dlight.upcastToPandaNode())
dlnp.setHpr(lightHpr[0],lightHpr[1],lightHpr[2])
dlnp.setPos(lightPos[0],lightPos[1],lightPos[2])
render.setLight(dlnp)
alight = AmbientLight('alight')
alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
alnp = render.attachNewNode(alight.upcastToPandaNode())
# *** Setup scene
base.setBackgroundColor(0.0,0.1,0.7,1.0)
# *** Setup events
self.setupKeyBindings()
# *** Setup models
lodNode = NodePath(FadeLODNode('lod'))
lodNode.reparentTo(render)
lod0 = loader.loadModel("Torii/Torus_04_032")
lod0.reparentTo(lodNode)
lodNode.node().addSwitch(999999, 4)
lod1 = loader.loadModel("Torii/Torus_08_064")
lod1.reparentTo(lodNode)
lodNode.node().addSwitch(4, 3)
lod2 = loader.loadModel("Torii/Torus_16_128")
lod2.reparentTo(lodNode)
lodNode.node().addSwitch(3, 2)
lod3 = loader.loadModel("Torii/Torus_32_256")
lod3.reparentTo(lodNode)
lodNode.node().addSwitch(2, 0)
# *** Done, setup time update task
taskMgr.add(self.timeUpdate,'TimeUpdate')
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def toggleWireFrame(self):
base.toggleWireframe()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def toggleTexture(self):
base.toggleTexture()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def snapShot(self):
base.screenshot("Snapshot")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
def timeUpdate(self,task):
cPos = base.camera.getPos()
s = "Camera Pos : %12.4f %12.4f %12.4f" % (cPos[0],cPos[1],cPos[2])
self.mMessageDisplay.setText(s)
return Task.cont
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Method name : setupKeyBindings
#
# Description:
#
# Load and register key bindings
#
# Input(s):
#
# None
#
# Output(s):
#
# None
#
def setupKeyBindings(self) :
self.accept('p',self.snapShot)
self.accept('w',self.toggleWireFrame)
self.accept('t',self.toggleTexture)
self.accept('escape',sys.exit)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
world = World()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Run the program
run()