Skip to main content

Translate Java 3D coordinates to 2D screen coordinates

2 replies [Last post]
daks7
Offline
Joined: 2010-09-25
Points: 0

Hi All,
I'm working with a Java 3D application called "Walrus" that is used to display directed graphs. The code already has a feature to highlight a node and draw label adjacent in graph given its screen coordinates.

Upon rotating the screen, the node is no more highlighted.

What I have is the node coordinates in 3D. I need to draw label to it.

Code for highlight using 3D coordinates
Point3d p = new Point3d();
m_graph.getNodeCoordinates(node, p);

PointArray array = new PointArray(1, PointArray.COORDINATES);
array.setCoordinate(0, p);

m_parameters.putModelTransform(gc);
gc.setAppearance(m_parameters.getPickAppearance());

1. How can I draw Label with 3D coordinates( Raster graphics throws error Renderer: Error creating immediate mode Canvas3D graphics context )

2. How can I convert 3D coordinates to 2D screen and use existing code to draw label at 2D screen point

Thanks,
Dakshina

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
tmilard
Offline
Joined: 2004-03-25
Points: 0

Answer for question 2 :
plotting on the 2D screen a label at a position where the 3D nodes is projected on the screen:
the main issue I have at the moment is the calculte the X,Y position on the screen.
Here is a fonction I found on an old post :
http://www.mail-archive.com/java3d-interest@java.sun.com/msg19964.html

    public Point2d get3DTo2DPoint(Point3d point3d)
>          {
>
>             Transform3D temp = new Transform3D();
>             this.canvas3D.getVworldToImagePlate(temp);
>             temp.transform(point3d);
>             Point2d point2d =new Point2d();
>             this.canvas3D.getPixelLocationFromImagePlate(point3d,point2d);
>             return point2d;
>          }

Please tell us if this code works.
-------------------------
Explanation
a) temp::Transform3D just 'transform' a pure 3D-java3Dworld coordinates into a 3D-Image-Plamate coordinates.
b) I think the 'Image plate' coodinates is a XYZ coordinates but
- the origin : is located on the lower -left corner on the screen-of-camera (view Frustrum)
- the X axe is from left to right, the Y axe going up, the Z going away from the Screen.

Hope this helps

daks7
Offline
Joined: 2010-09-25
Points: 0

Hi All,
I found the solution.
This is the function to display Text3D at image 2D coordinates
public void drawLabel(GraphicsContext3D gc, double x, double y, int zOffset, String s) {
boolean frontBufferRenderingState = gc.getFrontBufferRendering();
gc.setBufferOverride(true);
gc.setFrontBufferRendering(true);
Point3d eye = getEye();
double labelZ = zOffset * LABEL_Z_OFFSET_SCALE
+ LABEL_Z_SCALE * eye.z + LABEL_Z_OFFSET;

double xOffset = LABEL_X_OFFSET * m_pixelToMeterScale;
double yOffset = LABEL_Y_OFFSET * m_pixelToMeterScale;
Point3d p = new Point3d(x + xOffset, y + yOffset, 0.0);
{
// Project given (x, y) coordinates to the plane z=labelZ.

// Convert from image-plate to eye coordinates.
p.x -= eye.x;
p.y -= eye.y;

double inversePerspectiveScale = 1.0 - labelZ / eye.z;
p.x *= inversePerspectiveScale;
p.y *= inversePerspectiveScale;

// Convert from eye to image-plate coordinates.
p.x += eye.x;
p.y += eye.y;

}

Transform3D scale = new Transform3D();
scale.set(LABEL_SCALE);

Vector3d t = new Vector3d(p.x, p.y, labelZ);
Transform3D translation = new Transform3D();
translation.set(t);
translation.mul(scale);

Transform3D transform = new Transform3D(m_imageToVworld);
transform.mul(translation);

gc.setModelTransform(transform);

//-----------------
int fontSize=(int)(10*m_magnification);

if(fontSize>20)
fontSize=20;
//---------------

// XXX: Courier may not be available on all systems.
Text2D text = new Text2D(s, new Color3f(1.0f, 1.0f, 1.0f),
"Courier", fontSize, Font.BOLD);

gc.draw(text);

gc.flush(true);

// NOTE: Resetting the model transform here is very important.
// For some reason, not doing this causes the immediate
// following frame to render incorrectly (but subsequent
// frames will render correctly). In some ways, this
// makes sense, because most rendering code assumes that
// GraphicsContext3D has been set to some reasonable
// transform.
gc.setModelTransform(m_objectTransform);
gc.setFrontBufferRendering(frontBufferRenderingState);
}

This is the function to take 3D coordinates and convert them to image 2D coordinates and render using above function
private boolean displayOnScreenLabel(int node, String label) {
boolean success = false;
try {
Transform3D transform = m_parameters.getObjectToEyeTransform();
Point3d nodeC = new Point3d();

m_graph.getNodeCoordinates(node, nodeC);
transform.transform(nodeC);

Point3d eye = m_parameters.getEye();

double perspectiveScale = 1.0 / (1.0 - nodeC.z / eye.z);

double centerX = eye.x + nodeC.x * perspectiveScale;
double centerY = eye.y + nodeC.y * perspectiveScale;

GraphicsContext3D gc = m_canvas.getGraphicsContext3D();

m_parameters.drawLabel(gc, centerX, centerY, m_labelZOffsetCounter++, label);

success = true;
} catch (final java.lang.OutOfMemoryError error) {
JOptionPane.showMessageDialog(m_frame, "The 3D Graphics is unable to find enough memory on your system. Kill the application!", "Out Of Memory!", JOptionPane.ERROR_MESSAGE);
} catch (Exception e) {
success = false;
}
return success;
}