retrieving angle from a Transform ?

Hi,

I’m quite new to this wonderfull world of Java3d, and, of course, I’ve got lots of problems…

I’m trying to display a part of a huge background image depending on the direction the viewer is watching.
To do this, I get his rotational TransformGroup, and try to guess the angles between the direction it is watching and the right and up axis.

Alas, this doesn’t seem to work well.
I guess I’m not alone in this case, does anyone knows how to do it ?

For info, here is my source code. I apply the transform to the right and up axis and then retrieve the angle between them.

I don’t know what’s wrong here… I get incorrect values for angleUp and angleRight when I move too much my point of view.

Gérard

        viewDirection.getTransform(trans);

        double xPos=0;
        double yPos=0;
            
        test.x=Constants.right.x;
        test.y=Constants.right.y;
        test.z=Constants.right.z;
        trans.transform(test);
        test.y=0.0;
        
        double angleRight = Constants.right.angle(test);
        if (test.z<0.0)
           angleRight=2*Math.PI-angleRight;
        
        test.x=Constants.up.x;
        test.y=Constants.up.y;
        test.z=Constants.up.z;
        trans.transform(test);
        test.x=0.0;
        
        double angleUp = Constants.up.angle(test);
        if (test.z>0.0)
           angleUp=2*Math.PI-angleUp;

Is this easier than mapping the image to the inside of a sphere and using that as background geometry?

BranchGroup bgGeometry = new BranchGroup();
Appearance App = new Appearance();
try {
   Texture tex = new TextureLoader(new java.net.URL(Path_To_Your_Image), this).getTexture();
   App.setTexture(tex);
}
catch (Exception e)
{
   e.printStackTrace();
}
Sphere outerWorld = new Sphere( 1.0f, Primitive.GENERATE_TEXTURE_COORDS | Primitive.GENERATE_NORMALS_INWARD, App);
bgGeometry.addChild(outerWorld); 

Background bg = new Background();
bg.setApplicationBounds(bounds);
bg.setGeometry(bgGeometry);
objRoot.addChild(bg);

Well, it’s not easier, but it’s much more beautifull.

I tried the technique you describe first, but I had to discard it because

  • Either the background image is too big to be mapped as a texture (OutOfMemoryError)
  • Or the texture is too low and you see the sphere triangles…

If you look at the Background Demo sun provides, you see the result is terrible.

Using a 2D image provides a much more convincing intergalactic space…

It’s much slower too…

Gérard

I just wanted to check that you knew about that functionality. The reason the sun background example is bad is that it is not a very good image- if you look at the sky picture in a normal image editory you will notice that it looks fairly sucky.

You should be able to clear the triangle thing by changing the fold angle, surely?

It still seems a bit as though you are making things very difficult for yourself.

what type is the variable test?

I guess it is the above method you can’t get right, true?

In that case why not show us the source code of that method to try and figure out how you are calculating the angles?

Regards
Nikolai

Here is the complete source code of the method drawing into the background.

Breakfast:
I’m sorry, I’m new to Java3d (but not Java), how do you change the fold angle ? I’ve played a bit with the Background and Sphere class and hasn’t been able to get a correct thing… Maybe I missed something here.
My image is 2300x1575… I can take a smaller one, but not so much and using Background I get memory exception (with a 512Mo RAM, ATI Radeon 8500 32Mo DDR video card) when I load a 640x480 image, It’s definitively too small.

Ifadolai:

Constants.up and Constants.right are Vector3d meaning up (0.0,1.0,0.0) and right (1.0,0.0,0.0).
So the angle function is the one from Vector3d.

My idea is to apply the transform to up and right and then gets the angle between the transformed Vector3d and it’s source.
This way I should get the angles with X and Y axis…

I guess the ideal would be a Background with a compressed texture (because it’s fast), and a good fold angle parameter, so that it would feel like space.

Here is the complete source code. It’s a Canvas3D derived class.

viewDirection is the rotational TransformGroup of the viewer,
vImage is the VolatileImage I’m trying to display.

Thank you all for your help and ideas.

Gérard


    public void preRender ()
    {
       // super.preRender ();
        int drawWidth = 0;
        int drawHeight = 0;
        int screenWidth = getWidth();
        int screenHeight = getHeight();
        int posX=0,posY=0;
        
        if (viewDirection!=null)
        {
            viewDirection.getTransform(trans);
            double xPos=0;
            double yPos=0;
                
            test.x=Constants.right.x;
            test.y=Constants.right.y;
            test.z=Constants.right.z;
            trans.transform(test);
            test.y=0.0;
            
            double angleRight = Constants.right.angle(test);
            if (test.z<0.0)
               angleRight=2*Math.PI-angleRight;
            
            test.x=Constants.up.x;
            test.y=Constants.up.y;
            test.z=Constants.up.z;
            trans.transform(test);
            test.x=0.0;
            
            double angleUp = Constants.up.angle(test);
            if (test.z>0.0)
               angleUp=2*Math.PI-angleUp;

            yPos = ((double)imageHeight)*angleUp/(2*Math.PI);
            xPos = ((double)imageWidth)*angleRight/(2*Math.PI);
            posX =(int)xPos;
            posY =(int)yPos;
        }
        
        J3DGraphics2D graph = getGraphics2D ();
        checkVolatile (vImage, image);
        
        drawWidth = Math.min(screenWidth, imageWidth-posX);
        drawHeight = Math.min(screenHeight, imageHeight-posY);
        
        graph.drawImage (vImage,0,0,drawWidth, drawHeight, posX, posY, drawWidth+posX, drawHeight+posY,null);
        if (drawWidth<screenWidth)
        {
            graph.drawImage (vImage,drawWidth, 0, screenWidth, drawHeight, 0, posY, screenWidth-drawWidth, drawHeight+posY,null);
        }
        if (drawHeight<screenHeight)
        {
            graph.drawImage (vImage,0, drawHeight, drawWidth, screenHeight, posX, 0, drawWidth+posX, screenHeight-drawHeight,null);
        }
        graph.flush (false);
    }


Oh, I forgot test is a Vector3d object used for calculation…

Gérard

It is much easier to get the rotation directly off the matrix.


viewDirection.getTransform(trans);
Quat4d q = new Quat4d();
trans.get(q);

The first three components of q will be a vector pointing in view direction. The fourth component will be the angle rotated about that vector.

The get the angles from that is quite easy.

Regards
Nikolai

I’ll try that.

Thank you !

Gérard

I’m sorry to bother you once again, but …
I tried your idea and displayed the value of q.x,q.y,q.z and q.w.

At the beginning of my test, I set the viewDir to (0,0,-1), => watching to the front of the screen.

With your method, I retreive x=0,y=0,z=0 and w=1. That is a null vector (how can it show a direction when it is null) ? and a rotation to 1.

If I move to the right (using Sun’s KeyNavigatorBehavior) then y lowers to -1 and w goes down to 0.
To my mind it should be x growing to 1, y shouldn’t move and z should come up from -1 to 0.

I don’t know where I’m wrong, and I don’t know what is the meaning of the Quad4d, but I don’t get the expected result…

Gérard

I am just wondering:

As for (0,0,0,1): it does not represent any rotation, in order to do that it must be a unit quaternion.

Your viewDirection could be invalid, how do you set its rotation? Are you sure there is not introduced any shear or scaling, maybe caused by floating-point imprecision?

Regards
Nikolai

Oupps you were right.
I used a AxisAngle4d with a null vector to do it.
It was a code I got from I don’t know where in the net, and it doesn’t seem to fit in my case.

Now I’m using transform.set (new Quat4d (0,0,-1,0)); to set the inital view direction, anf I have (it seems !) correct values when I make a transform.get (Quat4d)…

I’m fine now, I can go on.

Thanks a lot !
Gérard

[quote]I get memory exception
[/quote]
You can always set the memeory size in the jvm

ie do java -Xms128m -Xmx512m
where -Xms is the min heap size and -Xmx is the max heap size.