Parallel Projection Mode and Screen Coordinates

Hello, I am a newly registered forum member, but I have been lurking around for a while now as I learn and use jME in my game. I am relatively new to jME and OpenGL, but not to programming.



I am having trouble with translating world position to screen coordinates in parallel projection mode. I have searched the forums and found several topics on putting text above a model using the getScreenCoordinates(Vector3f worldPosition) method in the DisplaySystem class, but I have noticed a problem. Or, maybe its just I haven't noticed a problem in my code. To better explain I have provided the code below:


import com.jme.app.SimpleGame;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial.LightCombineMode;
import com.jme.scene.shape.Quad;
import com.jme.scene.shape.Sphere;
import com.jme.system.DisplaySystem;

public class ScreenCoordinateTest extends SimpleGame
{
   @Override
   protected void simpleInitGame()
   {
      final DisplaySystem display = DisplaySystem.getDisplaySystem();
      final Renderer renderer = display.getRenderer();
      
      Camera camera = renderer.getCamera();
      
      /*
       * Note I am working in parallel projection mode.
       */
      camera.setParallelProjection(true);
      
      final float aspect = (float)display.getWidth() / (float)display.getHeight();
      camera.setFrustum(-50, 500, -100 * aspect, 100 * aspect, -100, 100);
      
      Vector3f loc = new Vector3f(0.0f, 0.0f, 50.0f);
      Vector3f left = new Vector3f(1.0f, 0.0f, 0.0f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);
      
      camera.setFrame(loc, left, up, dir);            
      camera.update();

      renderer.setCamera(camera);
      renderer.setBackgroundColor(ColorRGBA.black);
      
      Node test = new Node("Test1");
      test.setLocalTranslation(0, 0, 0);
      
      Sphere sphere1 = new Sphere("Sphere1", 10, 10, 2.5f);
      sphere1.setDefaultColor(ColorRGBA.white);
      test.attachChild(sphere1);
      
      Vector3f screen = DisplaySystem.getDisplaySystem().getScreenCoordinates(test.getWorldTranslation());
      
      Quad quad = new Quad("Quad1", 5, 5);
      quad.setLocalTranslation(screen.getX(), screen.getY() + 15, 0);
      quad.setDefaultColor(ColorRGBA.white);
      quad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      quad.updateRenderState();
      test.attachChild(quad);
      
      test.updateRenderState();
      
      Node test2 = new Node("Test2");
      test2.setLocalTranslation(0, 50, 0);
      
      Sphere sphere2 = new Sphere("Sphere2", 10, 10, 2.5f);
      sphere2.setDefaultColor(ColorRGBA.red);
      test2.attachChild(sphere2);
      
      Vector3f screen2 = DisplaySystem.getDisplaySystem().getScreenCoordinates(test2.getWorldTranslation());
      
      Quad quad2 = new Quad("Quad2", 5, 5);
      quad2.setLocalTranslation(screen2.getX(), screen2.getY() + 15, 0);
      quad2.setDefaultColor(ColorRGBA.red);
      quad2.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      quad2.updateRenderState();
      test2.attachChild(quad2);
      
      test2.updateRenderState();
      
      rootNode.attachChild(test);
      rootNode.attachChild(test2);
      rootNode.setLightCombineMode(LightCombineMode.Off);
      rootNode.updateRenderState();
   }   
   
   /**
    * The start of test program.
    *
    * @param args The command line arguments.
    */
   public static void main(String[] args)
   {
      ScreenCoordinateTest app = new ScreenCoordinateTest();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
       app.start();
   }
}



Shouldn't the distance from the red sphere to the red quad be the same as the distance from the white sphere to the white quad? On my system, the distances are not the same. Does anyone else have the same observation? It appears that the screen coordinates are being calculated from a perspective mode, even though I am using parallel projection, and as the sphere is further from the center, the distance between the sphere and the quad increases. From my understanding, the distances should be the same because of the parallel projection, but maybe I misunderstood something? What am I missing?

I am using the jME 2.0 compiled from source, Java SDK 1.6, Eclipse 3.4

Any information or advice would be greatly appreciated.

Thank you,
Volks73

Okay, I was doing some more testing, and I still haven't found a solution to the problem. I tested a similar situation but with perspective mode and slightly different viewing angle and such. Below is some more test code but in perspective mode:


public class ScreenCoordinatesTest extends SimpleGame
{
   @Override
   protected void simpleInitGame()
   {
      final DisplaySystem displaySystem = DisplaySystem.getDisplaySystem();
      final Renderer renderer = displaySystem.getRenderer();
      Camera camera = renderer.getCamera();
      
      final float aspect = (float)display.getWidth() / (float)display.getHeight();
      camera.setFrustumPerspective(10.0f, aspect, 1, -1);
      
      Vector3f loc = new Vector3f(0.0f, 0.0f, 1000.0f);
      Vector3f left = new Vector3f(1.0f, 0.0f, 0.0f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);
      
      camera.setFrame(loc, left, up, dir);            
      camera.update();
      
      renderer.setBackgroundColor(ColorRGBA.black);
      
      CullState cs = renderer.createCullState();
      cs.setCullFace(CullState.Face.Back);
      rootNode.setRenderState(cs);
      
      rootNode.setLightCombineMode(LightCombineMode.Off);
      
      Node test = new Node("Test1");
      test.setLocalTranslation(0, 0, 0);
      rootNode.attachChild(test);
      
      Sphere sphere1 = new Sphere("Sphere1", 10, 10, 2.5f);
      sphere1.setDefaultColor(ColorRGBA.white);
      test.attachChild(sphere1);
      
      Vector3f screen = DisplaySystem.getDisplaySystem().getScreenCoordinates(test.getWorldTranslation());
      
      Quad quad = new Quad("Quad1", 5, 5);
      quad.setLocalTranslation(screen.getX(), screen.getY() + 15, 0);
      quad.setDefaultColor(ColorRGBA.white);
      quad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      quad.updateRenderState();
      test.attachChild(quad);
      
      test.updateRenderState();
      
      Node test2 = new Node("Test2");
      test2.setLocalTranslation(0, 50, 0);
      
      Sphere sphere2 = new Sphere("Sphere2", 10, 10, 2.5f);
      sphere2.setDefaultColor(ColorRGBA.red);
      test2.attachChild(sphere2);
      
      Vector3f screen2 = DisplaySystem.getDisplaySystem().getScreenCoordinates(test2.getWorldTranslation());
      
      Quad quad2 = new Quad("Quad2", 5, 5);
      quad2.setLocalTranslation(screen2.getX(), screen2.getY() + 15, 0);
      quad2.setDefaultColor(ColorRGBA.red);
      quad2.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      quad2.updateRenderState();
      test2.attachChild(quad2);
      
      test2.updateRenderState();
      
      rootNode.attachChild(test2);
      rootNode.updateRenderState();
   }

   public static void main(String[] args)
   {
      ScreenCoordinatesTest app = new ScreenCoordinatesTest();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
       app.start();
   }
}



I still have the red quad further from the red sphere than the white quad from the white sphere. I am trying to get both quads to be the same distance from their respective spheres.

Any ideas?

Thank you,
Volks73

I didn't see them when I looked before but here is your issue:



Node test = new Node("Test1");
test.setLocalTranslation(0, 0, 0);

Sphere sphere1 = new Sphere("Sphere1", 10, 10, 2.5f);
sphere1.setDefaultColor(ColorRGBA.white);
test.attachChild(sphere1);

Vector3f screen = DisplaySystem.getDisplaySystem().getScreenCoordinates(test.getWorldTranslation());

Quad quad = new Quad("Quad1", 5, 5);
quad.setLocalTranslation(screen.getX(), screen.getY() + 15, 0);
quad.setDefaultColor(ColorRGBA.white);
quad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
quad.updateRenderState();
test.attachChild(quad);
rootNode.attachChild(quad);

test.updateRenderState();

Node test2 = new Node("Test2");
test2.setLocalTranslation(0, 50, 0);

Sphere sphere2 = new Sphere("Sphere2", 10, 10, 2.5f);
sphere2.setDefaultColor(ColorRGBA.red);
test2.attachChild(sphere2);

Vector3f screen2 = DisplaySystem.getDisplaySystem().getScreenCoordinates(test2.getWorldTranslation());

Quad quad2 = new Quad("Quad2", 5, 5);
quad2.setLocalTranslation(screen2.getX(), screen2.getY() + 15, 0);
quad2.setDefaultColor(ColorRGBA.red);
quad2.setRenderQueueMode(Renderer.QUEUE_ORTHO);
quad2.updateRenderState();
test2.attachChild(quad2);
rootNode.attachChild(quad2);

test2.updateRenderState();

In this case it looks like a problem with your test...

(you are in effect adding the screen translation twice)
1 Like

Thank you, I made the changes, both in my test and my code and it works. I see what I did wrong.



-Volks73