Мастер
Регистрация: 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;
}
}
|
|