Thuật toán dịch chuyển trung điểm


14

MDPMDP

Câu hỏi này chủ yếu xuất phát từ sự tuyệt vọng , sau khi dành nhiều giờ cố gắng tìm ra vấn đề.

Nếu bạn đưa mắt vào bức ảnh trên, bạn sẽ thấy thuật toán chuyển vị trung điểm của tôi đang hoạt động (phần nào) thành công; trong việc tạo ra một mô hình tiếng ồn hơi mạch lạc.

Tuy nhiên, nó đang để lại một lưới chấm đen trên hình ảnh, và tôi không biết tại sao. Tôi có thể thấy trước đây là một vấn đề trong toán học, nhưng tôi không thể thấy nó; điều này cũng không được chỉ ra trong bất kỳ tài nguyên trực tuyến nào là một vấn đề có thể xảy ra; vì vậy bất kỳ trợ giúp sẽ được đánh giá cao để săn lùng lỗi này.

unsigned char** mdp(unsigned char** base, unsigned base_n, unsigned char r) {
    size_t n = (2 * base_n) - 1;

    unsigned char** map = new unsigned char*[n];
    for (unsigned i = 0; i < n; ++i) map[i] = new unsigned char[n];

    // Resize
    // 1 0 1
    // 0 0 0
    // 1 0 1
    for (size_t i = 0; i < n; i += 2) {
        for (size_t j = !(i % 2 == 0); j < n; j += 2) {
            map[i][j] = base[i / 2][j / 2];
        }
    }

    // Diamond algorithm
    // 0 0 0
    // 0 X 0
    // 0 0 0
    for (size_t i = 1; i < n; i += 2) {
        for (size_t j = 1; j < n; j += 2) {
            unsigned char& map_ij = map[i][j];

            unsigned char a = map[i - 1][j - 1];
            unsigned char b = map[i - 1][j + 1];
            unsigned char c = map[i + 1][j - 1];
            unsigned char d = map[i + 1][j + 1];
            map_ij = (a + b + c + d) / 4;

            unsigned char rv = std::rand() % r;
            if (map_ij + r < 255) map_ij += rv; // EDIT: <-- thanks! the bug! `map_ij + rv`, not `r`
            else map_ij = 255;
        }
    }

    // Square algorithm
    // 0 1 0
    // 1 0 1
    // 0 1 0
    for (size_t i = 0; i < n; ++i) {
        for (size_t j = (i % 2 == 0); j < n; j += 2) {
            unsigned char& map_ij = map[i][j];

            // get surrounding values
            unsigned char a = 0, b = a, c = a, d = a;
            if (i != 0) a = map[i - 1][j];
            if (j != 0) b = map[i][j - 1];
            if (j + 1 != n) c = map[i][j + 1];
            if (i + 1 != n) d = map[i + 1][j];

            // average calculation
            if (i == 0) map_ij = (b + c + d) / 3;
            else if (j == 0) map_ij = (a + c + d) / 3;
            else if (j + 1 == n) map_ij = (a + b + d) / 3;
            else if (i + 1 == n) map_ij = (a + b + c) / 3;
            else map_ij = (a + b + c + d) / 4;

            unsigned char rv = std::rand() % r;
            if (map_ij + r < 255) map_ij += rv;
            else map_ij = 255;
        }

    }

    return map;
}

Nếu bạn có bất kỳ mẹo hoặc tài nguyên nào khác ngoài http://www.gameprogrammer.com/fractal.htmlhttp://www.lighthouse3d.com/opengl/terrain/index.php?mpd2 để tạo địa hình dựa trên fractal, tôi sẽ đánh giá cao họ như ý kiến ​​cũng.

Biên tập:

MDP

Đây là hình ảnh mới, theo gợi ý (ty) của Fabians, tuy nhiên nó vẫn có một số điểm kỳ lạ, mà bạn sẽ có thể nhìn thấy ngay lập tức ('lúm đồng tiền' nhỏ ở mọi nơi).

Điều gì có thể gây ra hành vi kỳ lạ này? Mã nguồn được cập nhật: http://www.pastie.org/1924223

Biên tập:

Rất cám ơn Fabian trong việc tìm ra lỗi kiểm tra giới hạn, đối với những người quan tâm, đây là giải pháp hiện tại là 512x512 png. Và mã nguồn hiện tại (được sửa đổi bởi Fabian) . MDP

Chỉnh sửa (năm sau): Phiên bản Python https://gist.github.com/dcousens/5573724#file-mdp-py


Trong các bức ảnh, có vẻ như mỗi dấu chấm có cùng độ cao. Là các góc ở cùng một chiều cao là tốt?
deft_code

1
Đối với những gì nó có giá trị, hình ảnh của bạn trông rất đẹp. :)
ChrisE

scrand (): Tôi không hoàn toàn chắc chắn rằng tôi hiểu - điều này có nghĩa là trả lại một ký tự đã ký trong khoảng (-r / 2, r / 2]? Dù sao, lúm đồng tiền, đối với tôi, có vẻ giống như kết quả Các khu vực lân cận dường như đột nhiên bắn ra màu đen, và sau đó trèo lên màu trắng. Nhìn chung, có vẻ như có dải màu sắc, một lần nữa gợi ý cho tôi rằng bạn đang tràn ra, có lẽ. Bạn có phiền khi làm toán trong một độ chính xác cao hơn (giả sử là số nguyên), sau đó kẹp các giá trị vào phạm vi [0,256] hoặc [-128,127]?
ChrisE

Vấn đề đã được giải quyết dưới đây, đó là do tôi đã kiểm tra giới hạn phạm vi của giá trị ngẫu nhiên, không phải giá trị thực của nó. Scrand () là chức năng 'tiếng ồn' tạm thời trở lại lý tưởng [-128, 127]
giảm tốc

À, tuyệt! Vui mừng khi biết nó đang hoạt động.
ChrisE

Câu trả lời:


12

Thuật toán đệ quy thêm một giá trị, nhưng giá trị có thể dương hoặc âm (thường là + -1 / (2 ^ quãng tám))

Nếu bạn bắt đầu từ 0 và chỉ thêm các giá trị dương, thì bạn chỉ có thể đi lên và đó là lý do tại sao bạn nhìn thấy các đỉnh được kéo xuống.

hãy thử bắt đầu từ 127 thay vì 0 cho bốn góc và cũng thử ký char (sau đó kiểm tra giới hạn của bạn ở cả trên và dưới)

BIÊN TẬP

vì vậy, hai điều nữa cần thay đổi trong chính (64 >> i) để có được một nửa hiệu ứng ở mỗi quãng tám và cả chức năng đầu ra của bạn (chức năng ánh xạ cuối cùng [] [] tp imgdta [], bạn chỉ cần cần phải đưa vào

imgdta [(i * n) + j] = 128 + cuối cùng [i] [j];

thay vì khối if khác.

một điều nữa, tôi không chắc tại sao, nhưng kiểm tra giới hạn của bạn không thành công (đó là dòng 38 và 65) nếu bạn loại bỏ hoàn toàn kiểm tra, bạn cũng nhận thấy một số đốm màu mới, vì vậy tôi nghĩ bạn có thể cần phải quảng cáo lên loại lớn hơn trước khi thực hiện kiểm tra giới hạn nếu bạn muốn hình ảnh ồn hơn bạn nhận được với "64 / i".

EDIT KHÁC

chỉ cần tìm ra nó là gì, bạn đang so sánh với 'r', không phải 'rv', trong kiểm tra giới hạn. Đây là mã cố định: http://pastie.org/1927076


Đây chắc chắn là cách tốt hơn để nói về nó, nhưng chưa có điếu xì gà nào, có vẻ như hình ảnh của tôi vẫn còn một số 'quirks', tôi đã cập nhật bài viết gốc.
giảm tốc

không chắc chắn nhưng dòng 93 có vẻ sai, 64 / i có thể cần 64 >> i (khi bạn giảm một nửa hiệu ứng mỗi quãng tám)
Richard Fabian

À !! Cảm ơn bạn rất nhiều, tôi không thể tin rằng, tôi biết đó là một điều ngu ngốc cho vấn đề thứ hai đó. Rất thích mã TGA tạm thời của bạn, xin lỗi, tôi đã cứu bạn khỏi rắc rối và đưa ra tiêu đề.
giảm tốc

3

Hai thứ nhảy ra:

  1. Bạn có một lý do thuyết phục để làm điều này trong điểm cố định? Không có gì sai với nó cả, và có rất nhiều lý do để sử dụng nó (đáng chú ý nhất là yêu cầu bộ nhớ nếu bạn dự định đi lên bản đồ HUGE), nhưng tôi chắc chắn sẽ bắt đầu với phiên bản thuật toán nổi và chuyển đổi nó thành điểm cố định sau khi bạn đã làm việc; nếu không có gì khác, hãy loại bỏ một nguồn lỗi chính đáng (đặc biệt, tôi nghi ngờ việc kẹp của bạn có thể gây ra sự cố và các điều kiện khi nào cần thêm / trừ rv).
  2. Mặc dù rất khó để nói từ mã mà tôi thấy, có vẻ như sự dịch chuyển chiều cao ngẫu nhiên của bạn đang tăng theo cấp độ và kết hợp với vấn đề trong (1) có thể gây ra một số vấn đề - bạn không nên thay thế bởi cùng một lượng ở mỗi cấp.

Ồ, và một điều không phải là thuật toán: Tôi thực sự khuyên bạn không nên thực hiện phân bổ trong hàm mdp () của bạn; vượt qua trong hai mảng đã được phân bổ khác nhau và thực hiện phép lặp 'tại chỗ', đi từ cái này sang cái khác. Nếu không có gì khác, điều này sẽ cho phép bạn ping-pong qua lại khi bạn thực hiện các lớp thay vì phải phân bổ một mảng mới mỗi lần ra ngoài.


Một số điểm tốt, rõ ràng tôi chỉ đang cố gắng để có được thuật toán chính xác, việc triển khai không còn lý tưởng, tôi thậm chí còn không dọn sạch bộ nhớ vào thời điểm này: P.
giảm tốc

Tại thời điểm này, tỷ lệ vượt qua là 64 / i, rõ ràng tôi sẽ thay đổi điều đó sau, nhưng nó không thực sự giải thích hiệu ứng lúm đồng tiền hiện đang trải nghiệm. : S
deceleratedcaviar

0

Ngoài ra, bạn hiện không xóa bộ nhớ mà bạn đang phân bổ. Để khắc phục điều này, thay đổi dòng 104 từ:

for (unsigned i = 1; i < 6; ++i) final = mdp(final, n, 64 / i);

đến

for (unsigned i = 1; i < 6; ++i) {
  signed char** new_final = mdp(final, n, 64 / i);
  for (unsigned i = 0; i < n; ++i)
    delete[] final[i];
  delete[] final;
  final = new_final;
}

và thêm phần này sau khi viết ra tệp tga:

for (unsigned i = 0; i < n; ++i)
  delete[] final[i];
delete[] final;

Tôi rất ý thức về cách làm sạch bộ nhớ, nhưng vì đây chỉ là một nguyên mẫu thuật toán và sẽ được viết lại để sử dụng các vectơ, tôi chỉ muốn chắc chắn rằng nó là chính xác.
giảm tốc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.