Как использовать функцию шума Перлина? - Java

Узнай цену своей работы

Формулировка задачи:

Доброго времени суток. Пытаюсь понять как использовать шум Перлина. После прочтения этой статьи https://habrahabr.ru/post/265775/ я перевел функцию шума Перлина этой статьи на Java:
Листинг программы
  1. import java.util.Random;
  2. public class Perlin2D {
  3. private Random random;
  4. public Perlin2D(long seed) {
  5. random = new Random(seed);
  6. }
  7. public float getNoise(float x, float y) {
  8. int left = (int)x;
  9. int top = (int)y;
  10. float localX = x - left;
  11. float localY = y - top;
  12. // извлекаем градиентные векторы для всех вершин квадрата:
  13. Vector topLeftGradient = getPseudoRandomGradientVector(left, top );
  14. Vector topRightGradient = getPseudoRandomGradientVector(left+1, top );
  15. Vector bottomLeftGradient = getPseudoRandomGradientVector(left, top+1);
  16. Vector bottomRightGradient = getPseudoRandomGradientVector(left+1, top+1);
  17. // вектора от вершин квадрата до точки внутри квадрата:
  18. Vector distanceToTopLeft = new Vector(localX, localY);
  19. Vector distanceToTopRight = new Vector(localX-1, localY);
  20. Vector distanceToBottomLeft = new Vector(localX, localY-1);
  21. Vector distanceToBottomRight = new Vector(localX-1, localY-1);
  22. // считаем скалярные произведения между которыми будем интерполировать
  23. float tx1 = dot(distanceToTopLeft, topLeftGradient);
  24. float tx2 = dot(distanceToTopRight, topRightGradient);
  25. float bx1 = dot(distanceToBottomLeft, bottomLeftGradient);
  26. float bx2 = dot(distanceToBottomRight, bottomRightGradient);
  27. // собственно, интерполяция:
  28. float tx = lerp(tx1, tx2, localX);
  29. float bx = lerp(bx1, bx2, localX);
  30. float tb = lerp(tx, bx, localY);
  31. return tb;
  32. }
  33. private float lerp(float a, float b, float t) {
  34. return a + (b - a) * t;
  35. }
  36. private float dot(Vector a, Vector b) {
  37. return a.x * b.x + a.y * b.y;
  38. }
  39. private Vector getPseudoRandomGradientVector(int x, int y) {
  40. // псевдо-случайное число от 0 до 3 которое всегда неизменно при данных x и y
  41. int v = random.nextInt(4);
  42. switch (v)
  43. {
  44. case 0: return new Vector(1, 0);
  45. case 1: return new Vector(-1, 0);
  46. case 2: return new Vector(0, 1);
  47. default: return new Vector(0,-1);
  48. }
  49. }
  50.  
  51. private static class Vector {
  52. float x;
  53. float y;
  54. Vector(float x, float y) {
  55. this.x = x;
  56. this.y = y;
  57. }
  58. }
  59. }
однако остался ряд следующих вопросов: что передовать в качестве аргумента методу getNoise(float x, float y)? Координаты точки? Допустим у меня есть некий массив хранящий карту высот, где каждый элемент - тайл или пиксель определенного цвета (от белого, до черного). Я хочу заполнить его используя шум Перлина, чтобы затем использовать для вывода изображения. Я делаю это следующим образом:
Листинг программы
  1. import java.awt.*;
  2. import java.awt.geom.Rectangle2D;
  3. import javax.swing.*;
  4. public class Map {
  5. private JFrame frame;
  6. public static void main(String[] args) {
  7. new Map();
  8. }
  9. private Map() {
  10. createFrame(500, 500);
  11. }
  12. private void createFrame(int width, int height) {
  13. frame = new JFrame("Perlin noise 2D");
  14. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  15. frame.setResizable(false);
  16. frame.getContentPane().add(new MyMap(width, height, 1));
  17. frame.pack();
  18. frame.setLocationRelativeTo(null);
  19. frame.setVisible(true);
  20. }
  21.  
  22. private class MyMap extends JPanel {
  23. private float[][] map;
  24. private int widthInCell;
  25. private int heightInCell;
  26. private int cellSize;
  27. MyMap(int width, int height, int cellSize) {
  28. setLayout(null);
  29. setPreferredSize(new Dimension(width, height));
  30. widthInCell = width / cellSize;
  31. heightInCell = height / cellSize;
  32. this.cellSize = cellSize;
  33. map = new float[widthInCell][heightInCell];
  34. Perlin2D perlin = new Perlin2D(1000);
  35. for(int x = 0; x < widthInCell; x++) {
  36. for(int y = 0; y < heightInCell; y++) {
  37. float value = perlin.getNoise(x * 0.1f, y * 0.1f);
  38. map[x][y] = (int)(value * 255) & 255;
  39. }
  40. }
  41. }
  42. public void paintComponent(Graphics g) {
  43. super.paintComponent(g);
  44. Graphics2D g2d = (Graphics2D)g;
  45. for(int x = 0; x < widthInCell; ++x) {
  46. for(int y = 0; y < heightInCell; ++y) {
  47. Rectangle2D cell = new Rectangle2D.Float(x * cellSize, y * cellSize,
  48. cellSize, cellSize);
  49. g2d.setColor(new Color((int)map[x][y], (int)map[x][y], (int)map[x][y]));
  50. g2d.fill(cell);
  51. }
  52. }
  53. }
  54. }
  55. }
и ожидаю получить нечто похожее на туман, облака. Но получаю это: А вот как выглядит это безобразие, если размер клетки 1 пиксель: Скажите пожалуйста, что я не так делаю и каковы основные принципы его использования?

Решение задачи: «Как использовать функцию шума Перлина?»

textual
Листинг программы
  1. float value = perlin.getNoise(x / 100f, y / 100f, 8, 0.2f) + .5f;

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

7   голосов , оценка 4.143 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы