使用GLM和GTK进行简单的3D绘图

时间:2015-08-27 12:08:16

标签: c++ opengl 3d gtk glm-math

我正在尝试绘制3D笛卡尔轴以查看是否可以让3D工作。我正在和开罗一起使用GTK进行绘图。这是我的代码......

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

有人可以在这里查看数学,因为我得到了很多负坐标。我跑步时屏幕上没有任何内容。

编辑:

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

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

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

1 个答案:

答案 0 :(得分:1)

你正在使用透视投影,但你没有进行划分,这会完全搞砸你的结果。 glm::perspective将创建一个矩阵,该矩阵将沿着负z轴的给定角度和apsect比率的视锥体映射到剪辑空间中的[-w,w] ^ 3“立方体”。在透视除以w坐标之后,在标准化设备坐标中,视锥体将为[-1,1] ^ 3。通常在这个阶段,坐标会进一步转换为窗口空间,其中实际像素开始发挥作用。

在您的情况下,您似乎尝试将窗口分辨率合并到变换链开始处的model变换中,如果您稍后应用标准GL投影矩阵,这非常奇怪。