Направите интерактивну куглу од течног метала помоћу ВебГЛ-а

Аутор: John Stephens
Датум Стварања: 27 Јануар 2021
Ажурирати Датум: 19 Може 2024
Anonim
Направите интерактивну куглу од течног метала помоћу ВебГЛ-а - Креативан
Направите интерактивну куглу од течног метала помоћу ВебГЛ-а - Креативан

Садржај

Израда веб страница је пуно забаве, али понекад се морате ослободити и учинити нешто помало необично. То ћемо радити данас. Користићемо одличан Тхрее.јс мотор за стварање интерактивне металне куглице. Кликом и повлачењем куглице се искривљују, а затим полако враћају у свој првобитни облик.

Да бисмо то урадили, покриваћемо пролећну физику, 3Д векторе и ливење зрака (и још неколико других ствари), све у настојању да створимо убедљиво и забавно интерактивно искуство. Почнимо са гледањем шта ћемо направити.

Ствар у оваквим експериментима је та што на површини изгледа да немају директне комерцијалне примене. Било би вам опроштено што исто мислите и о овом, а можда сте и у праву. Али моја филозофија је да као програмер учите технике и решења проблема у овим експериментима који вам могу помоћи у свакодневном раду. Било је много пута када се ово показало тачним за мене, и сигуран сам да ће то успети и за вас. У сваком случају ово ће бити пуно забаве, па кренимо са стварањем наше сцене.


Подешавати

Да бисмо започели, мораћемо да креирамо сцену, камеру и приказивач:

/ * * * Ствара 3Д сцену, камеру и ВебГЛ приказивач. * Затим иде напред и додаје приказивач у тело * / функција инит () {вар видтх = виндов.иннерВидтх, хеигхт = виндов.иннерХеигхт, ратио = видтх / хеигхт; // постављање сцене и сцене са камере = нев ТХРЕЕ.Сцене (); камера = нова ТРИ.ПерспецтивеЦамера (75, // угао камере, однос, // однос видног поља 1, // близу равни и далека равнина испод 10000); // креирамо приказивач са антиалиасингом на рендереру = нови ТХРЕЕ.ВебГЛРендерер ({антиалиас: труе}); рендерер.сетСизе (ширина, висина); // сада додајте камеру на сцену // и ВебГЛ контекст у ДОМ сцену.адд (камера); доцумент.боди.аппендЦхилд (рендерер.домЕлемент); // радимо све остало цреатеОбјецтс (); цреатеСпрингс (); биндЦаллбацкс (); дисплацеРандомФаце (); рекуестАниматионФраме (анимате);}

Ако желите детаљнији водич за почетак рада са Тхрее.јс, то можете пронаћи на мојој веб локацији.


Претпостављам да сте покренули сцену. Е сад, ако бисте ово гледали, не бисте видели апсолутно ништа, што депримира додир, па ставимо нешто тамо!

Стварање сфере и пода

У нашој сцени имамо два предмета, лопту (сферу) и сенку на поду. Сфера је стандардни примитив Тхрее.јс (који сам мало изменио, али о томе нешто касније!), А под је раван текстурисане градијентом да изгледа као сенка. Сенке у реалном времену су заиста сјајне, али за овај водич наша слика ће нам пружити добар изглед.

Стварање сфере укључује стварање геометрије (темена и лица), а затим стварање материјала тако да изгледа као да је метално.

За креирање геометрије користимо следећи код:

// креирање сфере геометриспхереГеометри = нова ТРИ.СпхереГеометри (200, // радијус 60, // резолуција к 30); // резолуција и

Надам се прилично право напред! Имамо темена, шта је са нашим материјалом? Па, ово је мало више укључено. Сада морамо учитати у коцку текстуре (или мапу коцке како се понекад назива) како би нам пружили одсјаје, и морамо створити материјал који користи ову мапу коцке:


// прво креирамо окружење мапвар урлс = ['енвмап / поск.јпг', 'енвмап / негк.јпг', 'енвмап / поси.јпг', 'енвмап / неги.јпг', 'енвмап / посз.јпг', 'енвмап / негз.јпг'], // умотајте га у објекат који нам требатектуреЦубе = ТХРЕЕ.ИмагеУтилс.лоадТектуреЦубе (урлс); // креирамо материалсфера сфереМатериал = нев ТХРЕЕ.МесхЛамбертМатериал ({боја: 0кЕЕЕЕЕЕЕ, енвМап: тектуреЦубе , сјај: 200, сенчење: ТХРЕЕ.СмоотхСхадинг}); // сада креирамо куглу, а затим // проглашавамо њену геометрију динамичном // тако да је можемо касније ажурирати наспхере = нев ТХРЕЕ.Месх (сфераГеометрија, сфераМатеријал); сфера .геометри.динамиц = труе;

Дакле, можете видети да започињемо са стварањем мапе окружења или ТектуреЦубе. У мом случају користим једну од мапа окружења која долази са Тхрее.јс, али ви бисте могли користити другу. Затим креирамо коцку текстуре и применимо је на енвМап материјала или мапу окружења. То значи да ће сфера одражавати текстуру коцке. Такође ћете видети да сфери дајемо боју. Ова боја се помножи са текстуром на коцки и то је последња боја коју видимо. Тако, на пример, црна боја неће дати одраз, а бела боја потпуно одраз. Овде сам изабрао светло сиву. Последње што треба споменути на сфери је да смо геометрију прогласили динамичном:

сфера.геометри.динамиц = тачно;

Све ово заиста значи да говоримо Тхрее.јс-у да ћемо у једном тренутку ажурирати темена и лица и да треба да задржи те информације у близини. Ако то не учинимо, радо ћемо уклонити податке о геометрији, што је обично добра ствар јер смањује употребу меморије.

Пређимо на под. Ово је заправо прилично једноставно, па заронимо право у тај код:

// креирамо флоорпланеГеометри = нев ТХРЕЕ.ПланеГеометри (400, 400, 1); планеМатериал = нев ТХРЕЕ.МесхБасицМатериал ({цолор: 0кФФФФФФ, мап: ТХРЕЕ.ИмагеУтилс.лоадТектуре ("флоор.пнг"), транспарент: труе}) ; плане = ново ТХРЕЕ.Месх (планеГеометри, планеМатериал);

Овај пут креирамо ПланеГеометри ширине и висине од 400 и текстуре градијента који изгледа некако овако:

На крају треба да заротирамо под и поставимо га испод сфере:

// поставимо под мало надоле // и ротирамо га да буде окомит // на центар сфере плане.ротатион.к = Матх.ПИ * -0.5; плане.поситион.и = -150;

Велики! Дакле, ако отворите сцену, то би требало изгледати отприлике овако:

Пресек зрака

Овде ствари почињу да постају заиста забавне. Оно што сада желимо је да лопта реагује на кликове миша. Како кликнемо и повучемо, површина кугле би се требала искривити, а затим би требало да се слегне флуидно. Да се ​​позабавимо првим делом, изобличењем.

Да бисмо дошли до нашег решења, прво морамо да разумемо бацање зрака, што може звучати помало застрашујуће, али уверавам вас да није. Кад год цртамо 3Д облик на екрану, ми га заправо цртамо у 2Д. Ваш екран је ипак 2Д оквир. Овај процес се назива пројектовање и веома је као у стварном животу где бисте могли да пројектујете слику на зид. То нам такође ствара проблем, јер када кликнете на сцену, ми знамо к и и координате места на коме сте кликнули, али оно што не знамо је з координата; не знамо докле у екран на који сте мислили да кликнете.

Да бисмо то поправили, узимамо к и и координате места на које сте кликнули и креирамо бесконачно дугу линију или зрак унутар наше 3Д сцене која ће нам, када се поново изравна (као и остатак наше сцене), дати к и к и координати. У ствари, наш зрак представља све могуће 3Д локације које би могле представљати локацију на коју се кликнуло. Овај процес се назива непројектирање. Оно што онда можемо да урадимо са овим је да направимо зрак који започиње на положају наше камере са нашом непројектованом линијом и видимо да ли пресеца нашу сферу у било којој тачки. Ако се пресече, тачно ћемо сазнати где и изобличити лица сфере управо на тој локацији.

Као што је типично за Тхрее.јс, постоје корисне функције које можемо користити за ово:

/ * * * Проверава да ли клик мишем подразумева * пресек зрака са сфером и, ако је * да, помера лице које је погодило * * @парам {Евент} евт миш евент * / фунцтион цхецкИнтерсецтион (евт) {// добити положај миша и створити // пројектор за зрак вар моусеКс = евт.оффсетКс || евт.цлиентКс, моусеИ = евт.оффсетИ || евт.цлиентИ, пројектор = нови ТХРЕЕ.Пројецтор (); // поставимо нови вектор у тачан // систем координата вар вецтор = нев ТХРЕЕ.Вецтор3 ((моусеКс / виндов.иннерВидтх) * 2 - 1, - (моусеИ / виндов.иннерХеигхт) * 2 + 1, 0,5 ); // сада „избацујемо“ тачку на екрану // назад у саму сцену. Ово нам даје // пројектор правца зрака.унпројецтВецтор (вектор, камера); // креирамо зрак из нашег тренутног положаја камере // са тим правцем зрака и видимо да ли погађа сферу вар раи = нев ТХРЕЕ.Раи (цамера.поситион, вецтор.субСелф (цамера.поситион) .нормализе ()), пресеца се = раи.интерсецтОбјецт (сфера); // ако се зрак пресеца са // површином разрадити где и искривити лице иф (интерсецтс.ленгтх) {дисплацеФаце (пресеца [0] .фаце, ДИСПЛАЦЕМЕНТ); }}

Стварни поступак стварања зрака у Тхрее.јс врши се заузимањем положаја камере и смера који има наш виртуелни непројектовани зрак. Правац је нормализовани вектор (вектор чија је дужина 1) 3Д линије између наших непројектованих координата клика миша и положаја камере.

Коначно ћете видети да ако Тхрее.јс пријави раскрсницу да искривимо лице за које је речено да је погођено. Због једноставности нам је стало само до првог пресека који он пронађе. Вероватно ће бити другог пресека на другој страни сфере где наш зрак испуцава другу страну.

Пролећна физика

Сада хватамо кликове и искривљујемо лица која нам требају да би се наша сфера флуидно слегла. Да бисмо то урадили, користићемо основно подешавање опруге. Пошто слика говори хиљаду речи, погледајмо једну:

Оно што ћемо радити је стварање опруге између сваког темена који чине сферу. На горњој слици поједноставио сам модел сфере како би био јаснији. Истакнуо сам један од врхова наранџасте боје, виртуелна врела сјајно вруће ружичасте боје, а темена на која је повезан наранџасти плавом бојом. Сада, када изобличимо сферу, кодираћемо је, тако да се ти извори покушавају вратити у почетни положај, све кроз чудо Хооке-овог закона.

Прво што ћемо урадити је да прођемо кроз свако лице и за свако ћемо створити опруге између његових саставних врхова:

/ * * * Ствара појединачну опругу * * @парам {Нумбер} старт Индекс темена за почетак опруге * @парам {Нумбер} енд Индекс темена за почетак опруге * / функција цреатеСпринг (почетак, крај) {вар спхереВертицес = спхере.геометри.вертицес; вар стартВертек = сфераВертицес [старт]; вар ендВертек = сфераВертицес [крај]; // креирамо опругу стартВертек.спрингс.пусх ({старт: стартВертек, енд: ендВертек, ленгтх: стартВертек.поситион.ленгтх (ендВертек.поситион)});}

Да бих ствари учинио мало једноставнијим, уклонио сам код који ствара опружни низ унутар сваког темена, али ако погледате узорак кода, видећете га у пуном сјају. Можете да видите да стварамо опругу са референцама на положај сваког темена и оригиналну дужину опруге. Имајући дужину видећемо колико се проширио и колика је сила примењена да се врати на ову дужину.

Подразумевано примитиви у Тхрее.јс деле врхове између лица. Ово је сјајно за нас јер желимо да наша лица буду повезана кроз ове заједничке темене. Нажалост, подразумевано се не деле сви врхови, посебно почетни и крајњи у свакој траци. Нето резултат овога је да бисмо имали шав који се спушта од врха до дна наше сфере где не постоје опруге! Дакле, креирао сам модификовану верзију СпхереГеометри у пакету са Тхрее.јс и ажурирао је тако да дели први и последњи вертекс.

Па, ово је добро, сада се приближавамо свом циљу. Имамо куглу, под, пратимо кликове и искривљујемо лица сфере. На сфери имамо опруге које можемо користити за руковање темена. Последња ствар која све то повезује је стварна пролећна физика.

Погледајмо физику и можемо то раздвојити. Усредсредићемо се на занимљив део функције:

// сада прођите кроз сваку појединачну опругу (вар в = 0; в вертекСпрингс.ленгтх; в ++) {// израчунајте дужину опруге у поређењу // са њеном основном дужином вертекСпринг = вертекСпрингс [в]; дужина = вертекСпринг.старт.поситион. дужина (вертекСпринг.енд.поситион); // сада утврдимо докле се опруга // продужила и употребимо ово да створимо // силу која ће повући вертек ектенсион = вертекСпринг.ленгтх - ленгтх; // повући старт вертек аццелератион.цопи (вертекСпринг.старт.нормал) .мултиплиСцалар (ектенсион * СПРИНГ_СТРЕНГТХ); вертекСпринг.старт.велоцити.аддСелф (убрзање); // повући крај вертек аццелератион.цопи (вертекСпринг.енд.нормал) .мултиплиСцалар (ектенсион * СПРИНГ_СТРЕНГТХ); вертекСпринг.енд.велоцити.аддСелф (убрзање); // додамо брзину положају користећи // основну Еулерову интеграцију вертекСпринг.старт.поситион.аддСелф (вертекСпринг.старт.велоцити); вертекСпринг.енд.поситион.аддСелф (вертекСпринг.енд.велоцити); // пригуши брзину опруге тако да се заувек не врти напред-назад вертекСпринг.старт.велоцити.мултиплиСцалар (ДАМПЕН); вертекСпринг.енд.велоцити.мултиплиСцалар (ДАМПЕН);}

Као што видите из кода, пролазимо кроз сваку опругу и утврђујемо колико је опруга дуга, а одузимамо оригиналну дужину која нам даје продужетак опруге. Према Хоокеовом закону постоји сила коју треба применити на врх, а то је:

Ф = -к * продужетак, где је к „пролећна константа“

Све ово значи да је сила пропорционална продужетку и негативна је јер делује у супротном смеру од продужења. Што је продуженији, повлачи у супротном смеру. Све што остаје је к, колико је јака опруга и нормално је између 0 (не еластично) и 1 (потпуно еластично).

Одавде радимо једноставну Еулерову интеграцију. За израчунавање убрзања (претпостављам у коду масу од 1 ради једноставности) можемо да користимо класичну једначину Ф = ма коју додамо брзини опруге. На крају додајемо брзину опруге његовом положају.

На крају ћете приметити да пригушујем брзину при сваком пролазу. Разлог томе је што се у стварном животу извори заустављају. Без тога ће наше пролеће стално пинг-овати и напред и врло брзо ће измаћи контроли!

Завршни комадићи

Имамо све делове наше слагалице на месту. Шта сад? Па, неколико ствари сам убацио само да бих побољшао искуство, које нису строго неопходне, али, знате, ми радимо на стварању најбољих могућих искустава.

После пригушивања опруга видећете да покушавамо да олакшамо опругу у основни положај. Разлог за то је покушај задржавања лопте у приближно њеном изворном облику. Мали је додир, али само значи да опруга не контролише лопту у потпуности, што је добро за стабилизацију наше сфере:

// покушај пригушивања врха // у првобитни положај тако да се // не извуче из цонтролвертек.поситион.аддСелф (вертек.оригиналПоситион.цлоне (). субСелф (вертек.поситион) .мултиплиСцалар (0.03)) ;

Док прегледавате код, видећете да се по отпуштању миша поставља тајмер који, када се активира, насумично бира лице и помера га. Ово нам даје помало језив органски осећај лопте, помало као да нешто покушава да побегне.

/ * * * Случајно бира лице и премешта га *, а затим поставља временско ограничење за следеће премештање * / функција дисплацеРандомФаце () {вар спхереФацес = спхере.геометри.фацес, рандомФацеИндек = Матх.флоор (Матх. рандом () * спхереФацес.ленгтх), рандомФаце = спхереФацес [рандомФацеИндек]; дисплацеФаце (рандомФаце, ДИСПЛАЦЕМЕНТ); аутоДистортТимер = сетТимеоут (дисплацеРандомФаце, 100);}

На крају, али не најмање важно, морамо разговарати о ажурирању геометрије. У Тхрее.јс морате то да обавестите када ажурирате положаје врхова. Без овога на месту нећете видети никакве промене, а то је врло збуњујуће!

// означимо да се геометрија сфере // променила и прерачунавамо нормалсспхере.геометри .__ диртиВертицес = труе; спхере.геометри .__ диртиНормалс = труе; спхере.геометри.цомпутеФацеНормалс (); спхере.геометри.цомпутеВертекНормалс ()

Закључак

Па, не знам за вас, али имао сам гомилу забаве! Направили смо течну металну куглу која реагује на миша и изгледа заиста сјајно док то чини. Погледајте изворни код и раскомадајте га на делове.

Надам се да се осећате надахнуто да се поиграте са Тхрее.јс и ВебГЛ за себе. Ако то учините, обавестите нас; волели бисмо да видимо шта ви стварате!

Наше Публикације
Најбољи веб хостинг за ВордПресс 2021
Опширније

Најбољи веб хостинг за ВордПресс 2021

Тражите ли најбољи веб хостинг за ВордПресс сајтове? Онда сте дошли на право место. Прочитајте како бисте сазнали све о ВордПресс хостингу, зашто вам је потребан и који су најбољи добављачи.ВордПресс....
Како сликати култивисаног стеампунк ​​тигра
Опширније

Како сликати култивисаног стеампунк ​​тигра

Одређена правила вашег одабраног стеампунк ​​универзума вероватно ће одредити о каквом тигра овде говоримо. Да ли је антропоморфна, механичка или нешто треће?За лик тигра могу бити потребни дизајни за...
Приступачност и елемент
Опширније

Приступачност и елемент

ХТМЛ5 има скуп елемената који чине структуру странице приступачнијом помоћним технологијама (АТ). Тхе заглавље>, подножје>, нав>, чланак>, на страну> и сецтион> елементи омогућавају ...