Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Генерация карты высот

Anna | 25.06.2014 | нет комментариев
В качестве языка программирования тут применяется C , но перенести данный код на иной язык программирования будет не так уж трудно.
Код написанный ниже далёк от идеала, но новичкам он может сгодится.
Не так давным-давно у меня была задача с генерацией карты высот для ландшафта.

Я решил испробовать задать всякой точке случайное значение.
Вот пример кода для двухмерного массива данных.

//Задаётся зерно для генерации случайных чисел
srand(GetTickCount());       
for(int i=0;i<World::size;i  )
{
	for(int u=0;u<World::size;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];
	}
}
//Идём начиная со 2-й точки до предпоследней, Дабы у всякой точки было 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);

Позже этого я добавил ещё немножко маленьких холмов и ещё раз сгладил карту.
Вот что получилось:

 

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB