天天看点

games101 作业2框架修改重心坐标推导rasterize_triangleinsideTriangle(判断一个点是否在三角形内部)

框架修改

//把rasterizer.cpp第83行的vert.z() = vert.z() * f1 + f2改为vert.z() = -vert.z() * f1 + f2
           

重心坐标推导

games101 作业2框架修改重心坐标推导rasterize_triangleinsideTriangle(判断一个点是否在三角形内部)
games101 作业2框架修改重心坐标推导rasterize_triangleinsideTriangle(判断一个点是否在三角形内部)

rasterize_triangle

void rst::rasterizer::rasterize_triangle(const Triangle& t)
{
    /*
    // TODO : Find out the bounding box of current triangle.
    // iterate through the pixel and find if the current pixel is inside the triangle
    // If so, use the following code to get the interpolated z value.
    //auto[alpha, beta, gamma] = computeBarycentric2D(x, y, t.v);
    //float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
    //float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
    //z_interpolated *= w_reciprocal;
    // TODO : set the current pixel (use the set_pixel function) to the color of the triangle (use getColor function) if it should be painted.
         //TODO:找出当前三角形的边界框。
        //遍历像素并找出当前像素是否在三角形内
        //如果是这样,请使用以下代码获得插值的z值。
        //自动[α,β,γ]=计算中心2d(x,y,t.v);
        //浮点数w_倒数=1.0/(α/v[0].w()+β/v[1].w()+γ/v[2].w());
        //浮点z_插值=alpha*v[0].z()/v[0].w()+beta*v[1].z()/v[1].w()+gamma*v[2].z()/v[2].w();
        //z_插值*=w_倒数;
        //TODO:如果要绘制三角形,请将当前像素(使用set\ pixel函数)设置为三角形的颜色(使用getColor函数)。
     */
    auto v = t.toVector4();
     //创建三角形的2维bounding box。
     //找出最小和最大的的x和y
    float min_x = std::min(v[0][0], std::min(v[1][0], v[2][0]));
    float min_y = std::min(v[0][1], std::min(v[1][1], v[2][1]));
    float max_x = std::max(v[0][0], std::max(v[1][0], v[2][0]));
    float max_y = std::max(v[0][1], std::max(v[1][1], v[2][1]));
    bool MSAA = true;
    if (MSAA)
    {
        //4*4
        std::vector<Eigen::Vector2f> pos =
        {
            {0.25,0.25},
            {0.25,0.75},
            {0.75,0.25},
            {0.75,0.75}
        };
        for (int x = min_x; x < max_x; x++)
        {
            for (int y = min_y; y < max_y; y++)
            {
                int count = 0;
                //最小深度,默认是无穷远
                float mindpth = FLT_MAX;
                for (int i = 0; i < 4; i++)
                {
                    //判断像素点中心是不是在三角形内部
                    if (insideTriangle((float)x + pos[i][0], (float)y + pos[i][1], t.v))
                    {
                        
                        auto tup = computeBarycentric2D((float)x + pos[i][0], (float)y + pos[i][1], t.v);
                        float alpha;
                        float beta;
                        float gamma;
                        std::tie(alpha, beta, gamma) = tup;
                        float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
                        float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
                        z_interpolated *= w_reciprocal;
                        mindpth = std::min(mindpth, z_interpolated);
                        count++;
                    }
                }
                if (count != 0) 
                {
                    if (depth_buf[get_index(x, y)] > mindpth)
                    {
                        Vector3f color = t.getColor() * count / 4.0;
                        Vector3f point(3);
                        point << (float)x, (float)y, mindpth;
                        // 替换深度
                        depth_buf[get_index(x, y)] = mindpth;
                        // 修改颜色
                        set_pixel(point, color);
                    }
                }
            }
        }
    }
    else
    {
        //遍历此 bounding box 内的所有像素(使用其整数索引)。然后,使用像素中 心的屏幕空间坐标来检查中心点是否在三角形内
        for (int x = min_x; x < max_x; x++)
        {
            for (int y = min_y; y < max_y; y++)
            {
                //判断像素点中心是不是在三角形内部
                if (insideTriangle(x + 0.5, y + 0.5, t.v))
                {
                    //最小深度,默认是无穷远
                    float mindpth = FLT_MAX;
                    //如果在三角形内部,算插值,然后更新Z插值
                    //计算插值 alpha, beta, gamma
                    auto tup = computeBarycentric2D(x + 0.5, y + 0.5, t.v);
                    float alpha;
                    float beta;
                    float gamma;
                    std::tie(alpha, beta, gamma) = tup;
                    float w_reciprocal = 1.0 / (alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());
                    float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();
                    z_interpolated *= w_reciprocal;
                    mindpth = std::min(mindpth, z_interpolated);
                    //如果x,y所在点的深度小于z-buffer的深度,
                    if (depth_buf[get_index(x, y)] > mindpth)
                    {
                        //获得颜色
                        Vector3f color = t.getColor();
                        Vector3f point;
                        point << x, y, mindpth;
                        //更新深度
                        depth_buf[get_index(x, y)] = mindpth;
                        //更新所在点的颜色
                        set_pixel(point, color);
                    }
                }
            }
        }
    }
}
           

insideTriangle(判断一个点是否在三角形内部)

games101 作业2框架修改重心坐标推导rasterize_triangleinsideTriangle(判断一个点是否在三角形内部)
//测试点是否在三角形内。你可以修改此函 数的定义,这意味着,你可以按照自己的方式更新返回类型或函数参数
static bool insideTriangle(float x, float y, const Vector3f* _v)
{
// TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]
TODO:实现此函数以检查点(x,y)是否位于由_v[0]、_v[1]、_v[2]表示的三角形内
Eigen::Vector3f p;
  p << x, y,1;
   Vector3f v[3];
    for (int i = 0; i < 3; i++)
        v[i] = {_v[i].x(),_v[i].y(), 1.0};
    //向量
  Eigen::Vector3f ab;
  Eigen::Vector3f bc;
  Eigen::Vector3f ca;
   ab = v[1] - v[0];
   bc = v[2] - v[1];
   ca = v[0]- v[2];
  Eigen::Vector3f ap;
  Eigen::Vector3f bp;
  Eigen::Vector3f cp;
  ap=p- v[0];
  bp=p - v[1];
  cp = p - v[2];
  if((ab.cross(bc)).dot(ab.cross(ap)) > 0 && 
    (bc.cross(ca)).dot(bc.cross(bp)) > 0 && 
    (ca.cross(ab)).dot(ca.cross(cp))>0)
{
return true;
   }
   else
   {
     return false;
    }
}