Starting out looking for tips for showing binocular images from numpy arrays (plus an error)


#1

I am a noob, have just worked through the hello world tutorial. Before I even get into my problem, I should say my goal with panda3d – I’m showing visual stimuli in research, and I want a looping movie in the left side, then a gray stripe in the middle, and a similar looping movie on the right hand side. So far I’ve been creating animations using vispy/numpy/OpenGL with standard translation/scaling/rotations in homogeneous coordinates, but panda3d looks very promising and scalable so I want to try it.

The strategy I’m thinking might work is to build numpy arrays I want to show (they are different on each side), and display them on the left and right as textures (maybe using StereoDisplayRegion?), and do transforms on the textures while keeping the camera centered (0,0,100) xyz and (0,-90,0) hpr. So I’d use lerp intervals and sequences to move them relative to the fixed camera.

Does this seem like a good strategy for me to be aiming toward with Panda3d? Like I said, I’ve just done the hello world example so I may be missing obvious strategies.

At any rate, since that’s my strategy, I’ve been trying to figure out how to show a numpy array as a texture/image. For instance:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import Texture 
import numpy as np 

#Create random numpy array
texture = np.ones((512,512), dtype = np.uint8) #make textures a power of 2
texture[200:205,:] = 0 #black line

class MyApp(ShowBase):
     def __init__(self):
        ShowBase.__init__(self)
        self.imageTexture = Texture("image")
        self.imageTexture.setup2dTexture()  #could give more params
        self.imageTexture.setRamImage(texture)     
        
app = MyApp()
app.run()

I get the following error:

AssertionError: compression != CM_off || image.size() == do_get_expected_ram_image_size(cdata) at line 5498 of c:\buildslave\sdk-windows-amd64\build\panda\src\gobj\texture.cxx

I am current working through the rest of the manual, so I realize I am probably making some noob errors. But before I go down the rabbit hole here I’m wondering if people think my strategy seems sound, and if so what I should be doing differently with my texture rendering.

Also, are there any examples online that would particularly good for me to study, given my goals?


#2

You need to set up the texture with the right parameters so that the size matches. In your case, assuming you are going for a grayscale texture, that would be:

self.imageTexture.setup2dTexture(512, 512, Texture.T_unsigned_byte, Texture.F_luminance)

#3

@rdb thanks that stopped the error.

Unfortunately I’m just seeing a gray background, not the white with a black line. I also change it to a random texture (just to make sure it wasn’t something about that array) and don’t see that either:

texture = np.array(np.random.rand(512,512) * 255, dtype=np.uint8)

This is true even when I set the camera to xyz=0,0,10, hpr = 0,-90,0.


#4

You haven’t applied the texture to anything yet. Look into CardMaker or OnscreenImage for creating a fullscreen quad that you can apply the texture to and show it on screen.


#5

Thanks: Yes I figured that might be the issue was playign with that and haven’t gotten it quite working yet. To the above I added:

from panda3d.core import CardMaker

And then inside the class:

    cm = CardMaker('card')
    self.card = self.render.attachNewNode(cm.generate())
    self.card.setTexture(self.imageTexture)

And still getting the same issue. Here is the full code I have now, in case anyone wants to critique/run it:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import Texture, CardMaker 
import numpy as np 

#Create random numpy array
texture = 255*np.ones((512,512), dtype = np.uint8) #make textures a power of 2
texture[200:205,:] = 0 #black line

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.imageTexture = Texture("image")
        self.imageTexture.setup2dTexture(512, 512, Texture.T_unsigned_byte, Texture.F_luminance) #could give more params
        self.imageTexture.setRamImage(texture)  
       
        cm = CardMaker('card')
        self.card = self.render.attachNewNode(cm.generate())
        self.card.setTexture(self.imageTexture)

app = MyApp()
app.run()

#6

What is the problem?

from direct.showbase.ShowBase import ShowBase
from panda3d.core import Texture, CardMaker 
import numpy as np 

#Create random numpy array
texture = 255*np.ones((512,512), dtype = np.uint8) #make textures a power of 2
texture[200:205,:] = 0 #black line

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.imageTexture = Texture("image")
        self.imageTexture.setup2dTexture(512, 512, Texture.T_unsigned_byte, Texture.F_luminance) #could give more params
        self.imageTexture.setRamImage(texture)
        
        self.cam.setPos(0, -5, 0)
       
        cm = CardMaker('card')
        self.card = self.render.attachNewNode(cm.generate())
        self.card.setTexture(self.imageTexture)

app = MyApp()
app.run()

#7

Hey you are right it’s working. I guess I just needed to place my camera better! This is great thanks!