Мастер
Регистрация: 13.06.2011
Сообщений: 1,103
Написано 481 полезных сообщений (для 1,836 пользователей)
|
Ответ: Пуск рек на карте высот
Сообщение от Den
У меня была старая реализация с каплями, но это все генерировалось очень долго, а результат выходил не очень. На карте получались тысячи маленьких речушек и озер. Скринов и демок к сожалению не сохранилось, т.к. я посчитал это тупиковой ветвью и забил.
|
ну вот с каплями и со скрином.
Сообщение от dsd
какая то фигня при отрисовке в текстуру напоминающая реки.
довольно шустрая для карты 1024х1024
using UnityEngine; using System.Collections; public class CalcRiverbend : MonoBehaviour { public static int width = 1024; //карта высот public static float [,] map = new float [width,width]; //количество воды прошедшей по клетке public static int [,] water = new int [width,width]; //количество воды в клетке public static int [,] waterNumber = new int [width,width]; //кто из соседей клетки самый нижний // значение от 0 до 9 public static byte [,] height = new byte [width,width]; //смещения для воды public static Vector2 [] disp = { new Vector2(-1,-1), new Vector2(-1,0), new Vector2(-1,1), new Vector2(0,-1), new Vector2(0,0), new Vector2(0,1), new Vector2(1,-1), new Vector2(1,0), new Vector2(1,1)}; public static void Init(){ //получение карты высот for(int i = 0; i < width; i++){ for(int j = 0; j < width; j++) { map[i,j] = PerlinNoise.perlin2d(i*0.01f,j*0.01f,0); } } //вычисление самого низкого из ближайших соседей for(int i = 0; i < width; i++){ for(int j = 0; j < width; j++) { height[i,j] = CalcLowest(i,j); } } //теперь сбрасываю на каждую клетку карты по 1 капле воды for(int i = 0; i < width; i++){ for(int j = 0; j < width; j++) { waterNumber[i,j] = 1; } } //а теперь пусть капли текут вниз //заодно считаю для каждой точки сколько капель прошло по ней //повторяю сколько то раз процедуру for(int k = 0; k < 200; k++){ for(int i = 0; i < width; i++){ for(int j = 0; j < width; j++) { //если в точке есть капли if (waterNumber[i,j]>0) { //узнаю в какую из соседей она течет Vector2 displacement = disp[height[i,j]]; //номер ячейки int x0= (int)displacement.x + i, y0 = (int)displacement.y + j; //если точки в границах if(x0>=0 && y0>=0 && x0<width && y0<width){ //перевожу воду куда следует waterNumber[x0,y0] += waterNumber[i,j]; //увеличиваю счетчик воды прошедшей по клетке water[i,j] += waterNumber[i,j]; //убираю утекшую воду waterNumber[i,j] = 0; } } } } } } //вычисляет какое из девяти чисел самое маленькое private static byte CalcLowest(int x, int y){ //пусть нижняя центральная по умолчанию byte result = 4; //создаю массив для значений высот float [] heights = {0f,0f,0f,0f,0f,0f,0f,0f,0f}; //теперь заполняю его значения высот for(int i = -1; i <=1; i++){ for(int j = -1; j <=1; j++) { int x0= x+i, y0 = y+j; if(x0>=0 && y0>=0 && x0<width && y0<width){ heights[(i+1)*3+j+1] = map[x0,y0]; } } } //рисую где находится нижняя точка из текущих 9-ти for(int i = 0; i < heights.Length; i++){ if(heights[result]>heights[i]){result = (byte)i;} } return result; } }
|
|