very stupid questions (I guess)

Hi, I’ve started to learn Panda 3D scripting but I have 2 annoying problems. First of all loading models, if I try to load a model with a simple function like this:

def loadModel(self):
self.trex = loader.loadModel(‘models/t-rex/trex’)
self.trex.reparentTo(render)

and then I call the function with loadModel() all works fine. But if I create a class World (like in the tutorial) like this:

class World(DirectObject):

def init(self):
self.loadModel()

def loadModel(self):
self.trex = loader.loadModel(‘models/t-rex/trex’)
self.trex.reparentTo(render)

world = World()
base.useDrive()
run()

nothing works, I have the Panda window that opens but nothing’s inside. Why?

Second problem is about the Picker Class, if I try to use it I have an error at the compilation that says:

TypeError: CollisionTraverser::add_collider() argument 1 must be NodePath, not CollisionNode.
The class Picker is available on the website so I don’t understand why it gives me errors.

Thanks for the help.

The camera has a near clipping plane. Anything before that isn’t rendered. Try zooming out.

I tried but it didn’t work…it’s like the model is not there. Besides with the first method I’ve posted all works great…why all chenge if I encapsulate my method in a class?

Lots of things could be wrong. Put your code in a code block:

your code here

and turn on BBCode. Then post it again. Whitespace matters in python, but it doesn’t show up on your post without a code block.

base.useDrive() changes the default camera controls.

What color is the “empty” panda window? What version of Panda3d are you using? Are you running an IDE/debugger?

try this in your code:

base.disableMouse()
base.cam.lookAt(self.trex)

That will disable the default mouse drive, not the mouse itself, and change the camera HPR to aim at your model.

Try if that works. If it does, it means your mouse drive moves the camera so that your model is completely out of sight. It can be difficult to navigate through empty space using the default mouse drive.

this is my code:

import direct.directbase.DirectStart
from pandac.PandaModules import*
from direct.showbase.DirectObject import DirectObject
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import*
from direct.task import Task
import math
import sys
import random


class World(DirectObject):

    def _init_(self):

        #load models
        loadModels()

    #end init

    def loadModels():
        #load T Rex
        trex = loader.loadModel('/c/Documents and Settings/Robin/My Documents/Panda 3D/project01/models/t-rex/trex')
        trex.reparentTo(render)
    #end loadModels

#end Class World

base.useDrive()
world = World()
run()

I tried the lookAt(trex) but it didn’t work.
I use the latest Panda 3D version and I don’t use a debugger, only the Direct Session tool (by the way is there any tutorial about the Direct Session panel?).

OK, several Python scripting problems. You misspelled “[color=indigo]init” . There must be two underscores before and after. If it isn’t spelled exactly this way it is just another method and won’t be automatically called at instantiation.

If you want “[color=indigo]loadModels” to be an instance method you must define it as

def loadModels(self):

as all instance methods must have [color=blue]self as the first argument. To invoke the instance method from within the class use “self.loadModels()” not just “loadModels()”.

If, on the other hand you want “[color=indigo]loadModels” to be a static method, your current definition is fine, but to you need the line

loadModels=staticmethod(loadModels)

after the definition to make it explicitly static. To invoke the static method from within the class use “World.loadModels()” not just “loadModels()”.

I didn’t even know there was a direct session panel until you brought it up. It seems to be completely undocumented. If anyone knows about a tutorial, I would be interested as well.

You should consider using an IDE. It makes debugging much easier. There are many available for free. I use SPE.

You don’t seem to know Python very well, since you can’t make a proper class. That’s OK. It’s easy to learn.

Read Byte of Python. for the basics.
See Dive Into Python for a lot of neat tricks that will make python programming easier.
See http://www.python.org/doc/ (the official website) for refrence. You should become familiar with all the Built-in-funtions

Oh, regarding the second problem.

The error message “argument 1 must be NodePath, not CollisionNode” is as clear as it can get.

Put the CollisionNode instance in a NodePath instance. CollisionNode is a subclass of PandaNode which is not the same thing as a NodePath.

To give you an example it would help to see your code.

thanks, all works fine now :wink:

the code for the Picker class is here:

panda3d.org/manual/index.php/Examp … 3D_Objects

and the other file is taken from this tutorial:

etc.cmu.edu/bvw/scripting/tutorial.html

my code is as follows:

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.showbase.DirectObject import DirectObject
from direct.actor.Actor import Actor
from direct.interval.IntervalGlobal import*
from direct.task import Task
import math
import sys
import random
from Picker import Picker

class World(DirectObject):
    # constructor
    def __init__(self):
        base.disableMouse()
        camera.setPosHpr(Vec3(0,-15,7),Vec3(0,-15,0))

        self.loadModels()

        self.setupLighting()

        #setup targets
        self.setupCollisions()

        # setup key controls
        self.accept("escape",sys.exit)

        self.accept("arrow_up", self.walk)
        self.accept("arrow_left", self.turn,[-1])
        self.accept("arrow_right", self.turn,[1])

        #setup picking
        self.picker = Picker()
        self.panda.setTag("event", "hit-panda")
        self.accept("mouse1", self.pick)
        self.accept("hit-panda", self.hitPanda)

        #start camera task
        taskMgr.add(self.cameraFollowTask, 'cameraFollowTask')
    # end __init__


    def cameraFollowTask(self,task):
        camera.lookAt(self.panda,Point3(0,0,4))
        return Task.cont
    #end cameraFollowtask

    def loadModels(self):
        # load a model
        self.panda = Actor("/c/Panda3D-1.2.3/models/tutorialModels/panda-model",{"walk":"/c/Panda3D-1.2.3/models/tutorialModels/panda-walk4", "eat":"/c/Panda3D-1.2.3/models/tutorialModels/panda-eat"})
        self.panda.reparentTo(render)
        self.panda.setScale(.005)
        self.panda.setH(180)

        #load an environment
        self.environ = loader.loadModel("/c/Panda3D-1.2.3/models/tutorialModels/Environment")
        self.environ.reparentTo(render)
        self.environ.setScale(0.25,0.25,0.25)
        self.environ.setPos(-8,42,0)

        #load targets
        self.targets = []
        for i in range(5):
            target = loader.loadModel("/c/Panda3D-1.2.3/models/tutorialModels/Bambooshoot")
            target.setScale(.1)
            target.setPos(Vec3(random.uniform(-20,20),random.uniform(-15,15),0))
            target.reparentTo(render)
            self.targets.append(target)
    # end loadModels

    def setupCollisions(self):
        #use an event collision handler (sends events on collisions)
        self.cHandler = CollisionHandlerEvent()
        #set the pattern for the event sent on collision
        #"enter" plus the name of the object collided into
        self.cHandler.setInPattern("ate-%in")
        #make a traverser and make it the default traverser
        self.cTrav = CollisionTraverser()
        base.cTrav = self.cTrav

        #add a sphere aroun the manda to be collide with bamboo
        #get the bounding sphere of the panda
        bounds = self.panda.getChild(0).getBounds()
        center = bounds.getCenter()
        radius = bounds.getRadius()
        cSphere = CollisionSphere(center, radius)
        cNode = CollisionNode("Panda")
        cNode.addSolid(cSphere)
        cNode.setIntoCollideMask(BitMask32.allOff())
        cNodePath = self.panda.attachNewNode(cNode)
        #enable this next line if you want to see the area that the collision sphere covers
        cNodePath.show()

        #add the Panda's collision node to the traverser as a collider

        #***---PROBLEM---***

        self.cTrav.addCollider(cNode,self.cHandler)

        #**********************************************

        #add sphere around the bamboos to be collided into
        for target in self.targets:
            cSphere = CollisionSphere(Point3(0,0,15),15)
            cNode = CollisionNode("bamboo")
            cNode.addSolid(cSphere)
            cNodePath = target.attachNewNode(cNode)
            cNodePath.show()

        #listen for collisions from the panda into the bamboo
        self.accept("ate-bamboo", self.eat)
    #end setupCollisions

    def walk(self):
        dist = 5.0
        angle = self.panda.getH()*math.pi/180.0
        dx= dist*math.sin(angle)
        dy = dist*-math.cos(angle)
        pandaWalk = Parallel(
                             self.panda.posInterval(1.0,Vec3(self.panda.getX()+dx,self.panda.getY()+dy,0)),
                             self.panda.actorInterval("walk", loop=1,duration=1.0)
                             )
        pandaWalk.start()
    #end walk

    def turn(self,dir):
             pandaTurn = self.panda.hprInterval(.2,Vec3(self.panda.getH()-(10*dir),0,0))
             pandaTurn.start()
    #end turn

    def eat(self, cEntry):
        self.targets.remove(cEntry.getIntoNodePath().getParent())
        cEntry.getIntoNodePath().getParent().remove()
        pandaEar = self.panda.actorInterval("eat")
        pandaEat.start()
    #end eat

    def setupLighting(self):
         # start with a blank light attribute
        lightAttribute = LightAttrib.makeAllOff()

        # some directional light
        dirLight = DirectionalLight('dirLight')
        dirLight.setColor(Vec4(0.6,0.6,0.6,1.0))
        dirLightNP = render.attachNewNode(dirLight.upcastToPandaNode()) # crashes without upcast
        dirLightNP.setPos(Vec3(0.0,-10.0,10.0))
        dirLightNP.setHpr(Vec3(0.0,-26.0,0.0))
        lightAttribute = lightAttribute.addLight(dirLight) # add to attribute

        # add a little extra ambient lighting just because
        ambientLight = AmbientLight('ambientLight')
        ambientLight.setColor(Vec4(0.25,0.25,0.25,1.0))
        ambientLightNP = render.attachNewNode(ambientLight.upcastToPandaNode())
        lightAttribute = lightAttribute.addLight(ambientLight)

        # apply to world
        render.node().setAttrib(lightAttribute)
    # end setupLighting
    
    def pick(self):
        cEntry = self.picker.pick()
        if (cEntry):
           event = cEntry.gotIntoNodePath().getNetTag("event")
           if (event):
              messenger.send(event)
    #end pick

    def hitPanda(self):
        print "OUCH! You hit the Panda."
        currH = self.panda.getH()
        pandaStunned = Sequence(
                                self.panda.hprInterval(.25,Vec3(currH-20,0,0)),
                                self.panda.hprInterval(.5,Vec3(currH+20,0,0)),
                                self.panda.hprInterval(.25,Vec3(currH,0,0))
                                )
        pandaStunned.Start()
    #end hitPanda

# end class World

world = World()

run()

by the way I have a problem at this line too:

self.cTrav.addCollider(cNode,self.cHandler)

it’s strange because I followed exactly the tutorial instructions.

The tut must be old. There was a little change since V1.1.0.
Pass the nodepath instead of the collision node :
self.cTrav.addCollider(cNodePath,self.cHandler)

It’s important to mind the difference between PandaNodes and NodePaths.

ok, I have to learn these differences…unfortunately the tutorial is old and the problem persist in the class Picker. Picker is a module used to manage clicking on objects…some of you guys have the code of a Picker class that works? Thanks again for the help.

Which Picker class have you used ? Use the one came with Panda, in tut : picking (chessboard).

I used this one:

panda3d.org/manual/index.php/Examp … 3D_Objects

Yup, the manual is old too…

where can I find a new good tutorial?

Have you tried the ones came with Panda ? You can take a look at the picking tutorial (chessboard). It works.

Hello,

The two pages you used as a reference are very old, they apply to Panda versions prior to 1.1. (I think it was internal samples for students). It’s best to work with the tutorials shipped with current versions (they are up to date and well explained) or to use the online manual available from the website.

Anyway, solving errors in an old tutorials give you good debugging knowlegde :slight_smile: