HPR ..spin question.. and using Blender as your world editor

I did an experiment with Blender. I created 2 cubes. One at the origin and one at (-20, 0,0). I then exported/imported both and set the position of both at (0,0,0) parented to render. As expected, cube1 was at (0,0,0) and the other was at (-20,0,0). But when I used cube.setH(getH()+1) cube1 rotated in place while cube2 rotated around (0,0,0). When I set the position of cube1 to (-20,0,0) and used cube.setH(getH()+1), it rotated in place. I never really noticed this before because I always create my models at the origin in Blender. So I guess if you are using Blender as your world editor you are only places static objects that you have no intention of moving?

Models rotate around their model center, around their origin. In Blender you modeled a mesh 20 units away from its center, and in Panda it rotates around its center, as it should. If you want it to have different behavior, you should shift the model center to the actual data center in Blender.

I’m pretty sure I moved the model center. I never went into edit mode. I moved the model in object mode.

It is easy to check. Open cube.egg in text editor, and find vertices coordinates. If they are something like

    <Vertex> 0 {
      1.0 1.0 -1.0
    }
    <Vertex> 1 {
      1.0 -1.0 -1.0
    }

and so on, then the model center is the data center, if not - it was moved. From your description I am pretty sure it was moved :slight_smile:

Actually, that’s not a reliable way to tell, because of a quirk in egg: (almost) all vertices are reported in world coordinates, even if they are relative to another node. So even if the cube center were successfully offset, it wouldn’t have relative coordinates like this in the egg file.

The way to tell is to look for a entry in the egg file. If you see a by the amount that you shifted the model, then you have successfully shifted the model’s center (and the exporter correctly exported this). If you don’t see a , then either you have not shifted the model’s center, or the exporter did not correctly export the model.

David

Box1 {
{
{
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 1.000000 1.000000
}
}


Box2 {
{
{
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
-30.000000 0.000000 1.038211 1.000000
}
}

That looks right. So then it becomes a question of which node you are grabbing to spin around in-game.

What does your model hierarchy look like? Try the command:

model.ls()

You should see Box1 and Box2, and both of these should have the transforms shown. If you spin either of these nodes, they should spin around their respective origins. If you spin a node above these nodes, the boxes will spin around (0,0,0).

David

None
None
ModelRoot Floor1.egg
PandaNode
GeomNode Floor1 (1 geoms: MaterialAttrib) T:m(scale 9.8)
ModelRoot Floor2.egg
PandaNode
GeomNode Floor2 (1 geoms: MaterialAttrib) T:m(pos -30 0 0 scale 9.8)
None
None
None
ModelRoot Box1.egg
PandaNode
GeomNode Box1 (1 geoms: MaterialAttrib) T:m(pos 0 0 1)
ModelRoot Box2.egg
PandaNode
GeomNode Box2 (1 geoms: MaterialAttrib) T:m(pos -30 0 1.03821)
ModelRoot Box1.egg T:(pos -20 0 0)
PandaNode
GeomNode Box1 (1 geoms: MaterialAttrib) T:m(pos 0 0 1)

import direct.directbase.DirectStart
import sys, math, random
from direct.showbase.DirectObject import DirectObject
from direct.gui.DirectGui import *
from pandac.PandaModules import *
from direct.task.Task import Task
from direct.interval.IntervalGlobal import *
from direct.gui.OnscreenText import OnscreenText




class World (DirectObject):
    def __init__(self):
        
        base.win.setClearColor(Vec4(0,0,0,1))
        base.setBackgroundColor(0,0,0,1)

        self.Floor1 = loader.loadModel('Floor1')
        self.Floor1.reparentTo(render)
        self.Floor1.setPos(0,0,0)
        self.Floor1.setScale(1)
        
        print self.Floor1.ls()

        self.Floor2 = loader.loadModel('Floor2')
        self.Floor2.reparentTo(render)
        self.Floor2.setPos(0,0,0)
        self.Floor2.setScale(1)        
          
        print self.Floor2.ls()
        
        self.Box1 = loader.loadModel('Box1')
        self.Box1.reparentTo(render)
        self.Box1.setPos(0,0,0)
        
        print self.Box1.ls()
            
        self.Box2 = loader.loadModel('Box2')
        self.Box2.reparentTo(render)
        self.Box2.setPos(0,0,0)
        
        print self.Box2.ls()
        
        self.Box3 = loader.loadModel('Box1')
        self.Box3.reparentTo(render)
        self.Box3.setPos(-20,0,0)
        
        print self.Box3.ls()

        self.loadLightsF()
  
        #set the 'camera'
        base.oobe()
        base.disableMouse()

        taskMgr.add(self.rotateT, "rotateT")

                
    def rotateT(self,task):
        self.Box1.setH(self.Box1.getH()+1)
        self.Box2.setH(self.Box2.getH()+1)
        self.Box3.setH(self.Box3.getH()+1)
        return Task.cont
    
    
    
    def loadLightsF(self):
        #lights
        self.alight = AmbientLight('alight')
        self.alight.setColor(VBase4(0.5, 0.5, 0.5, 1))
        self.alnp = render.attachNewNode(self.alight)
        self.alnp.setPos(0,0,1)
        render.setLight(self.alnp)

        self.plight = PointLight('plight')
        self.plight.setColor(VBase4(1, 1, 1, 1))
        self.plight.setAttenuation(Point3(0,0, 0.16))
        self.plnp = render.attachNewNode(self.plight)
        self.plnp.setPos(0,0,3)
        render.setLight(self.plnp) 
        
        self.plight2 = PointLight('plight2')
        self.plight2.setColor(VBase4(1, 1, 1, 1))
        self.plight2.setAttenuation(Point3(0,0, 0.16))
        self.plnp2 = render.attachNewNode(self.plight2)
        self.plnp2.setPos(-10,0,3)
        render.setLight(self.plnp2) 
    
 
            
w=World()
run()

Ah, see, you are manipulating the entire model, not just the node in question.

Try something like this:

self.Box2 = loader.loadModel('Box2')
self.Box2 = self.Box2.find('**/Box2')
self.Box2.reparentTo(render)

Note that if you then do self.Box2.setPos(0, 0, 0) you will remove the transform you have applied in the model.

David

I see. So then you need to write down all the transform values for all the models, avoid any reference to them by using

self.Box2 = self.Box2.find('**/Box2')

and then code them in one by one using setPostion?

Huh? No, the position is already there. Just don’t do a new setPos() on top of it; that would replace the position that’s already there with the new position you specify (in your example, 0,0,0).

You don’t need to write anything down. That would be silly.

David

I see. It works now.

So, I can use .setPos() afterwards:

        self.Box2 = loader.loadModel('Box2') 
        self.Box2 = self.Box2.find('**/Box2') 
        self.Box2.reparentTo(render)  
        self.Box2.setPos(-20,0,0) #test

One thing I’m noticing is a change in Z position now when I use .setPos(). I guess its using the model’s center now, so the model is half below the XY plane.

import direct.directbase.DirectStart 
import sys, math, random 
from direct.showbase.DirectObject import DirectObject 
from direct.gui.DirectGui import * 
from pandac.PandaModules import * 
from direct.task.Task import Task 
from direct.interval.IntervalGlobal import * 
from direct.gui.OnscreenText import OnscreenText 




class World (DirectObject): 
    def __init__(self): 
        
        base.win.setClearColor(Vec4(0,0,0,1)) 
        base.setBackgroundColor(0,0,0,1) 

        #FLOOR
        self.Floor1 = loader.loadModel('Floor1') 
        self.Floor1.reparentTo(render) 
        self.Floor1.setPos(0,0,0) 
        self.Floor1.setScale(1)         
        print "FLOOR 1",self.Floor1.ls() 

        self.Floor2 = loader.loadModel('Floor2') 
        self.Floor2.reparentTo(render) 
        self.Floor2.setScale(1)            
        print "FLOOR 2",self.Floor2.ls() 
        
        #BOXES
        self.Box1 = loader.loadModel('Box1') 
        self.Box1.reparentTo(render)        
        print "..BOX 1..",self.Box1.ls() 
        
        self.Box2 = loader.loadModel('Box2') 
        self.Box2 = self.Box2.find('**/Box2') 
        self.Box2.reparentTo(render)  
        self.Box2.setPos(-20,0,0) #test
        print "...BOX 2...",self.Box2.ls() 
        
        #LIGHTS
        self.loadLightsF() 
  
        #set the 'camera' 
        base.oobe() 
        base.disableMouse() 

        #TASKS
        taskMgr.add(self.rotateT, "rotateT") 

    #FUNCTIONS            
    def rotateT(self,task): 
        self.Box1.setH(self.Box1.getH()+1) 
        
        self.Box2.setX(self.Box2.getX()+0.001) #test setX
        self.Box2.setH(self.Box2.getH()+1) 
        print "box2 X pos", self.Box2.getX()
        return Task.cont   
    
    def loadLightsF(self): 
        #lights 
        self.alight = AmbientLight('alight') 
        self.alight.setColor(VBase4(0.5, 0.5, 0.5, 1)) 
        self.alnp = render.attachNewNode(self.alight) 
        self.alnp.setPos(0,0,1) 
        render.setLight(self.alnp) 

        self.plight = PointLight('plight') 
        self.plight.setColor(VBase4(1, 1, 1, 1)) 
        self.plight.setAttenuation(Point3(0,0, 0.16)) 
        self.plnp = render.attachNewNode(self.plight) 
        self.plnp.setPos(0,0,3) 
        render.setLight(self.plnp) 
        
        self.plight2 = PointLight('plight2') 
        self.plight2.setColor(VBase4(1, 1, 1, 1)) 
        self.plight2.setAttenuation(Point3(0,0, 0.16)) 
        self.plnp2 = render.attachNewNode(self.plight2) 
        self.plnp2.setPos(-10,0,3) 
        render.setLight(self.plnp2) 
    
  
            
w=World() 
run()