使用 GLM 和 GTK 制作简单的 3D 绘图

Using GLM with GTK to make simple 3D drawing

我只是想画一个 3D 笛卡尔轴,看看我是否可以让 3D 工作。我正在使用 GTK 和 Cairo 来绘图。这是我的代码...

glm::vec3 camera_pos(0, 0, -10);
glm::vec3 camera_target(0, 0, 0);
glm::vec3 up(0, 1, 0);

gboolean draw_callback(GtkWidget* widget, cairo_t* cr, gpointer data)
{
    guint width, height;

    width = gtk_widget_get_allocated_width(widget);
    height = gtk_widget_get_allocated_height(widget);

    glm::mat4 model = glm::translate(glm::vec3(width / 2.0f, height / 2.0f, 0.0f)) *
            glm::scale(glm::vec3(100.0f, 100.0f, 100.0f));
    glm::mat4 camera = glm::lookAt(camera_pos, camera_target, up);
    glm::mat4 perspective = glm::perspective(45.0f, (float)width / (float)height, 0.1f, 100.0f);

    glm::mat4 transform = perspective * camera * model;

    glm::vec4 xaxis = transform * glm::vec4(1, 0, 0, 1);
    glm::vec4 yaxis = transform * glm::vec4(0, 1, 0, 1);
    glm::vec4 zaxis = transform * glm::vec4(0, 0, 1, 1);
    glm::vec4 orig = transform * glm::vec4(0, 0, 0, 1);

    cout << orig.x << " " << orig.y << endl;

    cairo_set_source_rgb(cr, 1.0, 0, 0);
    cairo_move_to(cr, orig.x, -orig.y);
    cairo_line_to(cr, xaxis.x, -xaxis.y);
    cairo_stroke(cr);

    cairo_set_source_rgb(cr, 0, 1.0, 0);
    cairo_move_to(cr, orig.x, -orig.y);
    cairo_line_to(cr, yaxis.x, -yaxis.y);
    cairo_stroke(cr);

    cairo_set_source_rgb(cr, 0, 0, 1.0);
    cairo_move_to(cr, orig.x, -orig.y);
    cairo_line_to(cr, zaxis.x, -zaxis.y);
    cairo_stroke(cr);

    return FALSE;
}

有人可以在这里检查数学吗,因为我得到了很多负坐标。当我 运行 this.

时,我的屏幕上没有任何显示

编辑:

我刚刚像这样修改了我的相机矢量。

gboolean draw_callback(GtkWidget* widget, cairo_t* cr, gpointer data)
{
    guint width, height;

    width = gtk_widget_get_allocated_width(widget);
    height = gtk_widget_get_allocated_height(widget);

    glm::vec3 camera_pos(0, 0, 1000);
    glm::vec3 camera_target(width / 2.0f, height / 2.0f, 0);
    glm::vec3 up(0, 1, 0);

    glm::mat4 model = glm::translate(glm::vec3(width / 2.0f, height / 2.0f, 0.0f));// *
            //glm::scale(glm::vec3(100.0f, 100.0f, 100.0f));
    glm::mat4 camera = glm::lookAt(camera_pos, camera_target, up);
    glm::mat4 perspective = glm::perspective(45.0f, (float)width / (float)height, 0.1f, 100.0f);

    glm::mat4 transform = perspective * camera * model;

    glm::vec4 xaxis = transform * glm::vec4(100, 0, 0, 1);
    glm::vec4 yaxis = transform * glm::vec4(0, 100, 0, 1);
    glm::vec4 zaxis = transform * glm::vec4(0, 0, 100, 1);
    glm::vec4 orig = transform * glm::vec4(0, 0, 0, 1);

    cout << xaxis.x << " " << xaxis.y << endl;

    cairo_set_source_rgb(cr, 1.0, 0, 0);
    cairo_move_to(cr, orig.x, -orig.y);
    cairo_line_to(cr, xaxis.x, -xaxis.y);
    cairo_stroke(cr);

    cairo_set_source_rgb(cr, 0, 1.0, 0);
    cairo_move_to(cr, orig.x, -orig.y);
    cairo_line_to(cr, yaxis.x, -yaxis.y);
    cairo_stroke(cr);

    cairo_set_source_rgb(cr, 0, 0, 1.0);
    cairo_move_to(cr, orig.x, -orig.y);
    cairo_line_to(cr, zaxis.x, -zaxis.y);
    cairo_stroke(cr);

    return FALSE;
}

现在我可以从屏幕的一角看到一条蓝线,但它仍然是错误的。

你用的是透视投影,但是你没有进行透视划分,这会完全搞砸你的结果。 glm::perspective 将创建一个矩阵,该矩阵将沿负 z 轴具有给定角度和纵横比的视锥体映射到剪辑 space 中的 [-w,w]^3 "cube"。透视图除以 w 坐标后,视锥在标准化设备坐标中将为 [-1,1]^3。通常在这个阶段,坐标会进一步转换为 window space,实际像素开始发挥作用。

在你的情况下,你似乎试图在变换链的开头将 window 分辨率合并到 model 变换中,如果你稍后应用标准 GL 投影,这将是完全奇怪的矩阵.