C# 三维体素网格视线Bresenham算法

C# 三维体素网格视线Bresenham算法,c#,algorithm,unity3d,voxel,bresenham,C#,Algorithm,Unity3d,Voxel,Bresenham,给定一个三维体素网格,其中每个体素的大小*大小*大小(宽度*高度*长度)为某个整数大小,并且一条线通过网格中的一些体素,是否有一种非常有效的方法来计算视线算法,以检测线通过的所有体素 算法约束: 由于原始Bresenham的近似性质,不会遗漏任何体素,如本2D示例所示: 算法需要合理有效,因为每帧计算一次;只要该算法不计算立方体的面积,并计算直线是否与每个立方体相交,就应该可以了 首先,Bresenham在视线方面不是很好:正如您的图纸所示,由于所有这些锯齿状边缘,最终选择的单元/体素将不允许

给定一个三维体素网格,其中每个体素的大小*大小*大小(宽度*高度*长度)为某个整数大小,并且一条线通过网格中的一些体素,是否有一种非常有效的方法来计算视线算法,以检测线通过的所有体素

算法约束:

  • 由于原始Bresenham的近似性质,不会遗漏任何体素,如本2D示例所示:
  • 算法需要合理有效,因为每帧计算一次;只要该算法不计算立方体的面积,并计算直线是否与每个立方体相交,就应该可以了

  • 首先,Bresenham在视线方面不是很好:正如您的图纸所示,由于所有这些锯齿状边缘,最终选择的单元/体素将不允许源“看到”目标

    然而,如果你愿意考虑Bresenham在2D中的问题,那么很容易扩展到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 --;
         }
       }
    }
    
    //改编自https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
    //期望x是变化最快的维度;代替
    //否则,请使用最快的更改维度,并相应地修复plot()
    功能线(浮点数x0、浮点数y0、浮点数x1、浮点数y1、浮点数z1、浮点数y1){
    浮点数dx=x1-x0;
    浮动dy=y1-y0;
    浮子dz=z1-z0;
    浮动三角误差:=abs(dy/dx);
    浮动三角误差z:=abs(dz/dx);
    浮动误差=0;
    浮动误差z=0;
    int y=y0;
    int z=z0;
    对于(int x=x0;x=0.5){
    y+=符号(dy);
    错误--;
    }
    errorZ+=三角形errorZ;
    而(errorZ>=0.5){
    z+=符号(dz);
    errorZ--;
    }
    }
    }
    

    Brensenham背后的思想可以推广到任何层面:只需跟踪累积的错误,当需要控制它们时,跳转

    @MBo我不知道如何将对查找对象交点感兴趣的光线跟踪算法用作Bresenham算法的推广,以3d@tucuxiBresenham algo不提供所有接触体素的注册,因此。。如果没有关键的改变,它就不适合这里。@MBo我同意,但OP明确要求在3d中使用Bresenham。见我答案的第一段。@tucuxi我想他用Bresenham作为(唯一)已知算法的例子