Tag Archives: displacement

Պրոցեդուրային գեներացում: Մաս 1

1.1 Ներածություն
Այս խորագրի ներքո այսուհետ կներկայացվեն հոդվածներ ժամանակակից ծրագրավորման առջև դրված հետաքրքիր խնդիրների դասի՝ պրոցեդուրային գեներացման (procedural generation) վերաբերյալ: Պրոցեդուրային գեներացումը նվիրված է հաշվիչ մեքենաների միջոցով պսեվդո-պատահական պատկերների ստացմանը և մեծ կիրառություն ունի համակարգչային գրաֆիկայում և խաղերի դիզայնում: Հոդվածները հաճախ կուղեկցվեն ծրագրային կոդի հատվածներով, հարկ եղած դեպքում կոդը կուղեկցվի հարակից բացատրություններով: Օրինակները աշխատացնելու համար պահանջվող գրադարանների և կոմպոնենտների մասին կնշվի առանձին, ամեն օրինակի հետ:
Պրոցեդուրային գեներացումը անհնար կլիներ առանց պսեվդո-պատահական թվերի ստացման մեթոդների: Մենք չենք սևեռի մեր ուշադրությունը այս ոլորտի վրա, փոխարենը կօգտագործենք պսեվդո-պատահական թվեր գեներացնող .Net Framework-ի գրադարանի System.Random դասը:

1.2 Ռեալիստիկ լանդշաֆտի ստացում, միջնակետի տեղաշարժման ալգորիթմ

Դիտարկենք հետևյալ խնդիրը: Պահանջվում է գեներացնել և պատկերել իրական [Երկիր մոլորակի] լանդշաֆտի ուրվագծին նման ուրվագիծ: Պարզության համար կդիտարկենք ոչ թե եռաչափ լանդշաֆտի գեներացումը, այլ երկչափինը: Կարելի է վերաբերվել դրան որպես եռաչափ լանդշաֆտի ուղղահայաց հատույթի: Նայեք նկարին, որպեսզի պարզ լինի, ինչի մասին է խոսքը:
image

Նման պատկեր կարելի է տեսնել օրինակ երեկոյան հեռվից սարերի/բլուրների խմբին նայելիս: Նման խնդրի լուծման զանազան ալգորիթմներ կան, առավել պարզը դրանցից (ընդ որում, պարզ != վատ) միջնակետի տեղաշարժման ալգորիթմն է:

1. Սկզբում ունենք մի հորիզոնական հատված

midpoint02. Հատվածի ամեն սեգմենտը միջնակետում բաժանում ենք 2 մասի, միջնակետը [-range, range] միջակայքում ընկած պատահական չափով տեղաշարժում ենք վերև կամ ներքև
midpoint3. range թիվը բազմապատկում ենք roughness-ով (խորդուբորդության գործակից): Այն 0.0 – 1.0 միջակայքի ինչ-որ թիվ է: Որքան փոքր է այն, այնքան հղկված ու «փափուկ» է ստացվում ուրվագիծը:
4. Կրկնում ենք 2 և 3 քայլերը պահանջված անգամ: Դժվար չէ նկատել, որ ամեն անգամ 2-րդ քայլն անելուց հետո հատվածների քանակը կրկնապատկվում է:

Դիտողություն: Ռեալիստիկ պատկեր ստանալու համար կարելի է ալգորիթմն աշխատացնել սեգմենտների բավականին մեծ քանակ պահանջելով: Կարելի է նաև ստանալ համեմատաբար քիչ թվով կետեր (սեգմենտների փոքր թիվ տալ մուտքում) և դրանք ինտերպոլացնել գծայնորեն:

Դիտողություն 2: Շատերի մոտ կարող է այս ալգորիթմը ռեկուրսիվ իրականացնելու «ախորժակ» առաջանա: Մի շտապեք, իտերատիվ տարբերակը ճիշտ իրականացնելիս ավելի էֆեկտիվ է:

Այս, առաջին հայացքից պարզ հրամանները կարող են տալ շատ հզոր արդյունք: Իրականում այս ալգորիթմը ծնունդ է առել ծրագրավորման բոլորովին այլ՝ պատկերների ֆրակտալ կոմպրեսիայի ոլորտում կատարված հետազոտությունների արդյունքում: Սա ուղղված է պատկերները պահելու համար պիքսելների մասին ինֆորմացիա պահելու փոխարեն այլ տվյալներ պահելուն, պատկերի զբաղեցրած հիշողության ծավալը փոքրացնելու նպատակով:

Ստորև բերվում է C#-ով գրված ֆունկցիա, որն իրականացնում է ալգորիթմը:

private List<Point> GeneratePoints(int S, float roughness, int range)
{
List<Point> pts = new List<Point>();
pts.Insert(0, new Point(800, 200));
pts.Insert(0, new Point(0, 200));
int segments = 1;
Random rand = new Random();

            while (segments < S)
{
for (int i = 0; i < segments; i++)
pts.Insert(1 + 2 * i, new Point((pts[2*i].X + pts[2*i + 1].X) / 2, (pts[2*i].Y + pts[2*i + 1].Y) / 2 + rand.Next(-range, range)));

                segments *= 2;
range = (int)((float)range * roughness);
}

return pts;
}

Կարող եք բեռնել և փորձարկել նաև Midpoint Displacement ծրագիրը: Այն թույլ է տալիս աշխատանքի ընթացքում կարգավորել սեգմենտնետի քանակը, հեռահարությունն ու խորդուբորդության գործակիցը: Այն աշխատացնելու համար անհրաժեշտ է ունենալ .Net Framework Redistributable 4.0-ն:

midpoint

Եթե ցանկանում եք ստանալ այս ծրագրի կոդը, գրեք մեկնաբանություններում կամ էլեկտրոնային փոստով:
Հաջորդ անգամ (հաջորդ սերիայում Open-mouthed smile) կդիտարկենք նույն խնդիրը լուծող մեկ այլ մեթոդ՝ Pimsleur (չգիտեմ հայերեն էս ոնց են արտասանում…) Noise ֆունկցիայի վրա հիմնված: Կդիտարկենք նաև տարածված ծրագրերում և խաղերում այս մեթոդների կիրառությունների օրինակներ:

Advertisements

Թողնել մեկնաբանություն

Filed under Ծրագրավորում