Исправление 3D рисования линий в C # - PullRequest
0 голосов
/ 13 декабря 2010

Я (с помощью) создал функцию, которая строит и рисует линию блоков в трехмерном пространстве.Обычно это выполняется в сетчатом кубе 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 - вот где я считаю, что проблема существует.

Ответы [ 2 ]

8 голосов
/ 13 декабря 2010

Может быть, альтернатива алгоритму линии Брезенхама , модифицированная для (надеюсь) работы в 3D, может быть альтернативой для вас?

0 голосов
/ 14 декабря 2010
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
    }

Я не понимаю код, но, основываясь на указаниях, которые дал мне Джонас, я смог реализовать это и протестировать без ошибок.

...