Home › Forums › GAMES在线课程(现代计算机图形学入门)讨论区 › 请教老师一个问题,关于重心坐标 › Reply To: 请教老师一个问题,关于重心坐标
Participant
用面积计算是合适的
比如我这里使用面积计算重心坐标,可以得到预期的效果
static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector4f* v){
Eigen::Vector2f p(x, y);
Eigen::Vector2f tri_node_coords[3];
for (int i = 0; i < 3; ++i) {
tri_node_coords[i] = v[i].head<2>();
}
Eigen::Vector2f edge_1, edge_2;
float s_sub_tri[3];
for (int i = 0; i < 3; ++i) {
edge_1 = tri_node_coords[(i + 1) % 3] - p;
edge_2 = tri_node_coords[(i + 2) % 3] - p;
s_sub_tri[i] = edge_1.x() * edge_2.y() - edge_2.x() * edge_1.y();
}
float s_sum = 0;
for (int i = 0; i < 3; ++i) {
s_sum += s_sub_tri[i];
}
return { s_sub_tri[0] / s_sum, s_sub_tri[1] / s_sum, s_sub_tri[2] / s_sum };
}
如果担心计算出来的重心坐标为负会不会不正确,那么可以试着在 rasterize_triangle() 光栅化三角形的时候就剔除掉那些重心坐标为负的点
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos)
{
int x_screen_min = width - 1;
int x_screen_max = 0;
int y_screen_min = height - 1;
int y_screen_max = 0;
for (int i = 0; i < 3; i++) {
x_screen_min = std::min(x_screen_min, (int)t.v[i][0]);
y_screen_min = std::min(y_screen_min, (int)t.v[i][1]);
x_screen_max = std::max(x_screen_max, (int)t.v[i][0]);
y_screen_max = std::max(y_screen_max, (int)t.v[i][1]);
}
// temp var
Eigen::Vector3f interpolated_color;
Eigen::Vector3f interpolated_normal;
Eigen::Vector2f interpolated_texcoords;
Eigen::Vector3f interpolated_shadingcoords;
for (int x = x_screen_min; x <= x_screen_max; ++x) {
for (int y = y_screen_min; y <= y_screen_max; ++y) {
if (insideTriangle(x + 0.5f, y + 0.5f, t.v)) {
auto [alpha, beta, gamma] = computeBarycentric2D(x + 0.5f, y + 0.5f, t.v);
if (alpha < 0.0f || alpha > 1.0f) continue;
if (beta < 0.0f || beta > 1.0f) continue;
if (gamma < 0.0f || gamma > 1.0f) continue;
可见,在模型的每一个三角面的边上显示出缝隙
也就是说,重心坐标为负的点也可能位于三角形的边上
如果去掉了这些点,就相当于在三角形的边上没有颜色,那么渲染出来的就会在模型的每一个三角面的边上显示出缝隙
所以只要你的 insideTriangle() 写对了,就不需要考虑 computeBarycentric2D() 算出来的重心坐标为负还是为正