Help for the frame or scene update

Hi,
I met with an issue when rendering a rope and save each frame seperately.
My code is using a loop to generate multiple frames and save each separately :

base = ShowBase()
for t in range(10):
    m = myrope(t)
    base.graphicsEngine.renderFrame()
    base.screenshot(namePrefix='/image_0_'+ str(t) +'.png',
                    defaultFilename=False, source=None, imageComment="")

And each frame is created by class myrope(DirectObject).

It will create all the scenes (from 0 to current t ) together in the current frame, I would like to reinitlize the scene for each frame or remove the scene each time, but can not find the right way.
Could anyone give me some suggestions?
Thanks a lot!

I am really confused which calss controls the scene or window update, is the base or the directObject? I tried many fucntions like base.destroy(), base.restart(), base.funcExit(), they do not work for this.

And how does myModel.removeNode() work ussulally? are there any other examples except
https://docs.panda3d.org/1.10/python/programming/scene-graph/scene-graph-manipulations?highlight=mymodel%20detachnode

Thanks again.

As an example of a restart.

I’m not sure about your main question, but I may be able to help with this one. Could you clarify what you mean, please? Are you asking about how “removeNode” is used, or for what purposes it’s used, or how it works internally, or something else?

Hi Thaumaturge,
Thank you for reply. My code aims to render a rope based on some known postions (x,y,z) :

class myrope(DirectObject):
def init(self, t=0):
# self.reset()
base.setBackgroundColor(1, 1, 1, 1)
base.setFrameRateMeter(True)
base.cam.setPos(0, 0, 30)
base.cam.lookAt(0, 0, 1)
# Light
alight = AmbientLight(‘ambientLight’)
alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
alightNP = render.attachNewNode(alight)

    dlight = DirectionalLight('directionalLight')
    dlight.setDirection(Vec3(5, 0, -2))
    dlight.setColor(Vec4(0, 1, 0, 1))
    dlightNP = render.attachNewNode(dlight)

    render.clearLight()
    render.setLight(alightNP)
    render.setLight(dlightNP)

    for i in range(segs[t].shape[0]):   
        # get the (i,x,y) values for pusher, i is the number of section
        x = segs[t][i,0]*40
        y = segs[t][i,1]*40
        z = segs[t][i,2]*40
        
        self.KPoint = loader.loadModel("models/ball.egg")
        self.KPoint.setPos(x,y,z)
        self.KPoint.setTexture(loader.loadTexture("./models/iron.jpg"))
        self.KPoint.reparentTo(render)

Then I want to create a seires of images by using the loop in previous post.
The question is how I can reset the scene of each loop, that means I need to update while not adding all the scene together. Something like I can do self.reset() when calling the class myrope()…

I fear that I may have written unclearly, and I apologise if so: I was trying to say that this question I’m unsure about, but that I might be able to help with your question regarding “removeNode”. Could you clarify that one–the question about “removeNode”–please?

(I don’t see usage of “removeNode” in the code that you posted.)

Sorry for that, I would like to know if removeNode can be used for reset the scene, I can use it to remove it after
self.KPoint.reparentTo(render)
self.KPoint.removeNode()
But I want remove it after saving each frame in the main loop.

Hmm… I think that you should be able to successfully use “removeNode” in that way. However, I’ll confess that I’ve not tried anything like that myself, and so bow out in favour of those who might know better.

Thank you!
I will try this:)

The basic idea is to wrap the code in a function for reuse.

Firstly, it seems you’re mixing code related to the general scene setup into your myrope class.
Secondly, you are reusing the same self.KPoint variable to assign different model instances to. It would be better to add them to a list. Then you can access those models after rendering a screenshot and detach all of those models by iterating over that list and then clearing that list.

So your code might look something like this:

base = ShowBase()
base.setBackgroundColor(1, 1, 1, 1)
base.setFrameRateMeter(True)
base.cam.setPos(0, 0, 30)
base.cam.lookAt(0, 0, 1)

# Light

alight = AmbientLight('ambientLight')
alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
alightNP = render.attachNewNode(alight)

dlight = DirectionalLight('directionalLight')
dlight.setDirection(Vec3(5, 0, -2))
dlight.setColor(Vec4(0, 1, 0, 1))
dlightNP = render.attachNewNode(dlight)

render.clearLight()
render.setLight(alightNP)
render.setLight(dlightNP)

class myrope(DirectObject):

    def __init__(self, t=0):

        # self.reset()
        self.KPoints = []

        for i in range(segs[t].shape[0]):   
            # get the (i,x,y) values for pusher, i is the number of section
            x = segs[t][i,0]*40
            y = segs[t][i,1]*40
            z = segs[t][i,2]*40
            
            KPoint = loader.loadModel("models/ball.egg")
            KPoint.setPos(x,y,z)
            KPoint.setTexture(loader.loadTexture("./models/iron.jpg"))
            KPoint.reparentTo(render)
            self.KPoints.append(KPoint)

for t in range(10):
    m = myrope(t)
    base.graphicsEngine.renderFrame()
    base.screenshot(namePrefix='/image_0_'+ str(t) +'.png',
                    defaultFilename=False, source=None, imageComment="")

    for point in m.KPoints:
        point.detach_node()

    m.KPoints.clear()

Hi Epihaius,
Thank you so much for the help. It works perfect.
I am really new to Panda3d, but it is nice to learn more.
And I changed the code as:

class mybase(ShowBase):
def init(self):
ShowBase.init(self)

    self.setBackgroundColor(1, 1, 1, 1)
    self.setFrameRateMeter(True)

    self.cam.setPos(0, 0, 30)
    self.cam.lookAt(0, 0, 1)

    # Light
    alight = AmbientLight('ambientLight')
    alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
    alightNP = render.attachNewNode(alight)

    dlight = DirectionalLight('directionalLight')
    dlight.setDirection(Vec3(5, 0, -2))
    dlight.setColor(Vec4(0, 1, 0, 1))
    dlightNP = render.attachNewNode(dlight)

    render.clearLight()
    render.setLight(alightNP)
    render.setLight(dlightNP)

And there is another question on this, I added another object in the same scene, but I need to change the color, here dlight.setColor(Vec4(0, 1, 0, 1)) set both same color, which the best way to set different object with different colors?

You can apply a colour to a NodePath with the “setColor” method–although this may not work with some models. You can also apply a tint to a NodePath with the “setColourScale” method.

For example:

r = 0.1
g = 0.5
b = 1
a = 1
myModel1.setColor(r, g, b, a)

r = 0.3
g = 1
b = 0.1
a = 1
myModel2.setColorScale(r, g, b, a)

(The “a” value here is the value to apply to the “alpha” channel, which controls transparency/opacity.

Note that setting this vaue may not appear to have any effect if transparency is disabled for a given NodePath–which can happen automatically under certain circumstances. In such cases, however, transparency can be manually enabled for the NodePath, in which case the alpha-value should have a visible effect.)

Great! Thank you very much for your help!

1 Like