Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

11273 Posts in 1452 Topics- by 675 Members - Latest Member: flytosea

09. September 2010, 05:37:36 PM
Xith3D CommunityGeneral CategorySupport (Moderator: Marvin Fröhlich)Projection to screen
Pages: [1]
Print
Author Topic: Projection to screen  (Read 699 times)
Gunslinger
Enjoying the stay
*
Offline Offline

Posts: 44


View Profile
« on: 11. March 2009, 09:06:39 AM »

Hi!

I want to project a 3D point to the screen. I want to mark the position of a certain Node on the hud (even when the node itself is not visible). This is so you can select an enemy as the current target and have it marked even when it is on the other side of a hill or buildning.

I found an old thread about this and copied the code from it. But I can't get it to work. The point is a little bit wrong. I'm not (yet) good enough at the matrix operations of openGL to understand what is happening.

The method below is not exactly the one described on for instance this page. But I tried that one as well, didn't get it to work.
http://pyopengl.sourceforge.net/documentation/manual/gluProject.3G.xml

Code:
import org.openmali.vecmath2.*;
import org.openmali.FastMath;
import org.xith3d.loop.InputAdapterRenderLoop;
import org.xith3d.loop.RenderLoop;
import org.xith3d.base.Xith3DEnvironment;
import org.xith3d.scenegraph.BranchGroup;
import org.xith3d.scenegraph.TransformGroup;
import org.xith3d.scenegraph.Transform3D;
import org.xith3d.scenegraph.StaticTransform;
import org.xith3d.scenegraph.primitives.Cube;
import org.xith3d.render.RenderPass;
import org.xith3d.render.Canvas3DFactory;
import org.xith3d.render.Canvas3D;
import org.xith3d.render.util.WindowClosingListener;
import org.xith3d.ui.hud.HUD;
import org.xith3d.ui.hud.widgets.LineWidget;
import org.jagatoo.input.events.KeyPressedEvent;
import org.jagatoo.input.devices.components.Key;
import org.jagatoo.input.InputSystem;
import org.jagatoo.input.InputSystemException;

public class Test extends InputAdapterRenderLoop implements WindowClosingListener {
    private Xith3DEnvironment env;
    private BranchGroup root;
    private RenderPass scenePass;
    private Canvas3D canvas;
    private Cube cube;
    private TransformGroup cubeTG;
    private LineWidget line;

    public static void main(String[] args) {
        Test test = new Test();
        test.begin(RenderLoop.RunMode.RUN_IN_SAME_THREAD);
    }

    public Test() {
        super(30);

        env = new Xith3DEnvironment(this);
        env.getView().setFrontClipDistance(0.2f);
        env.getView().setBackClipDistance(1500f);

        root = new BranchGroup();

        scenePass = env.addPerspectiveBranch(root);

        canvas = Canvas3DFactory.createWindowed(800, 600, "Project");
        env.addCanvas(canvas);
        canvas.addWindowClosingListener(this);
        try {
            InputSystem.getInstance().registerNewKeyboardAndMouse(canvas.getPeer());
        } catch (InputSystemException e) {
            e.printStackTrace();
        }

        cube = new Cube(1);
        StaticTransform.translate(cube, 0, 3, 0);
        cubeTG = new TransformGroup();
        cubeTG.addChild(cube);
        root.addChild(cubeTG);

        canvas.getView().lookAt(new Tuple3f(10, 0, 0), Point3f.ZERO, Vector3f.POSITIVE_Y_AXIS);

        HUD hud = new HUD(800, 600, 800);
        env.addHUD(hud);

        line = new LineWidget(new Vector2f(0, 5), 5f, Colorf.RED);
        hud.addWidget(line);
        line.setZIndex(1);
    }

    @Override
    /**
       Rotates the cube around zero and tries to mark it's position (or rather, the center of it's worldbounds)
     with a lineWidget.
     */
    public void update(long gameTime, long frameTime, TimingMode timingMode) {
        super.update(gameTime, frameTime, timingMode);

        Transform3D t3d = cubeTG.getTransform();
        t3d.rotZ(timingMode.getSecondsAsFloat(gameTime));
        cubeTG.setTransform(t3d);

        Point3f centerPoint = Point3f.fromPool();
        cube.getWorldBounds().getCenter(centerPoint);
        Point2f point = worldToScreen(centerPoint);
        line.setLocation(point.getX(), point.getY());
        Point3f.toPool(centerPoint);
    }

    public Point2f worldToScreen (Point3f p) {
        // get the model-view and the projection matrix
Matrix4f mP = canvas.getView().calculatePerspective(800, 600).getMatrix4f();
Matrix4f mM = canvas.getView().getModelViewTransform(true).getMatrix4f();

// convert the point into a vector of length 4
Vector4f v = new Vector4f(p.getX(), p.getY(), p.getZ(), 1);

// compute the distance between the eye and the view plane
float vpd = 1.0f / FastMath.tan(canvas.getView().getFieldOfView());

// v' = P x M x v
v.mul(mM, v);
v.mul(mP, v);

// scale the resulting vector so that it lies in the view plane
float x = v.getX() * vpd / v.getZ();
float y = v.getY() * vpd / v.getZ();

        // convert normalized view plane coordinates into screen coordinates
float xs = (float) 800 * (x + 1f) / 2f;
float ys = (float) 600 / 2f * (1f - y);
return new Point2f(xs, ys);
}


    public void onWindowCloseRequested(Canvas3D canvas) {
        this.end();
    }

    public void onKeyPressed(KeyPressedEvent e, Key key) {
        switch (key.getKeyID()) {
            case ESCAPE:
                this.end();
                break;
        }
    }


}


Edit:
This is the old thread:
http://xith.org/forum/index.php/topic,464.15.html

Edit 2:
Sorry, just noticed I posted this in General. Should be in support of course. So I deleted the first and posted it here.
Logged
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4153


May the 4th, be with you...


View Profile WWW
« Reply #1 on: 11. March 2009, 08:52:20 PM »

I see two potential problems in your code. You may need to call updateBounds() after you rotated the cube's TG and you shouldn't override the RenderLoop's update() method, but the prepareNextFrame() method. The update method has already rendered the frame when you fix the projected point. So you're one frame late.

Marvin
Logged
Gunslinger
Enjoying the stay
*
Offline Offline

Posts: 44


View Profile
« Reply #2 on: 12. March 2009, 08:03:00 AM »

Thanks (I am always learning something new posting here)... but this is not it. The dot is not lagged behind, it's far away. Calling update bounds didn't change anything visible.

I tried calling the glu.glProject(...) I found in JOGL (only to test it), but the results I got from that were not right either (in fact, they were very wrong). I guess I am doing something wrong.
Logged
shatterblast
Enjoying the stay
*
Offline Offline

Posts: 45


View Profile
« Reply #3 on: 12. March 2009, 06:17:29 PM »

I'm still learning so my explanation might seem a little shaky.  A separate object could store copies of the X and Y coordinates of important nodes, especially the tanks and the object representing the player's perspective.  If the X and Y point of a "tank" node meets the "less than or equal to" value required for rendering the tank in relation to the "player's camera" node, then a true / false statement could permit or deny updateBounds().  I assume it produces the green box outlines around the tanks any how. 

Using X and Y coordinates alone would not take in to account objects behind terrain.  It could allow for determining whether to use a 2D place-holder in the HUD or updateBounds() to represent the tank's direction.  Keeping X and Y values in some other object could help simplify a method for selecting targets.  The Z coordinate for a node would still remain necessary for estimating where to put a "beyond range" place-holder on the HUD.
« Last Edit: 12. March 2009, 06:23:04 PM by shatterblast » Logged
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4153


May the 4th, be with you...


View Profile WWW
« Reply #4 on: 12. March 2009, 08:52:48 PM »

I will see, if I can add a utility method for things like that.

10000th post in this board. yeah Smiley

Marvin
Logged
shatterblast
Enjoying the stay
*
Offline Offline

Posts: 45


View Profile
« Reply #5 on: 13. March 2009, 01:43:40 AM »

Congrats?!   Shocked
Logged
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4153


May the 4th, be with you...


View Profile WWW
« Reply #6 on: 13. March 2009, 03:15:02 AM »

Please update from SVN and use Canvas3D.worldToScreen(). I am not sure, if this is the right place for this method though.

Marvin
Logged
Gunslinger
Enjoying the stay
*
Offline Offline

Posts: 44


View Profile
« Reply #7 on: 14. March 2009, 11:13:20 AM »

Thanks! Works perfectly!
Logged
gbrinon
Just dropped in

Offline Offline

Posts: 10


View Profile
« Reply #8 on: 25. July 2010, 08:24:12 PM »

Hi,

I've got a problem with this method (worldToScreen).
When I face the object it works perfectly.
When the object is just behind the camera, the method gives me coordinates on the screen, it's really weird. It's just like i had a mirror in front of me.
Any idea ?
« Last Edit: 26. July 2010, 07:30:51 AM by gbrinon » Logged

Guillaume
Tries to migrate his HEMERA project from JIRR to XITH3D
gbrinon
Just dropped in

Offline Offline

Posts: 10


View Profile
« Reply #9 on: 05. August 2010, 01:44:43 PM »

UP

Someone have an idea ? Maybe precisions are missing ?
Logged

Guillaume
Tries to migrate his HEMERA project from JIRR to XITH3D
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic