Преобразование 3D-координат Java в 2D-координаты экрана

Я работаю с 3D-приложением Java под названием «Walrus», которое используется для отображения ориентированных графиков. В коде уже есть функция выделения узла и рисования метки рядом на графике с учетом его экранных координат.

После поворота экрана узел больше не выделяется.

У меня есть координаты узлов в 3D. Мне нужно нарисовать к нему ярлык.

Код для выделения с использованием 3D-координат

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. Как нарисовать этикетку с 3D-координатами (растровая графика выдает ошибку Renderer: Ошибка при создании немедленного режима графического контекста Canvas3D)

  2. Как преобразовать 3D-координаты в 2D-экран и использовать существующий код для рисования метки в точке 2D-экрана

Спасибо,

Дакшина


person Dakshina Ilangovan    schedule 04.05.2011    source источник
comment
Возможно дубликат: stackoverflow.com/questions/724219/, поскольку, как только вы разберетесь с этой частью, нарисовать этикетку очень легко.   -  person jefflunt    schedule 04.05.2011


Ответы (3)


У меня есть алгоритм / метод преобразования [x,y,z] в [x,y] с параметром depth:

Значение x: (int) (x - (z / depth * x))

Значение y: (int) (y - (z / depth * y))

По сути, глубина - это фокус. Точка схода будет на [0,0,depth].

person hyper-neutrino    schedule 24.08.2015

Вот что я использовал для преобразования моих трехмерных координат в перспективные 2D, где x2 и y2 были двухмерными координатами, а xyz - трехмерными координатами.

используйте эти формулы:

х2 = соз (30) * х - соз (30) * у

у2 = грех (30) * х + грех (30) * у + z

Я выбрал угол 30, поскольку он удобен для перспективных целей, также используется в изометрических сетках для рисования 3D на бумаге 2D. Так как ось z будет вертикальной, x и y - это те, которые находятся на 60 градусах от нее вправо и влево. Изометрическая сетка.

Я все еще работаю над вращением, но без изменения осей, просто координаты вращения в 3D. Наслаждаться.

person ThaBomb    schedule 07.05.2013

Я нашел решение. Это функция для отображения Text3D в 2D-координатах изображения.

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

Это функция для получения 3D-координат и преобразования их в 2D-координаты изображения и рендеринга с использованием вышеуказанной функции.

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;
}
person Dakshina Ilangovan    schedule 18.05.2011