2012-12-17 107 views
2

我想写几个函数绘制(填充)平顶和平底三角形。对于大部分他们工作,但有时在相邻的三角形之间有共同的一面发生裂纹。我使用内插技术,我将三角形逐行扫描,计算每一步的新左右极限。这在很大程度上是在代码中所解释的,但这里是一般的想法(对于平底):从三角形光栅化问题

1)找到DY(高度)

2)求出DY/DX(斜率)顶点到每个底部点

3)移动到起始行(地板(顶点)),并且发现初始x开始和x结束坐标

4)移动到下一行,计算新的开始和终点限制...

我应该注意到只有在两侧连接的三角形之间才能看到裂纹,而不是顶部/底部连接。我已经这么久了,我不知道该怎么尝试了。我认为逻辑是稳定的,也许任何裂缝都是由浮点错误引起的。我真的很感激一些反馈。

typedef unsigned int uint32; 

void Line(uint32 y, uint32 x_left, uint32 x_right); //Draws a horizontal line 

struct vector2 
{ 
    float x,y; 
}; 

//-------------------------------------------------------------------------------- 
//  Draws a flat bottom triangle from top to bottom 
//-------------------------------------------------------------------------------- 
void Draw_Bottom_Tri_SOLID(Vector2 p0, Vector2 p1, Vector2 p2) 
{ 
    //Point order: 
    //Bottom left: p0 
    //Bottom right: p1 
    //Top point:  p2 

    //calculate dy 
    float dy = p2.y - p0.y; 

    //dx/dy for the left and right edges 
    float dxdy_left = (p0.x - p2.x)/dy; 
    float dxdy_right = (p1.x - p2.x)/dy; 

    //Since we start the raster process at floor(p2.y) 
    //we need to shift the initial x start and x end 
    //postions along by this factor: 
    float y_bump = p2.y - floor(p2.y); 

    //Initial start and end x values 
    float xs = p2.x + dxdy_left*y_bump; //x left (start) 
    float xe = p2.x + dxdy_right*y_bump; //x right (end) 

    uint32 yb = uint32(p0.y) + 1;   //y bottom, +1 for top left fill convention 
    uint32 yt = uint32(p2.y);    //y top, use casting instead of std::floor 

    //Draw lines 
    for (uint32 i = yt; i >= yb; i--) 
    { 
     //Set left and right limits, use casting instead of std::floor 
     uint32 left = uint32(xs) + 1;  //+1 for top left fill convention 
     uint32 right = uint32(xe); 

     //Draw line, can also be std::fill or simply a for loop. 
     Line(i, left, right); 

     //Increment limits 
     xs += dxdy_left; 
     xe += dxdy_right; 
    } 

} //End: Draw_Bottom_Tri_SOLID() 


//-------------------------------------------------------------------------------- 
//  Draws a flat top triangle from bottom to top 
//-------------------------------------------------------------------------------- 
void Draw_Top_Tri_SOLID(Vector2 p0, Vector2 p1, Vector2 p2) 
{ 
    //Point order: 
    //Top left:  p0 
    //Top right:  p1 
    //Bottom point: p2 

    //calculate dy (height) 
    float dy = p0.y - p2.y; 

    //dx/dy for the left and right edges 
    float dxdy_left = (p0.x - p2.x)/dy; 
    float dxdy_right = (p1.x - p2.x)/dy; 

    //Find shifting factor 
    float y_bump = ceil(p2.y) - p2.y; 

    //Initial start and end x values 
    float xs = p2.x + dxdy_left*y_bump; //x left (start) 
    float xe = p2.x + dxdy_right*y_bump; //x right (end) 

    uint32 yb = uint32(p2.y) + 1;   //y bottom, +1 for top left fill convention 
    uint32 yt = uint32(p0.y) ;    //y top 

    //Draw lines 
    for (uint32 i = yb; i <= yt; i++) 
    { 
     //Set left and right limits 
     uint32 left = uint32(xs) + 1;  //+1 for top left fill convention 
     uint32 right = uint32(xe); 

     //Draw line, can be std::fill or simply a for loop. 
     Line(i, left, right); 

     //Increment limits 
     xs += dxdy_left; 
     xe += dxdy_right; 
    } 


} //End: Draw_Top_Tri_SOLID() 

回答

1

浮动错误似乎很可能。您需要确保最终获得两个相邻边的相同值。当你以这种方式积累时,用浮点值修正这可能有点棘手。根据您的需求,您有几个选项:

  • 改为使用固定点。这也可能会更快。
  • 如果透支不是问题,您可以简单地为您的浮动值添加足够大的epsilon。