javajava-3d

Java3D transformation from 3D to current view 2D coordinate


I'm trying to add a 2D overlay for a 3D scene in Java3D, part of this overlay is to draw a line from a 2D object to a corresponding point in the 3D scene...

Searched transformation from 3D to 2D and read those threads:

from code inside walrus: https://github.com/CAIDA/walrus/blob/master/H3ViewParameters.java

copied a method to a class extending Canvas3D:

public Transform3D getObjectToEyeTransform() {
    Point3d m_eye = new Point3d();
    getCenterEyeInImagePlate(m_eye);
    Transform3D m_imageToEye = new Transform3D();
    m_imageToEye.set(new Vector3d(-m_eye.x, -m_eye.y, 0.0));
    Transform3D m_vworldToImage = new Transform3D();
    getVworldToImagePlate(m_vworldToImage);

    Transform3D transform = new Transform3D(m_imageToEye);
    transform.mul(m_vworldToImage);
    //transform.mul(m_objectTransform);
    return transform;
}

and then in my overlay in method postRender i try to do the following:

Transform3D viewTrans3d = getObjectToEyeTransform();
Vector3d point = new Vector3d(1,1,1);
viewTrans3d.invert();
viewTrans3d.transform(point);
this.getGraphics2D().drawLine(0, 0, (int)point.x, (int)point.y);

Getting very weird line, which do change in a quite logical pattern (when i rotate and tilt the view) but far from what i expect...

Questions:

  1. commented the m_objectTransform matrix multiplication because i don't understand its purpose, any idea?
  2. Why do i need to invert the transform matrix? without the invert the results are even weirder...
  3. Is there a simpler way to do this??? sounds like something solved eons ago...

Solution

  • This can be done by using getVworldToImagePlate and then getPixelLocationFromImagePlate in the Canvas3D class. For example:

    public Point2d getPosition2d(Point3d point) {
        Transform3D transform = new Transform3D();
        getVworldToImagePlate(transform);
        transform.mul(objectTransform);
    
        Point3d newPoint = new Point3d(point);
        transform.transform(newPoint);
    
        Point2d point2d = new Point2d();
        getPixelLocationFromImagePlate(newPoint, point2d);
        return point2d;
    }
    

    The objectTransform variable should be the transform of any TransformGroup in the scene that is applied to the 3d objects that are displayed. If you don't have any TransformGroup, then you can leave this out. Also, the transform shouldn't be inverted, just use it as it is.