我正在创建一个高度贴图绘画工具,它使用样条线来绘制高度贴图,其值为0到1.样条曲线由几个点组成,每个点都有不同的厚度(大小/宽度),并进行插值。该工具在高度图上绘制路径的投影,其厚度由用户指定,乘以每个点的大小和用户指定的羽毛。到目前为止,我已经设法实现了所有内容,我的实现就是这样:
取两点(i和i + 1)(http://i.imgur.com/PToj9ws.jpg)
找到垂直线(points [i + 1] .position-points [i] .position)(http://i.imgur.com/9imeDNU.jpg)
使用羽毛填充由垂直线(http://i.imgur.com/QFfcR89.jpg)的起点和终点定义的矩形。
为了填充这些矩形,我使用Bresenham线算法的变体绘制了多条线:
public void drawLine(Point fromPoint, Point toPoint, float fromValue, float toValue, ref float[,] grid)
{
int x0 = fromPoint.x, y0 = fromPoint.y, x1 = toPoint.x, y1 = toPoint.y;
int dx = Mathf.Abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = -Mathf.Abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = dx + dy, e2;
int x = x0, y = y0;
Vector2 target = new Vector2(x1 - x0, y1 - y0);
while(true)
{
Vector2 current = new Vector2(x - x0, y - y0);
float addValue = Mathf.Lerp(fromValue, toValue, current.magnitude / target.magnitude);
plot(x, y, addValue, 1f, ref grid);
if (sample) grid[x, y] = supersample(x, y, ref grid);
if (x == x1 && y == y1) break;
e2 = 2 * err;
if (e2 > dy)
{
err += dy;
x += sx;
} else if (e2 < dx)
{
err += dx;
y += sy;
}
}
}
到目前为止一切顺利!然而,当样条曲线上的一个点具有与其他点不同的尺寸时,问题就出现了。由于此算法不绘制抗锯齿线,因此绘制的形状开始看起来很锯齿。这是因为我为较大点的垂直线的每个像素绘制一条线,并将它们的端点映射到较小点的垂直线。所以基本上线条开始在更狭窄的点附近相互重叠。 我试图绘制图形来可视化问题:
所以我的最终结果如下:
你可以看到羽状部分是如何锯齿状的。
我尝试使用Xiaolin Wu的线算法绘制线条,但这会导致像素之间出现间隙,填充变得不一致。 到目前为止,只应用高斯模糊使事情看起来更好,但它不能完全解决问题而且它很重,所以我也放弃了这个选项。
我真的需要在不使用任何库的情况下实现这一点,因此非常欢迎任何有关如何处理此问题的建议。谢谢!
答案 0 :(得分:1)
听起来,如果有多行正在绘制特定点,则需要为每一行添加“less”。绘制到特定点的线越多,每条线的“更少”应该影响它。
像......(未编译的例子)
int[,] gridDrawCount = new int[grid.GetLength(0),grid.GetLength(1)];
...
//inside the loop
gridDrawCount[x,y]++;
plot(x, y, addValue/gridDrawCount[x,y], 1f, ref grid); //I added the divide by part
你可能想要,而不是像上面所示在循环中进行除法,在循环之后遍历你的网格,然后每个值除以gridDrawCount值(注意div为零) - 应该给出一个稍微不同,可能更一致的效果,但显然会更慢。
答案 1 :(得分:0)
我想出了解决问题的方法。它不是最优的,但它现在对我有用。
在我的问题中,我解释说该算法为点的垂直线的每个像素绘制一条直线,指向下一个点垂直线的映射出的像素(基于百分比)。这导致了透支,所以Glurth建议我保留一系列我已经吸引的点。这种方法实际上引起了更多的晃动,因为线条并不总是向正确的像素绘制正确的值(因为映射 - 它是一个浮点百分比,必须舍入才能从下一条垂直线获得像素)。
所以我所做的是将每个像素从当前绘制线投影到连接点的中心线上,并测量线像素和投影像素之间的距离。基于此我计算羽毛。
当然,由于样条曲线路径被投影到像素网格上,因此会出现锯齿现象,而我(现在)的解决方案是在绘制的像素上使用半径为1f的Gausian模糊来平滑结果。
整个事情并不是太慢,它给出了一个相当不错的结果,现在已经足够了。由于每两个点的垂直线的末端形成一个多边形,我可以对它进行三角测量(手动设置三角形,我不需要没有复杂的三角测量算法)并像这样填充它而不是绘制多条线,这些线经常划过相同的像素几次。
希望这很有用。如果有人决定尝试我的方法,我建议他们马上跳到三角测量而不是使用画线。我开始绘制线条所以我使用了它,但在我看来它并不是最优的。