makeCubeMap Reflections Not Laterally Inverted

Using the code in the manual I’ve set up a Dynamic Cube Map and rendered it onto a cube exported from Blender via Chicken and loaded into my world which is based on Roaming Ralph; it almost works but to get the reflection to render on the face nearest my character (not the opposite face) I had to add the line:
rig.setHpr(180,0,0)
to spin the camera rig around. When I do that though the image is not laterally inverted – ie if my character walks from right to left in front of the cube, the refection walks from left to right. Rendering onto the teapot.egg sample without spinning the rig works fine. How do I change my cube to fix it?

Try applying the transform on the vertices after rotating it using:

rig.flattenLight()

You only need to do this once – after you did this, the transform will be applied on the vertices.

Thanks. Added rig.flattenLight() after rig.setHpr(180,0,0) but it made no differnce to the lateral inversion. From the manual it looks to be something to do with reducing the number of meshes?

Sounds like a problem with the way your UVW’s were applied to your cube model. Did you apply them via blender, or did you use Panda’s dynamic texture coordinate generation option to create them on-the-fly?

David

I applied them via Blender.
Brian

That’s probably not the right way to apply texture coordinates intended for a reflection map. The reflection map coordinates have to be generated carefully, to ensure they are consistent with the global orientation of your object in the scene, relative to the orientation of the camera, as both are placed at runtime.

Try using the dynamic texture coordinate generation, as illustrated in the dynamic reflection map example.

David

Added:
self.models[0].setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldCubeMap)
Where self.models[0] is the cube, and tried lots of values for TexGenAttrib; none so far show the reflection on the correct surface unless I also include
rig.setHpr(180,0,0)
in which case I get reflection on the correct surface but incorrect lateral inversion as before; any thoughts?
Brian

If you paste in exactly the code sample given in the manual, does it work properly?

If so, try to narrow down what you’re doing different that makes the difference. Change out one piece at a time, for instance, replace the teapot with your box model, and so on, until it stops working again.

David

The code in the manual uses the teapot model, which already works correctly in my world even without using setTexGen etc. Here’s the cube .egg file. Can you spot anything wrong or better still, make it mirror correctly?
Brian
{ Z-up }

{ “Egg laid by Chicken for Blender v1.0” }

Material {
diffr {0.800000011921}
diffg {0.800000011921}
diffb {0.800000011921}
specr {0.25}
specg {0.25}
specb {0.25}
shininess {12.5}
}
Cube {
{
{
-0.999994 0.003328 0.000000 0.000000
-0.003328 -0.999994 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 0.000000 1.000000
}
}
Cube {
0 {
-1.003322 -0.996667 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
1 {
-0.996667 1.003322 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
2 {
1.003322 0.996667 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
3 {
0.996667 -1.003322 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
4 {
-1.003322 -0.996666 1.000000
{ 1.0 1.0 1.0 1.0 }
}
5 {
0.996667 -1.003322 1.000000
{ 1.0 1.0 1.0 1.0 }
}
6 {
1.003322 0.996667 1.000000
{ 1.0 1.0 1.0 1.0 }
}
7 {
-0.996666 1.003323 1.000000
{ 1.0 1.0 1.0 1.0 }
}
8 {
-1.003322 -0.996667 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
9 {
-1.003322 -0.996666 1.000000
{ 1.0 1.0 1.0 1.0 }
}
10 {
-0.996666 1.003323 1.000000
{ 1.0 1.0 1.0 1.0 }
}
11 {
-0.996667 1.003322 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
12 {
-0.996667 1.003322 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
13 {
-0.996666 1.003323 1.000000
{ 1.0 1.0 1.0 1.0 }
}
14 {
1.003322 0.996667 1.000000
{ 1.0 1.0 1.0 1.0 }
}
15 {
1.003322 0.996667 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
16 {
1.003322 0.996667 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
17 {
1.003322 0.996667 1.000000
{ 1.0 1.0 1.0 1.0 }
}
18 {
0.996667 -1.003322 1.000000
{ 1.0 1.0 1.0 1.0 }
}
19 {
0.996667 -1.003322 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
20 {
-1.003322 -0.996666 1.000000
{ 1.0 1.0 1.0 1.0 }
}
21 {
-1.003322 -0.996667 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
22 {
0.996667 -1.003322 -1.000000
{ 1.0 1.0 1.0 1.0 }
}
23 {
0.996667 -1.003322 1.000000
{ 1.0 1.0 1.0 1.0 }
}
}
Cube1 {
{
{ Material }
{ 0.000000 0.000000 -1.000000 }
{ 0 1 2 3 { Cube } }
}
{
{ Material }
{ 0.000000 0.000000 1.000000 }
{ 4 5 6 7 { Cube } }
}
{
{ Material }
{ -0.999995 0.003328 0.000000 }
{ 8 9 10 11 { Cube } }
}
{
{ Material }
{ 0.003328 0.999994 -0.000000 }
{ 12 13 14 15 { Cube } }
}
{
{ Material }
{ 0.999994 -0.003328 -0.000000 }
{ 16 17 18 19 { Cube } }
}
{
{ Material }
{ -0.003328 -0.999995 0.000000 }
{ 20 21 22 23 { Cube } }
}
}
}

Huh? You can’t apply a reflection map to the teapot, or to almost any model, without doing the setTexGen() bit. So I don’t know what you mean here.

In any case, when I cut and paste your cube model and drop it into the sample code, it works fine. I see mirror images reflected properly in each face of the cube.

David

I started again with a really simple example based on the ‘Teapot on TV’ sample and it works! My code is below. Don’t understand what’s different in my main game, but I expect I’ll work it out eventually. Thanks for your help.
Brian

from pandac.PandaModules import Texture,TextureStage,TexGenAttrib,DirectionalLight,AmbientLight
import direct.directbase.DirectStart
from pandac.PandaModules import Filename,Texture
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import NodePath,TextNode
from pandac.PandaModules import Point3,Vec3,Vec4,BitMask32,VBase3
from direct.task.Task import Task
from direct.actor.Actor import Actor
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
import sys, os, random

Function to put instructions on the screen.

def addInstructions(pos, msg):
return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
pos=(-1.3, pos), align=TextNode.ALeft, scale = .05)
base.setBackgroundColor(Vec4(0.0,0.0,0.0,1.0))
class World(DirectObject):
def init(self):
self.inst0 = addInstructions(0.95,“v: View scene”)
self.inst1 = addInstructions(0.90,“m: Toggle teapot/cube”)
self.inst2 = addInstructions(0.85,“r: Rotate man”)
self.inst3 = addInstructions(0.80,“ESC: Quit”)
mainWindow=base.win
altBuffer=mainWindow.makeTextureBuffer(“hello”, 512, 512)
self.altCam=base.makeCamera(altBuffer)
self.altCam.reparentTo(render)
self.altCam.setPos(0,-15,0)
self.man=loader.loadModel(‘mechman_idle’)
self.man.reparentTo(render)
self.man.setPos(2,-2,-3)
self.choice = “teapot”
self.model=loader.loadModel(self.choice)
dlight = DirectionalLight(‘dlight’)
alight = AmbientLight(‘alight’)
dlnp = render.attachNewNode(dlight.upcastToPandaNode())
alnp = render.attachNewNode(alight.upcastToPandaNode())
dlight.setColor(Vec4(0.8, 0.8, 0.5, 1))
alight.setColor(Vec4(0.2, 0.2, 0.2, 1))
dlnp.setHpr(0, -20, 0)
render.setLight(dlnp)
render.setLight(alnp)
base.bufferViewer.setPosition(“llcorner”)
base.bufferViewer.setCardSize(1.25, 0)
self.accept(“m”, self.flip)
self.accept(“v”, base.bufferViewer.toggleEnable)
self.accept(“r”, self.spin)
self.accept(“escape”, sys.exit, [0])
def flip(self):
if self.choice==“teapot”:
self.choice=“cube”
self.pos=VBase3(2,20,1) #left/right,in/out,up/down
self.scale=5
else:
self.choice=“teapot”
self.pos=VBase3(-2,-1,-1)
self.scale=1
self.model.hide()
self.model=loader.loadModel(self.choice)
self.model.reparentTo(render)
self.model.setPos(self.pos)
self.model.setScale(self.scale)
self.model.show()
cubeCameraMask = BitMask32(1)
rig = NodePath(‘rig’)
buffer = base.win.makeCubeMap(‘env’, 256, rig,cubeCameraMask)
rig.reparentTo(self.model)
self.model.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldCubeMap)
self.model.setTexture(buffer.getTexture(),1)
def spin(self):
self.man.setH(self.man.getH() + 90)
w = World()
run()

It seems the statements I was missing are:
alnp = render.attachNewNode(ambientLight.upcastToPandaNode())
render.setLight(alnp)
without them my cube reflects what’s on the opposite side of it, with them it reflects correctly.
Can anyone explain why?
Brian

No, really? That doesn’t make sense at all. The presence or absence of an ambient light should have no effect on the reflection map. Are you sure?

In any case, note that the “upcastToPandaNode()” part of the call hasn’t been needed for many years, not since Panda 1.0.

David

Sure? No, I’m even more confused! The statement
render.setLight(alnp)
alone makes the reflection work in my main game, but removing the statement in the test program I quoted above makes no difference – in fact the refection works correctly even when all the alight and dlight code is commented out! :astonished:(
By the way what determines the size of the reflected image? In my main game it’s about 30% too big compared to the figure it’s reflecting; in the test program it looks about right…
Brian

The size of the reflected image, as well as its orientation, is determined entirely by the (u, v, w) texture coordinates, which are generated by the line:

model.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldCubeMap)

David

Thanks. Maybe I’m missing something, but does that mean I can actually change the size of the reflected image?
Brian

I suppose you could model geometry that would be shaped like a magnifying lens, but other than that, no: the size of the reflected image is computed based on the physical properties of the geometry.

David

Ah! That explains why the refection looks smaller in the teapot than it does in the cube! Thanks. Pity it generates a reflected image that’s over-sized in a flat surface though.
Brian

Even more oddly, as you move the main camera away from the reflecting surface and the real object that’s being reflected, the real object get smaller (correctly) but the reflection of it gets bigger! Does anyone know if that behaviour can be changed?
Brian

That sounds like your mirror camera is not properly positioned within your reflecting model.

David