天天看點

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