Cannot get texture data


#1

Hi all,
I should get the render data to process it, so I’m trying to render to a texture buffer.
I followed the example on the manual I couldn’t make it work. When the step function is called it returns an empty object.
Any suggestion?
Thanks.

class ChronoPandaInterface(ShowBase):
    ChBodyList = []
    ModelList = []
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)
        
        mybuffer =  base.win.makeTextureBuffer("Buffer", 512, 512)
        mytexture = mybuffer.getTexture()
        mybuffer.setSort(-100)
        mycamera = base.makeCamera(mybuffer)
        myscene = NodePath("My Scene")
        mycamera.reparentTo(myscene)
        self.texture = mybuffer.getTexture()
        

        self.accept('escape', sys.exit)  # Escape quits
        self.disableMouse()  # Disble mouse camera control

        self.setupLights()  # Setup default lighting
    

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
        
        
    """Function called at each step to update rendered bodies positions 
       according to the position af their respective modelled bodies"""    
    def Update_Pos(self):
           for model, body in zip(self.ModelList, self.ChBodyList) :
                  new_pos = body.GetPos()
                  model.setPos(new_pos.x, new_pos.y, new_pos.z)
                  new_ori = body.GetRot()
                  q = Quat(new_ori.e0, new_ori.e1, new_ori.e2, new_ori.e3)
                  model.setQuat(q)

    """Function used to update the visualization
    It shouldn't be called at each simulation step"""                    
    def Advance(self):
           
           self.Update_Pos()
           self.taskMgr.step()
           return self.texture

#2

What do you mean by “an empty object”? Do you mean you get a texture without a RAM image? If so, it’s because to transfer the texture contents from video card memory to CPU RAM automatically, you need to set the to_ram=True flag in makeTextureBuffer.

Also, you’ve created a new scene graph and camera, but in your code it’s not visible that you have set up any objects to be rendered under your new scene graph. If you wish to instead transfer the contents of the main window into a texture, you should instead use base.win.addRenderTexture.


#3

Yes, indeed, I had a Texture without RAM image. Setting the flag “True” I finally get a proper output but now the texture doesn’t contain the render output, it is just a white image.
The objects are inserted externally by the main script using another class, I post the complete code below to give you a better idea!

from panda3d.core import AmbientLight, DirectionalLight, LightAttrib
from panda3d.core import TextNode, NodePath, Texture, CardMaker, Shader
from panda3d.core import LPoint3, LVector3, BitMask32, Quat
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from direct.task.Task import Task
import sys


class ChronoPandaInterface(ShowBase):
    ChBodyList = []
    ModelList = []
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)
        
        mybuffer =  base.win.makeTextureBuffer("Buffer", 1024, 1024, to_ram=True )
        mytexture = mybuffer.getTexture()
        mybuffer.setSort(-100)
        mycamera = base.makeCamera(mybuffer)
        myscene = NodePath("My Scene")
        mycamera.reparentTo(myscene)

        self.texture = mytexture
        

        self.accept('escape', sys.exit)  # Escape quits
        self.disableMouse()  # Disble mouse camera control
        mycamera.setPosHpr(0, -12, 8, 0, -35, 0)  # Set the camera
        self.setupLights()  # Setup default lighting
    

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
        
        
    """Function called at each step to update rendered bodies positions 
       according to the position af their respective modelled bodies"""    
    def Update_Pos(self):
           for model, body in zip(self.ModelList, self.ChBodyList) :
                  new_pos = body.GetPos()
                  model.setPos(new_pos.x, new_pos.y, new_pos.z)
                  new_ori = body.GetRot()
                  q = Quat(new_ori.e0, new_ori.e1, new_ori.e2, new_ori.e3)
                  model.setQuat(q)

    """Function used to update the visualization
    It shouldn't be called at each simulation step"""                    
    def Advance(self):
           
           self.Update_Pos()
           self.taskMgr.step()
           return self.texture 
           

        
        
class ChPandaBody(object):
    #def __init__(self, CPInterf, chbody , color)
    def __init__(self, CPInterf, chbody):
        self.chbody = chbody
        self.obj = loader.loadModel(self.model)
        self.obj.reparentTo(render)
        #self.obj.setColor(color)
        PosVec = chbody.GetPos()
        self.obj.setPos(PosVec.x,PosVec.y, PosVec.z)
        RotQuat = chbody.GetRot()
        q = Quat(RotQuat.e0,RotQuat.e1, RotQuat.e2, RotQuat.e3)
        self.obj.setQuat(q)
        CPInterf.ChBodyList.append(self.chbody)
        CPInterf.ModelList.append(self.obj)

    
class PandaCube(ChPandaBody):
       model = "models/cube.blend"
       def __init__(self, CPInterf, chbody, s, color=None):
              ChPandaBody.__init__(self, CPInterf, chbody)
       
              self.obj.setScale(s)
              if color:
                     self.obj.setColor(color)

class PandaSphere(ChPandaBody):
       model = "models/sphere.blend"
       def __init__(self, CPInterf, chbody, s, color=None):
              ChPandaBody.__init__(self, CPInterf, chbody)
       
              self.obj.setScale(s)
              if color:
                     self.obj.setColor(color)

class PandaBox(ChPandaBody):
       model = "models/cube.blend"
       def __init__(self, CPInterf, chbody, s, color=None):
              ChPandaBody.__init__(self, CPInterf, chbody)
       
              self.obj.setSx(s[0])
              self.obj.setSy(s[1])
              self.obj.setSz(s[2])
              
              if color:
                     self.obj.setColor(color)
  #TODO: not a proper ellipsoid, just a stretched sphere                   
class PandaEllipsoid(ChPandaBody):
       model = "models/sphere.blend"
       def __init__(self, CPInterf, chbody, s, color=None):
              ChPandaBody.__init__(self, CPInterf, chbody)
       
              self.obj.setSx(s[0])
              self.obj.setSy(s[1])
              self.obj.setSz(s[2])
              
              if color:
                     self.obj.setColor(color)   
         
"""Cylinder visualization. Set s=(r,h)
TODO: not properly set. 
"""              
class PandaCyilinder(ChPandaBody):
       model = "models/cylinder.obj"
       def __init__(self, CPInterf, chbody, s, color=None):
              ChPandaBody.__init__(self, CPInterf, chbody)
       
              self.obj.setSx(s[0])
              self.obj.setSy(s[2])
              self.obj.setSz(s[1])
              
              if color:
                     self.obj.setColor(color)

#4

I forgot to mention that if I render to the windows everything works properly


#5

Looking at your ChPandaBody class, it seems you are reparenting all of your loaded models to render, while it’s probably your mycamera that you want to render your models with, correct?
In that case, try to reparent the models to myscene instead, as this is the root of the scenegraph that you set up to be rendered with mycamera.


#6

Thank you, Epihaius! It worked smoothly! I post the full code below for future users interested in something similar!

from direct.showbase.ShowBase import ShowBase


from panda3d.core import AmbientLight, DirectionalLight, LightAttrib
from panda3d.core import TextNode, NodePath, Texture, CardMaker, Shader
from panda3d.core import LPoint3, LVector3, BitMask32, Quat
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from direct.task.Task import Task
import sys


class ChronoPandaInterface(ShowBase):
    ChBodyList = []
    ModelList = []
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)
        
        mybuffer =  base.win.makeTextureBuffer("Buffer", 1024, 1024, to_ram=True)
        mytexture = mybuffer.getTexture()
        mybuffer.setSort(-100)
        mycamera = base.makeCamera(mybuffer)
        self.myscene = NodePath("My Scene")
        mycamera.reparentTo(self.myscene)

        self.texture = mytexture
        

        self.accept('escape', sys.exit)  # Escape quits
        self.disableMouse()  # Disble mouse camera control
        mycamera.setPosHpr(0, -12, 8, 0, -35, 0)  # Set the camera
        self.setupLights()  # Setup default lighting
    

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
        
        
    """Function called at each step to update rendered bodies positions 
       according to the position af their respective modelled bodies"""    
    def Update_Pos(self):
           for model, body in zip(self.ModelList, self.ChBodyList) :
                  new_pos = body.GetPos()
                  model.setPos(new_pos.x, new_pos.y, new_pos.z)
                  new_ori = body.GetRot()
                  q = Quat(new_ori.e0, new_ori.e1, new_ori.e2, new_ori.e3)
                  model.setQuat(q)

    """Function used to update the visualization
    It shouldn't be called at each simulation step"""                    
    def Advance(self):
           
           self.Update_Pos()
           self.taskMgr.step()
           return self.texture 
           

        
        
class ChPandaBody(object):
    #def __init__(self, CPInterf, chbody , color)
    def __init__(self, CPInterf, chbody):
        self.chbody = chbody
        self.obj = loader.loadModel(self.model)
        self.obj.reparentTo(CPInterf.myscene)
        #self.obj.setColor(color)
        PosVec = chbody.GetPos()
        self.obj.setPos(PosVec.x,PosVec.y, PosVec.z)
        RotQuat = chbody.GetRot()
        q = Quat(RotQuat.e0,RotQuat.e1, RotQuat.e2, RotQuat.e3)
        self.obj.setQuat(q)
        CPInterf.ChBodyList.append(self.chbody)
        CPInterf.ModelList.append(self.obj)

    
class PandaCube(ChPandaBody):
       model = "models/cube.blend"
       def __init__(self, CPInterf, chbody, s, color=None):
              ChPandaBody.__init__(self, CPInterf, chbody)
       
              self.obj.setScale(s)
              if color:
                     self.obj.setColor(color)