Inverted clip planes when using a DirectScrolledFrame

I have a problem with using a DirectScrolledFrame: with the setup I’m using, that involves a negative scaling in Y, the horizontal clip-plane normals point to the wrong direction, effectively excluding everything inside the window.

Let me explain how this happens:
I’m lately doing a lot of 2D rendering with Panda3D and was a bit unhappy with the adressing scheme of aspect2D.
With the -1.33/-1 to 1.33/1 space of a 4:3 screen, it was hard for me to precisely and intuitively position objects on screen, especially with each frame creating its own -1/-1 to 1/1 space.
Therefore I resorted to creating my own coordinate space, using a virtual resolution of 1024x768 pixels.
Here’s what I do:
(a bit simplified, the real code handles window resizes as well…)

class TopLeft4by3(NodePath):
    def __init__(self, layouter):
        NodePath.__init__(self,"TopLeft4by3")
        self.reparentTo(aspect2d)
        self.setScale(2.0/768.0,1,-2.0/768.0)
        self.setPos(-4.0/3.0,0,1.0)

So as you can see, I basically move the origin to the top left and scale in such a way that I get a virtual resolution of 1024x768. The notable point is that it involves a negative scaling in Y.

Now, when generating assets with egg-texture-cards, I specifiy the parameters -g 0,1,1,0 -p 1,1
The idea here is that the artist draws the textures for a resolution of 1024x768 and by specifying -p 1,1 the geometry is scaled accordingly, and -g 0,1,1,0 makes sure that the resulting texture card also has the origin at the top left
corner and extends downwards to the right to end at the bottom right corner. So all in all I have a convenient and for me intuitive way of working with 2d graphics.

Sorry for taking so long, but now I finally can get to the point:
Because of the negative scaling I apply in Y, the DirectScrolledFrame creates the clip planes wrongly (for me):
In the following code, the clip planes get created:

void PGVirtualFrame::
set_clip_frame(const LVecBase4f &frame) {
  if (!_has_clip_frame || _clip_frame != frame) {
    _has_clip_frame = true;
    _clip_frame = frame;

    const LVector3f r = LVector3f::right();
    const LVector3f u = LVector3f::up();

    PT(PlaneNode) left_clip =
      new PlaneNode("left_clip", Planef(r, r * _clip_frame[0]));
    PT(PlaneNode) right_clip =
      new PlaneNode("right_clip", Planef(-r, r * _clip_frame[1]));

    PT(PlaneNode) bottom_clip =
      new PlaneNode("bottom_clip", Planef(u, u * _clip_frame[2]));
    PT(PlaneNode) top_clip =
      new PlaneNode("top_clip", Planef(-u, u * _clip_frame[3]));

    _clip_plane_node->remove_all_children();
    _clip_plane_node->add_child(left_clip);
    _clip_plane_node->add_child(right_clip);
    _clip_plane_node->add_child(bottom_clip);
    _clip_plane_node->add_child(top_clip);

    CPT(ClipPlaneAttrib) plane_attrib = DCAST(ClipPlaneAttrib, ClipPlaneAttrib::make());
    plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(left_clip)));
    plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(right_clip)));
    plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(bottom_clip)));
    plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(top_clip)));

    _canvas_node->set_attrib(plane_attrib);
    clip_frame_changed();
  }
}

and because the unscaled (that is in my case the un-inverted) LVector3f::up() is being used, the planes point into the wrong direction.

Now for my question: is there an easy way to work around this? Or would this involve a change to the panda3d source code?
I’d be ready to make the change but I thought I’d rather first ask…
If changes to the code are needed, suggestions about the most elegant way would be highly appreciated.
Another side effect of this whole issue is that the horizontal scrollbar is also mis-placed (ending up on the outside instead of the inside of the control), but I deem this a minor issue.

Cheers,

Erik

Interestingly, when I try to reproduce the problem, it seems to work fine. As well it should: the DirectScrolledFrame creates planes that would be appropriate if +Y (actually, +Z) were up, but in fact that is the case in the frame’s own coordinate space. It’s only the global coordinate space that is inverted. So the clip planes work properly.

Unless you are also inverting the frame itself somehow?

David

Hmm, you’re right.

In my test, I inverted the frame as well, but without inverting it it works.
I guess thats goood enough for me to start with…

Thanks for answering so quickly!

Erik