В качестве языка программирования здесь используется C++, но перенести этот код на другой язык программирования будет не так уж сложно.
Код написанный ниже далёк от идеала, но новичкам он может пригодится.
Не так давно у меня была проблема с генерацией карты высот для ландшафта.
Я решил попробовать задать каждой точке случайное значение.
Вот пример кода для двухмерного массива данных.
for(int i=0;i<World::size;i++)
{
for(int u=0;u<World::size;u++)
{
//Задаётся зерно для генерации случайных чисел
srand(GetTickCount()*i*u);
//Задаются случайные значения всем точкам от 0*0.1-10, до 100*0.1-10
World::data[i][u]=(rand()%100)*0.1f-10.0f;
}
}
Но такой результат мне не годился, и я решил добавить холмы и ямы.
Код с использованием функции Land_MakeHill(код которой находится ниже):
srand(GetTickCount());
for(int i=0;i<rand()%(World::size*World::size*1000);i++)
{
Land_MakeHill(World::data, //Карта высот
rand()%(World::size), //Координаты по X в пределах размера карты
rand()%(World::size), //Координаты по Y в пределах размера карты
World::size, //Размер карты
(rand()%20*1.0)+20)/100.0, //Высота холма
rand()%14+14); //Радиус холма(в данном случае от 14 до 28 точек).
}
srand(GetTickCount());
for(int i=0;i<rand()%(World::size*World::size*1000);i++)
{
Land_MakeHill(World::data, //Карта высот
rand()%(World::size), //Координаты по X в пределах размера карты
rand()%(World::size), //Координаты по Y в пределах размера карты
World::size, //Размер карты
-(rand()%20*1.0)+20)/100.0, //Глубина ямы
rand()%4+7); //Радиус ямы(в данном случае от 7 до 11 точек).
}
Обратите внимание — отличие создания холма от ямы всего лишь высота. У ямы она меньше нуля, у холма больше.
Код функции Land_MakeHill:
/*data - указатель на массив,
px - координаты по x,
py - координаты по y,
size - размер карты,
height - высота,
Rad - радиус
*/
void Land_MakeHill(float** data,int px,int pz, int size,float height,int Rad )
{
for(int i=0;i<size;i++){
for(int w=0;w<size;w++){
//Чем дальше точка от центра, тем меньше значение
float d=Rad *Rad -((px-i)*(px-i)+(pz-w)*(pz-w));
data[i][w]+=d*height;
}
}
}
Такому ландшафту очень не хватает плавности, поэтому понадобилось сделать сглаживание.
Код функции Land_blur:
void Land_Blur(float** data,int size)
{
//Временный массив вершин
float** oldData = new float*[size];
for (int i = 0; i < size; i++){
oldData[i] = new float[size];
}
//Переносим значения из массива вершин во временный массив, чтобы для сглаживания не использовались уже сглаженные точки
for(int i=0;i<size;i++){
for(int u=0;u<size;u++){
oldData[i][u]=data[i][u];
}
}
//Идём начиная со второй точки до предпоследней, чтобы у каждой точки было 8 точек вокруг.
for(int i=1;i<size-1;i++){
for(int u=1;u<size-1;u++){
float v[9];
v[0]=data[i-1][u-1];
v[1]=data[i-1][u ];
v[2]=data[i-1][u+1];
v[3]=data[i] [u-1];
v[4]=data[i] [u ];
v[5]=data[i] [u+1];
v[6]=data[i+1][u-1];
v[7]=data[i+1][u ];
v[8]=data[i+1][u+1];
data[i][u]=(v[0]+v[1]+v[2]+v[3]+v[4]+v[5]+v[6]+v[7]+v[8])/9;
}
}
}
Это наипростейшее сглаживание.
Берётся точка, берутся точки вокруг неё. Их значения складываются и делятся на их количество.
Это значение и есть высота выбранной точки.
Теперь код генерации карты высот имеет следующий вид:
//Задаём случайные значения для всех точек
for(int i=0;i<World::size;i++)
{
for(int u=0;u<World::size;u++)
{
srand(GetTickCount()*i*u);
World::data[i][u]=(rand()%1000)*0.1-100;
}
}
srand(GetTickCount());
//Создаём холмы
for(int i=0;i<rand()%(World::size*World::size*1000);i++)
{
//Эта функция идентична той, которая была разобрана ранее
Land_MakeHill(World::data,rand()%(World::size*17),rand()%(World::size*17),World::size,((rand()%10*1.0)+10)/100.0,rand()%14+14);
}
srand(GetTickCount());
//Создаём ямы
for(int i=0;i<rand()%(World::size*World::size*1000);i++)
{
//Эта функция идентична той, которая была разобрана ранее
Land_MakeHill(World::data,rand()%(World::size),rand()%(World::size),World::size,-((rand()%20*1.0)+20)/100.0,rand()%4+7);
}
//Делаем сглаживание 3 раза подряд
for(int i=0;i<3;i++)
Land_Blur(World::data,World::size);
После этого я добавил ещё немного маленьких холмов и ещё раз сгладил карту.
Вот что получилось:
Автор: NomaddPlayer