Java软光栅渲染器-光栅化2D直线

目标

光栅化2D直线(布雷森汉姆直线演算法、吴小林直线算法等)

实现

在前面的基础上,实现光栅化2D直线就简单多了,只需要在 ImageRaster 类中增加一个画线方法即可。具体的实现,我先选择布雷森汉姆(Bresenham )直线算法。

网上相关资料非常多,我参考的是这些文章:

实现代码如下:

/**
 * 画线
 * 
 * http://tech-algorithm.com/articles/drawing-line-using-bresenham-algorithm/
 * 
 * @param x0
 * @param y0
 * @param x1
 * @param y1
 * @param color
 */
public void drawLine(int x0, int y0, int x1, int y1, ColorRGBA color) {
    int x = x0;
    int y = y0;

    int w = x1 - x0;
    int h = y1 - y0;

    int dx1 = w < 0 ? -1 : (w > 0 ? 1 : 0);
    int dy1 = h < 0 ? -1 : (h > 0 ? 1 : 0);

    int dx2 = w < 0 ? -1 : (w > 0 ? 1 : 0);
    int dy2 = 0;

    int fastStep = Math.abs(w);
    int slowStep = Math.abs(h);
    if (fastStep <= slowStep) {
        fastStep = Math.abs(h);
        slowStep = Math.abs(w);

        dx2 = 0;
        dy2 = h < 0 ? -1 : (h > 0 ? 1 : 0);
    }
    int numerator = fastStep >> 1;

    for (int i = 0; i <= fastStep; i++) {
        drawPixel(x, y, color);
        numerator += slowStep;
        if (numerator >= fastStep) {
            numerator -= fastStep;
            x += dx1;
            y += dy1;
        } else {
            x += dx2;
            y += dy2;
        }
        drawPixel(x, y, color);
    }
}

我需要多定义一个2D线段类,并让它实现Drawable接口。

package net.jmecn.geom;

import net.jmecn.math.ColorRGBA;
import net.jmecn.renderer.ImageRaster;

/**
 * 代表一条线段。
 * 
 * @author yanmaoyuan
 *
 */
public class Line2D implements Drawable {

    public int x0, y0;
    public int x1, y1;
    public ColorRGBA color = ColorRGBA.RED;

    @Override
    public void draw(ImageRaster imageRaster) {
        imageRaster.drawLine(x0, y0, x1, y1, color);
    }

}

挺简单的吧?

然后再写一个测试用例。

package net.jmecn.examples;

import java.util.Random;

import net.jmecn.Application;
import net.jmecn.geom.Line2D;
import net.jmecn.math.ColorRGBA;

/**
 * 绘制2D线段
 * 
 * @author yanmaoyuan
 *
 */
public class Test2DLines extends Application {

    public static void main(String[] args) {
        Test2DLines app = new Test2DLines();
        app.setResolution(720, 405);
        app.setTitle("2D Lines");
        app.setFrameRate(120);
        app.start();
    }

    /**
     * 初始化
     */
    @Override
    protected void initialize() {
        Random rand = new Random();
        /**
         * 随机生成线段
         */
        for(int i=0; i<100; i++) {
            Line2D line = new Line2D();
            line.x0 = rand.nextInt(width);
            line.y0 = rand.nextInt(height);
            line.x1 = rand.nextInt(width);
            line.y1 = rand.nextInt(height);
            line.color = new ColorRGBA(rand.nextInt(0x4FFFFFFF));

            // 添加到场景中
            scene.add(line);
        }
    }

    @Override
    protected void update(float delta) {
    }

}

没有什么太多好解释的,不过是随机生成了一些直线。

运行结果:

总结

目标达成。

我没有尝试吴小林直线画法,主要是以前做TMXLoader项目时,用jME3的ImageRaster实现过这种抗拒齿直线算法,这里就不打算再做一遍了。