Translate Java 3D coordinates to 2D screen coordinates

泪湿孤枕 提交于 2020-01-03 17:07:13

问题


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


回答1:


Here's what i used to convert my 3D coordinates into perspective 2D, x2 and y2 being the 2dimensional coordinates, xyz being the 3D coordinates.

use these formulas:

x2 = cos(30)*x - cos(30)*y

y2 = sin(30)*x + sin(30)*y + z

I picked the angle 30 as it is easy for perspective purposes, also used in Isometric grids for drawing 3D on 2D papers. As the z axe will be the vertical one, x and y are the ones at 60 degrees from it right and left. Isometric Grid Picture.

I'm still working on rotation, but without altering the axes, just coordinate rotation in 3D. Enjoy.




回答2:


I have an algorithm/method for converting [x,y,z] into [x,y] with the depth parameter:

The x value is : (int) (x - (z / depth * x))

The y value is : (int) (y - (z / depth * y))

Essentially, the depth is the focal point. The vanishing point will be at [0,0,depth].




回答3:


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;
}


来源:https://stackoverflow.com/questions/5883979/translate-java-3d-coordinates-to-2d-screen-coordinates

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!