使用 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 投影,这将是完全奇怪的矩阵.
我只是想画一个 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 投影,这将是完全奇怪的矩阵.