如何使用等轴投影将3D坐标转换为2D坐标?

3

编程语言:C

我目前正在实现一个通过等角投影表示的3D线框模型。

我目前对该项目的理解是:

  1. 解析包含线框模型的x、y、z坐标的文本地图
  2. 使用等角投影将3D坐标转换为2D坐标
  3. 使用Bresenham Line算法和我选择的图形库中的一些函数绘制线条。

我已经完成了第1步,但是在过去的几天里一直卡在第2步。

我知道等角投影是将2D平面投影到一个角度,使其看起来像是3D,即使我们只在绘制线条时使用x、y。如果我描述不正确,请纠正我。

文本地图示例:

0 0 0

0 5 0

0 0 0

我选择的数据结构(实现为结构体数组)

typedef struct point
{
    float       x;
    float       y;
    float       z;
    bool        is_last;
    int     color; // Implemented after mandatory part
} t_point;

我基本上只是读取文本地图的行、列和值,并将它们分别存储在x、y、z值中。

现在我需要对它们进行转换,我尝试了以下公式:

    const double angle = 30 * M_PI / 180.0;


void    isometric(t_dot *dot, double angle)
{
    dot->x = (dot->x - dot->y) * cos(angle);
    dot->y = (dot->x + dot->y) * sin(angle) - dot->z;
}

static void iso(int x, int y, int z)
{
    int previous_x;
    int previous_y;

    previous_x = x;
    previous_y = y;
    x = (previous_x - previous_y) * cos(0.523599);
    y = -z + (previous_x + previous_y) * sin(0.523599);
}

t_point *calc_isometric(t_point *pts, int max_pts)
{
    float   x;
    float   y;
    float   z;
    const double angle = 30 * M_PI / 180.0;
    int num_pts;

    num_pts = 0;
    while (num_pts < max_pts)
    {
        x = pts[num_pts].x;
        y = pts[num_pts].y;
        z = pts[num_pts].z;
        printf("x: %f y: %f z: %f\n", x, y, z);
        pts[num_pts].x = (x - y) * cos(angle);
        pts[num_pts].y = (x + y) * sin(angle) - z;
        printf("x_iso %f\ty_iso %f\n\n", pts[num_pts].x, pts[num_pts].y);
        num_pts++;
    }
    return (pts);
}

它输出了各种对我来说毫无意义的东西。我可以继续尝试从这里实现线性算法,并希望一切顺利,但我想要理解我在这里实际上正在做什么。 除此之外,通过我的研究,我了解到需要以特定方式设置相机才能创建投影。

总的来说,我很迷茫,我的问题归结为以下两点:

  1. 请帮助我理解等轴投影的概念。
  2. 如何将三维坐标(x,y,z)转换为使用等轴投影的坐标。
1个回答

2
我这样看:

isometric

// constants:
float deg = M_PI/180.0;
float ax = 30*deg;
float ay =150*deg;
vec2 X = vec2(cos(ax),-sin(ax)); // x axis
vec2 Y = vec2(cos(ay),-sin(ay)); // y axis
vec2 Z = vec2(    0.0,-    1.0); // z axis
vec2 O = vec2(0,0);              // position of point (0,0,0) on screen
// conversion:
vec3 p=vec3(?,?,?); // input point
vec2 q=O+(p.x*X)+(p.y*Y)+(p.z*Y); // output point

逐坐标版本:

float Xx =  cos(ax);
float Xy = -sin(ax);
float Yx =  cos(ay);
float Yy = -sin(ay);
float Zx =      0.0;
float Zy = -    1.0;
float Ox =        0;
float Oy =        0;
// conversion:
float px=?,py=?,pz=?; // input point
float qx=Ox+(px*Xx)+(py*Yx)+(pz*Yx); // output point
float qy=Oy+(px*Xy)+(py*Yy)+(pz*Yy); // output point

假设X轴向右,Y轴向下...通常将O设置为屏幕中心,而不是(0,0),除非您添加等角世界的平移功能。

如果您想在“3D” XY平面内添加任意旋转,请参见:

因此,您只需计算椭圆上的X,Y向量(注意它们将不再是单位向量!)。所以如果我理解正确的话就是:

float ax=?,ay=ax+90*deg;
float Xx =  cos(ax)    ;
float Xy = -sin(ax)*0.5;
float Yx =  cos(ay)    ;
float Yy = -sin(ay)*0.5;

其中ax是旋转角度...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接