flipping a scene

flipping a scene

Post by Simon Triebenbache » Sun, 18 May 2003 01:58:09



Hello everybody,

I want to flip the image that Open Inventor/OpenGL created (right ->
left). i have found in other postings that this can easily be done in
OpenGL by supplying the glFrustrum function with flipped coordinates but
until now i haven't found a simple possibility to do it in Open
Inventor. I tried to scale the whole scenegraph by (-1,1,1) but that
messed up the lighting also. Then i tried to remove all normals and have
Inventor calculate them bei specifying ShapeHints... didn't work (I'm
using the SoVRML* classes which do handle normals differently).
The most unsatisfying possibility I can think of, would be to have two
scenegraphs with mirrored geometry. But that means that I would have to
change all vertices manually. But I don't know how to do that.
Please Help!

Bye

Simon

PS: Here's a posting which describes the same problem:

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=3...

 
 
 

flipping a scene

Post by Morten Erikse » Sun, 18 May 2003 03:33:19



> I want to flip the image that Open Inventor/OpenGL created (right ->
> left). i have found in other postings that this can easily be done
> in OpenGL by supplying the glFrustrum function with flipped
> coordinates but until now i haven't found a simple possibility to do
> it in Open Inventor.

I'm not sure this would work without actually trying it, but I see no
reason why not: insert SoCallback nodes after any camera nodes you
place in the scene. Then, in the the actual callback function, read
out the current OpenGL frustum coordinates (with one of the glGet*()
functions, I guess), flip the coordinates horizontally and pass them
back into the OpenGL state machine with a glFrustum() call.

Or instead of inserting SoCallback nodes everywhere, I suppose you
could attach an abort callback to the SoGLRenderAction: if you detect
that the last traversed node was an SoCamera, read frustum and flip,
as described above.

Both these techniques are a bit "hack-ish", of course, but you
couldn't really expect a general purpose scene graph API to contain
functionality for doing the special trick you are trying to do.

Morten
--
<URL:http://www.coin3d.org>

 
 
 

flipping a scene

Post by Simon Triebenbach » Mon, 19 May 2003 23:59:49




> > I want to flip the image that Open Inventor/OpenGL created (right ->
> > left). i have found in other postings that this can easily be done
> > in OpenGL by supplying the glFrustrum function with flipped
> > coordinates but until now i haven't found a simple possibility to do
> > it in Open Inventor.

> I'm not sure this would work without actually trying it, but I see no
> reason why not: insert SoCallback nodes after any camera nodes you
> place in the scene. Then, in the the actual callback function, read
> out the current OpenGL frustum coordinates (with one of the glGet*()
> functions, I guess), flip the coordinates horizontally and pass them
> back into the OpenGL state machine with a glFrustum() call.

I got the desired behaviour with the following code:

void mycallback(void * userdata, SoAction * action)
{
  int flip = *(int*)userdata;
  if (action->isOfType(SoGLRenderAction::getClassTypeId())) {

    // Get the OpenGL projection matrix
    GLfloat *params = new GLfloat[16];
    glGetFloatv(GL_PROJECTION_MATRIX, params);

    // Print the projection matrix
    for(int i=0; i<4; i++) {
      printf("%.3f\t%.3f\t%.3f\t%.3f\n", params[0+i], params[4+i],
params[8+i], params[12+i]);
    }
    printf("\n");

    // Do a left <-> right flip if necessary
    if(flip)
      params[0] = -params[0];

    // Store the current matrix mode
    GLint matrixmode;
    glGetIntegerv (GL_MATRIX_MODE, &matrixmode);

    // Go to projection mode and set the new matrix
    glMatrixMode (GL_PROJECTION);
    glLoadMatrixf(params);

    // Restore previous matrixmode
    glMatrixMode (matrixmode);

  }

Quote:}

// the main function
main (int, char **argv)
{

  ...

  SoSeparator *Root = new SoSeparator;

  SoCamera *cam = new SoCamera();
  Root->addChild(cam);
  SoCallback *cb = new SoCallback();
  int flip = 0;
  cb->setCallback(mycallback, &flip);
  Root->addChild(cb);

  ...

Quote:}

A problem I have noticed is, that picking doesn't work right after
flipping. But for my purpose this doesn't matter.

Thanks for your advice!

Simon

 
 
 

flipping a scene

Post by Morten Erikse » Tue, 20 May 2003 15:43:21



> I got the desired behaviour with the following code: [...]

It just hit me: the "correct", non-hackish way to do this is to use
the state elements, SoProjectionMatrixElement and
SoViewingMatrixElement, and possibly a few others.

Check out the SoCamera::GLRender() function to see how the camera
nodes sets up the frustum. You could probably more or less copy that
code, and just insert a little snippet to flip the direction when
wanted.

Quote:> A problem I have noticed is, that picking doesn't work right after
> flipping. [...]

Setting up the frustum by using state elements would probably solve
that problem.

Morten
--
<URL:http://www.coin3d.org>