三维体素网格视线Bresenham算法

时间:2018-05-24 17:52:02

标签: c# algorithm unity3d voxel bresenham

给定一个3D体素网格,其中每个体素的SIZE * SIZE * SIZE(宽度*高度*长度)对于某个整数SIZE和一条线穿过网格中的一些体素,是否有一种相当有效的计算方法视线算法检测线通过的所有体素?

算法约束:

  1. 由于原始Bresenham的近似性质,没有遗漏任何体素,如本2D图所示:
  2. 2D Bresemham

    1. 算法需要合理有效,因为每帧会计算一次;只要算法不占用立方体区域并计算线是否与每个立方体相交,就应该没问题。

1 个答案:

答案 0 :(得分:0)

首先,Bresenham在视线方面并不擅长:如图所示,由于所有这些锯齿状边缘,所得到的细胞/体素选择将不允许光源“看到”目标。

但是,如果你愿意在2d中考虑Bresenham对你的问题有好处,那么很容易扩展到3d:给定一条从p0 = {x0,y0,z0}到p1 = {x1,y1,z1}的行,你可以从{x0,y0}到{x1,y1}以及从{x0,z0}到{x1,z1}两次运行2d Bresenham。使用第一次运行的x和y值,以及第二次运行的z值。

或者,您可以进行全面概括:

 // adapted from https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
 // expects x to be the fastest-changing dimension; replace
 //   with fastest-changing dimension otherwise, and fix plot() accordingly
 function line(float x0, float y0, float x1, float y1, float z1, float y1) {
   float dx = x1 - x0;
   float dy = y1 - y0;
   float dz = z1 - z0;
   float deltaErrorY := abs(dy / dx);
   float deltaErrorZ := abs(dz / dx);
   float errorY = 0;
   float errorZ = 0;
   int y = y0;
   int z = z0;
   for (int x = x0; x<x1; x++) { 
     plot(x,y,z);
     errorY += deltaErrorY;
     while (errorY >= 0.5) {
         y += sign(dy);
         errorY --;
     }
     errorZ += deltaErrorZ;
     while (errorZ >= 0.5) {
         z += sign(dz);
         errorZ --;
     }
   }
}

Brensenham背后的理念可以推广到任何方面:只需跟踪累积的错误,并在需要时跳转以控制它们