簡體   English   中英

在C#中更正3D線圖

[英]Correcting 3D line drawing in C#

我(在協助下)創建了一個函數,該函數可在3D空間中繪制和繪制一行塊。 通常,這是在64x64x64網格立方體中執行的。

這是我的代碼:

    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軸-這是我認為存在問題的地方。

也許將Bresenham線算法修改為(希望)在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;
        }
    }
}
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
    }

我不懂代碼,但是根據喬納斯(Jonas)的指示,我能夠實現此目標並進行無缺陷測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM