2010-12-13 126 views
0

我已经(在帮助下)创建了一个在3D空间内绘制并绘制块线的函数。通常这是在64x64x64网格立方体中执行的。更正C#中的3D线条绘图#

这是我的代码:

internal static int DrawLine(Player theplayer, Byte drawBlock, 
           int x0, int y0, int z0, int x1, int y1, int z1) 
    { 
     int blocks = 0; 
     bool cannotUndo = false; 
     bool detected = false; 

     int dx = x1 - x0; 
     int dy = y1 - y0; 
     int dz = z1 - z0; 

     DrawOneBlock(theplayer, drawBlock, x0, y0, z0, ref blocks, ref cannotUndo); 
     if (Math.Abs(dx) > Math.Abs(dy) && 
      Math.Abs(dx) > Math.Abs(dz) && 
      detected == false) 
     { 
      detected = true; 
      float my = (float)dy/(float)dx; 
      float mz = (float)dz/(float)dx; 
      float by = y0 - my * x0; 
      float bz = z0 - mz * x0; 
      dx = (dx < 0) ? -1 : 1; 
      while (x0 != x1) 
      { 
       x0 += dx; 
       DrawOneBlock(theplayer, drawBlock, 
        Convert.ToInt32(x0), 
        Convert.ToInt32(Math.Round(my * x0 + by)), 
        Convert.ToInt32(Math.Round(mz * x0 + bz)), 
        ref blocks, ref cannotUndo); 
      } 
     } 
     if (Math.Abs(dy) > Math.Abs(dz) && 
      Math.Abs(dy) > Math.Abs(dx) && 
      detected == false) 
     { 
      detected = true; 
      float mz = (float)dz/(float)dy; 
      float mx = (float)dx/(float)dy; 
      float bz = z0 - mz * y0; 
      float bx = x0 - mx * y0; 
      dy = (dy < 0) ? -1 : 1; 
      while (y0 != y1) 
      { 
       y0 += dy; 
       DrawOneBlock(theplayer, drawBlock, 
          Convert.ToInt32(Math.Round(mx * y0 + bx)), 
          Convert.ToInt32(y0), 
          Convert.ToInt32(Math.Round(mz * y0 + bz)), 
          ref blocks, ref cannotUndo); 
      } 
     } 
     if (detected == false) 
     { 
      detected = true; 
      float mx = (float)dx/(float)dz; 
      float my = (float)dy/(float)dz; 
      float bx = x0 - mx * z0; 
      float by = y0 - my * z0; 
      dz = (dz < 0) ? -1 : 1; 
      while (z0 != z1) 
      { 
       z0 += dz; 
       DrawOneBlock(theplayer, drawBlock, 
          Convert.ToInt32(Math.Round(mx * z0 + bx)), 
          Convert.ToInt32(Math.Round(my * z0 + by)), 
          Convert.ToInt32(z0), 
          ref blocks, ref cannotUndo); 
      } 
     } 
     return blocks; 
    } 

应该排队的框图和归还它绘制的块数。问题在于它没有画出一条不折线。在某些情况下,至少所有的块都应该通过它们的顶点进行连接,这会在块之间留下间隙。

我努力的代码的唯一部分是我计算轴的最大差异并创建一个斜率常数。试图做出完美的对角线时遇到了一个问题。所有值都是相等的,所以我只是默认了z轴 - 这是我相信问题存在的地方。

回答

8

也许Bresenham line algorithm修改为(希望)在3D工作可能是替代你吗?

public static void Swap<T>(ref T x, ref T y) 
{ 
    T tmp = y; 
    y = x; 
    x = tmp; 
} 

private void Draw3DLine(int x0, int y0, int z0, int x1, int y1, int z1) 
{ 
    bool steepXY = Math.Abs(y1 - y0) > Math.Abs(x1 - x0); 
    if (steepXY) { Swap(ref x0, ref y0); Swap(ref x1, ref y1); } 

    bool steepXZ = Math.Abs(z1 - z0) > Math.Abs(x1 - x0); 
    if (steepXZ) { Swap(ref x0, ref z0); Swap(ref x1, ref z1); } 

    int deltaX = Math.Abs(x1 - x0); 
    int deltaY = Math.Abs(y1 - y0); 
    int deltaZ = Math.Abs(z1 - z0); 

    int errorXY = deltaX/2, errorXZ = deltaX/2; 

    int stepX = (x0 > x1) ? -1 : 1; 
    int stepY = (y0 > y1) ? -1 : 1; 
    int stepZ = (z0 > z1) ? -1 : 1; 

    int y=y0, z=z0; 

    // Check if the end of the line hasn't been reached. 
    for(int x = x0; x!=x1; x+=stepX) 
    { 
     int xCopy=x, yCopy=y, zCopy=z; 

     if (steepXZ) Swap(ref xCopy, ref zCopy); 
     if (steepXY) Swap(ref xCopy, ref yCopy); 

     // Replace the WriteLine with your call to DrawOneBlock 
     Console.WriteLine("[" + xCopy + ", " + yCopy + ", " + zCopy + "], "); 

     errorXY -= deltaY; 
     errorXZ -= deltaZ; 

     if (errorXY < 0) 
     { 
      y += stepY; 
      errorXY += deltaX; 
     } 

     if (errorXZ < 0) 
     { 
      z += stepZ; 
      errorXZ += deltaX; 
     } 
    } 
} 
+0

将在几个小时内测试此代码。 – SystemX17 2010-12-14 07:38:29

+0

给出错误输出的x0,y0,z0,x1,y1和z1的值是多少? – 2010-12-14 12:39:04

+0

对不起,请注意我的码z被列为高度,所以我只是一个平面的尝试: X0 = 1个 Y0 = 1 Z0 = 1 X1 = 3 Y1 = 3 Z1 = 1 这未能得出任何结果。 – SystemX17 2010-12-14 13:01:48

0
internal static void LineCallback(Player player, Position[] marks, object tag) //MODIFIED// 
    { 
     byte drawBlock = (byte)tag; 
     if (drawBlock == (byte)Block.Undefined) 
     { 
      drawBlock = (byte)player.lastUsedBlockType; 
     } 

     player.undoBuffer.Clear(); 

     int blocks = 0; 
     bool cannotUndo = false; 

     // LINE CODE 

     int x1 = marks[0].x, y1 = marks[0].y, z1 = marks[0].h, x2 = marks[1].x, y2 = marks[1].y, z2 = marks[1].h; 
     int i, dx, dy, dz, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2; 
     int[] pixel = new int[3]; 
     pixel[0] = x1; 
     pixel[1] = y1; 
     pixel[2] = z1; 
     dx = x2 - x1; 
     dy = y2 - y1; 
     dz = z2 - z1; 
     x_inc = (dx < 0) ? -1 : 1; 
     l = Math.Abs(dx); 
     y_inc = (dy < 0) ? -1 : 1; 
     m = Math.Abs(dy); 
     z_inc = (dz < 0) ? -1 : 1; 
     n = Math.Abs(dz); 
     dx2 = l << 1; 
     dy2 = m << 1; 
     dz2 = n << 1; 

     DrawOneBlock(player, drawBlock, x2, y2, z2, ref blocks, ref cannotUndo); 
     DrawOneBlock(player, drawBlock, x2, y2, z2, ref blocks, ref cannotUndo); 

     if ((l >= m) && (l >= n)) { 

      err_1 = dy2 - l; 
      err_2 = dz2 - l; 
      for (i = 0; i < l; i++) { 
       DrawOneBlock(player, drawBlock, pixel[0], pixel[1], pixel[2], ref blocks, ref cannotUndo); 
       if (err_1 > 0) { 
        pixel[1] += y_inc; 
        err_1 -= dx2; 
       } 
       if (err_2 > 0) { 
        pixel[2] += z_inc; 
        err_2 -= dx2; 
       } 
       err_1 += dy2; 
       err_2 += dz2; 
       pixel[0] += x_inc; 
      } 
     } else if ((m >= l) && (m >= n)) { 
      err_1 = dx2 - m; 
      err_2 = dz2 - m; 
      for (i = 0; i < m; i++) { 
       DrawOneBlock(player, drawBlock, pixel[0], pixel[1], pixel[2], ref blocks, ref cannotUndo); 
       if (err_1 > 0) { 
        pixel[0] += x_inc; 
        err_1 -= dy2; 
       } 
       if (err_2 > 0) { 
        pixel[2] += z_inc; 
        err_2 -= dy2; 
       } 
       err_1 += dx2; 
       err_2 += dz2; 
       pixel[1] += y_inc; 
      } 
     } else { 
      err_1 = dy2 - n; 
      err_2 = dx2 - n; 
      for (i = 0; i < n; i++) { 
       DrawOneBlock(player, drawBlock, pixel[0], pixel[1], pixel[2], ref blocks, ref cannotUndo); 
       if (err_1 > 0) { 
        pixel[1] += y_inc; 
        err_1 -= dz2; 
       } 
       if (err_2 > 0) { 
        pixel[0] += x_inc; 
        err_2 -= dz2; 
       } 
       err_1 += dy2; 
       err_2 += dx2; 
       pixel[2] += z_inc; 
      } 
     } 

     // END LINE CODE 
    } 

我不明白的代码,但基于乔纳斯把我在我能够实现这个和测试无瑕疵的方向。

+0

我没有'我们对它进行了详细的分析,但看起来像Bresenham的线算法臃肿的实现... – 2010-12-14 14:42:32

+0

我不确定“脂肪”在哪里可以修剪,所以我认为它将不得不做。感谢您对我的回应。没有你的帮助,我会一直这么做! – SystemX17 2010-12-15 00:25:01