C ++ графическое программирование - PullRequest
2 голосов
/ 30 ноября 2010

Я новичок в c ++ 3D, так что, может быть, я просто упускаю что-то очевидное, но как мне конвертировать из 3D в 2D и (для заданного местоположения z) из 2D в 3D?

Ответы [ 4 ]

4 голосов
/ 30 ноября 2010

Вы отображаете 3D в 2D с помощью проекции . Вы отображаете 2D в 3D, вставляя соответствующее значение в элемент Z вектора.

0 голосов
/ 01 декабря 2010

Самый простой способ - сделать деление на z. Поэтому ...

screenX = projectionX / projectionZ;
screenY = projectionY / projectionZ;

Это делает перспективную проекцию на основе расстояния. Дело в том, что часто лучше использовать однородные координаты , поскольку это упрощает матричное преобразование (все становится кратным). В равной степени это то, что используют D3D и OpenGL. Понимание того, как использовать неоднородные координаты (т. Е. Координату (x, y, z)) будет очень полезно для таких вещей, как оптимизация шейдеров.

0 голосов
/ 30 ноября 2010

Это вопрос отбрасывания луча с экрана на плоскость, параллельную x-y и расположенную в требуемом месте z. Затем вам нужно выяснить, где на плоскости сталкивается луч.
Вот один пример, учитывая, что screen_x и screen_y находятся в диапазоне [0, 1], где 0 - самая левая или самая верхняя координата, а 1 - самая правая или самая нижняя соответственно:

Vector3 point_of_contact(-1.0f, -1.0f, -1.0f);
Matrix4 view_matrix = camera->getViewMatrix();
Matrix4 proj_matrix = camera->getProjectionMatrix();
Matrix4 inv_view_proj_matrix = (proj_matrix * view_matrix).inverse();
float nx = (2.0f * screen_x) - 1.0f;
float ny = 1.0f - (2.0f * screen_y);
Vector3 near_point(nx, ny, -1.0f);
Vector3 mid_point(nx, ny, 0.0f);
// Get ray origin and ray target on near plane in world space
Vector3 ray_origin, ray_target;
ray_origin = inv_view_proj_matrix * near_point;
ray_target = inv_view_proj_matrix * mid_point;

Vector3 ray_direction = ray_target - ray_origin;
ray_direction.normalise();

// Check for collision with the plane
Vector3 plane_normal(0.0f, 0.0f, 1.0f);
float denominator = plane_normal.dotProduct(ray_direction);
if (fabs(denom) >= std::numeric_limits<float>::epsilon())
{
    float num = plane_normal.dotProduct(ray.getOrigin()) + Vector3(0, 0, z_pos);
    float distance = -(num/denom);
    if (distance > 0)
    {
        point_of_contact = ray_origin + (ray_direction * distance);
    }
}
return point_of_contact

Примечание об отказе от ответственности: это решение было взято из кусочков графической библиотеки Ogre3D.

0 голосов
/ 30 ноября 2010

Одно неудачное решение:

^ y
|
|
|  /z
| /
+/--------->x

Угол - это угол между осями Ox и Oz (

#include <cmath>

typedef struct {
  double x,y,z;
} Point3D;

typedef struct {
  double x,y;
} Point2D 

const double angle = M_PI/4; //can be changed

Point2D* projection(Point3D& point) {
  Point2D* p = new Point2D();
  p->x = point.x + point.z * sin(angle);
  p->y = point.y + point.z * cos(angle);
  return p;
}

Однако в сети есть множество учебных пособий по этому вопросу ...Ты на это гуглил?

...