GLScene tutorial

1

GLScene tutorial

offline
  • Srđan Tot
  • Am I evil? I am man, yes I am.
  • Pridružio: 12 Jul 2005
  • Poruke: 2483
  • Gde živiš: Ljubljana

GLScene je 3D engine za Delphi zasnovan na OpenGLu. Sa njim je moguce vrlo brzo kreirati zanmljive 3D scene, aplikacije, igre... U sebi trenutno sadrzi 3D, script, physic i sound engine... takodje sadrzi rutine za lak rad sa misem, dzojstikom, tastaturom sto ga cini vrlo dobrim alatom za pravljenje igara u Delphiu.
Hompage: http://glscene.sourceforge.net/index.php

Najnoviju verziju mozete skinuti uz pomoc TortoiseCVS. To je program koji radi preko CVS protokola. Mozete ga skinuti sa http://www.tortoisecvs.org/index.shtml , a uputstvo za skidanje GLScene (CVS) mozete pronaci na http://sourceforge.net/cvs/?group_id=29749

Prilikom instalacije bitno je da u Delphi IDE dodate putanje do svih foldera u kojima se nalaze source fajlovi GLScene u Library path inace necete biti u mogucnosti da ih koristite. Kad to uradite u foderu DelphiX (gde je X verzija vaseg Delphia) cete naci pakete komponenti:

GLScene - komponente za rad sa 3D objektima
GLCg - komponente za rad sa Cg shaderima (morate imati instaliran NVidia Cg toolkit da bi mogli da instalirate ove komponente)*
GLSDL - rad sa SDL engineom (ova komponenta nije potrebna za rad sa GLScene i ja je licno nikad nisam koristio)*
GLSS_BASS - sound library BASS*
GLSS_FMOD - sound library FMOD*
GLS_ODE - physic engine ODE*
GLS_DWS - script engine Delph Web Script*
GLS_Python - script engine Python*

* Da bi ove komponente radile morate instalirati druge pakete. SDL, ODE, BASS, FMOD idu zajedno sa GLScene fajlovima. To su obicni Dll fajlovi koje je samo potrebno kopirati u Windows\System32 folder i to je to. DWS mozete skinuti sa http://www.dwscript.com/ Za Python jos ne znam gde mogu da ga pronadjem, ali se bez te komponente moze jer imate DWS Smile Za detaljnija uputstva o instalaciji pogledajte homepage GLScene.

Kada je instalacija zavrsena dolazi na red i probanje komponenti (moj omiljeni deo Wink ). Za pocetak cemo napraviti jednu loptu, svetlo i kameru koja gleda u loptu.
Prvo cemo komponentu GLScene sa GLScene grupe da postavimo na formu. Ta komponenta ce nam sluziti za kreiranje scene. Sledeca je na redu komponenta GLSceneViewer. Ona je zaduzena za iscrtavanje scene na nasoj formi. Ove dve komponente su skoro uvek obavezne. Sada postavimo GLSceneViewer1.Align na alClient tako da se GLSceneViewer1 rasiri preko cele forme.
Sada kliknite dva puta na GLScene komponentu (ili desni klik pa Show Scene Editor) i tako cete otviriti editor scene



Ovde cemo dodavati nase objekte.
Prvo sto cemo dodati je kamera. Desnim klikom na Cameras u Scene Editoru otvorice nam meni i tu kliknemo na Add camera. Kamera je dodata sada nam samo jos preostaje da u GLSceneVieweru postavimo Camera proerty na kameru koju smo sada kreirali. Klik na GLSceneViewer (nalazi se preko cele forme) i u Object Inspectoru pronadjemo property Camera i vrednost postavimo na GLCamera1. Ako ne postavimo kameru tada se na GLSceneVieweru nece nista videti pa... cim kreirate kameru odmah je postavide ovde Wink
Sada dodajemo i nasu lopticu... desni klik na Scene Objects u Scene Editoru, zatim Add Object->Basic Geometry->Sphere. Lopta je dodata, ali se ne vidi!? Problem je sto se i lopta i kamera nalaze na koordinatama 0,0,0 pa kamera ne moze da vidi loptu. Sada cemo pomeriti loptu ispred kamere tako sto cemo postaviti Position property lopte na 0,0,-3. Sada se lopta vec vidi :)Primecujete da je lopta crna...



To je zato sto nismo nigde postavili svetlo! Da bi i to resili dodacemo i jedan izvor svetla. Desni na Scene Objects pa izaberite LightSource. Cim smo dodali svetlo lopta je osvetljena Smile Po defaultu novo kreirani objekti su sivi i zbog toga je lopta siva.



To je u sustini princip rada GLScene... dakle dodajemo objekte u Scene Editoru, podesavamo im poziciju, velicinu, boju...
Kasnije cemo uraditi i primere u kojima cemo pomerati objekte po sceni, dodavati evekte, itd...
Za sad eksperimentisite malo sa osnovinm stvarima Smile
Srecno!!!

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 16:18

Hello!!! Smile
Kao sto rekoh sada cemo uraditi jos jedan jednostavan primer. I ovog puta pocinjemo stavljanjem GLScene i GLSceneViewer komponenti na formu. Sledece je na redu dodavanje kamere i postavljanje Camera property GLSceneViewera na nasu novo kreiranu kameru. Dodacemo i jedno svetlo kao u proslom primeru. Sledece na redu je dodavanje kocke. Kocka se dodaje kao i lopta. U Scene Editoru desni klik na Scene Objects->Add Object->Basic Geometry->Cube. Postavicemo poziciju kocke na 0, 0, -4. Sada cemo dodati i jednu loptu i nju postaviti na 0, 1.5, -4 tako da ce se videti iznad kocke kao na slici



Trenutno kocka i lopta nisu povezani... to cemo prikazati uskoro. Pre nego sto pocnemo da pomeramo objekte po sceni dodacemo jos jednu komponentu. Komponente se zove GLCadencer i nalazi se u GLScene grupi. Ova komponenta ima event koji se poziva prilikom svakog renderovanja. Znaci pre nego sto se scena iscrta izvrsi se nas event i tako svaki put. Sto se scena brze iscrtava to se nas event brze poziva. Tako cemo na brzim racunarima dobiti lepu, glatku animaciju, a na losijim nece sve biti usporeno nego ce jednostavno neki delovi animacije biti "preskoceni" (seckanje). Ova komponenta ima jedan lep property koji se zove Mode. Taj proerty odredjuje kad ce se nas event pozivati. Po defaultu stoji na ASAP (as soon as possible) sto nam daje najveci frame-rate, ali i 100% zuzeca procesora, zatim imamo ApplicationIdle i u tom modu se event pokrece samo kada aplikacija nema vise window poruka da obradjuje sto malo smanjuje frame-rate, ali i smanjuje opterecenje procesora. Na kraju imamo mod Manual i u tom modu GLCadencer nece pozivati event sve dok mi samo ne pozovemo GLCadencer.Progress. Ako neko bas jako zeli da sto manje opterecuje procesor postoji i property SleepLength. Dovoljno je postaviti ga na 1 i procenat zauzeca procesora ce drasticno pasti. Kada je SleepLength <> -1 tada GLCadencer u svojoj petlji poziva Sleep(SleepLength) cime prekida rad programa na odredjen broj milisekundi. Ja licno volim da imam sto vise frejmova u sekundi pa su mi default vrednosti sasvim ok.
Znaci postavili smo GLCadencer na formu i pre nego sto mozemo da ga koristimo treba da podesimo Scene property. Taj property odredjuje scenu za koju je nas GLCadencer zaduzen. Postavicemo ga na GLScene1. Sada nam ostaje da namisemo proceduru za OnProgress event.
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); var   X: Single; begin   X := Sin(newTime) * 2;   GLCube1.Position.SetPoint(X, 0, -4); end;
OnProgress event nam osim standardnog Sender (ko je pozvao event) daje jos dva podatka, deltaTime i newTime. DeltaTime je vreme u sekundama izmedju proslog poziva OnProgress eventa i trenutnog, a NewTime je vreme u sekundama od prvog do trenutnog poziva ovog eventa ili jednostavno receno od kad je GLCadencer.Enabled postavljen na True do sad. U nasem slucaju pomeracemo kocku po X osi po obicnoj sinusnoj funkiciji u zavisnosti od vremena koliko je GLCadencer aktivan.
Sada pokrenite program i videcete kako kocka klizi levo desno dok lopta stoji nepomicna. Sada cemo postaviti loptu tako da bude joj pozicija zavisi od pozicije koscke. Otvorite Scene Editor, kliknite na loptu i prevucite je preko kocke. Trebalo bi da ih postavite ovako



Kad ste to uradili lopta se odjednom pomerila u nazad iako nismo menjali njenu poziciju.



To je zato sto sada property Position za loptu predstavlja poziciju lopte u odnosu na kocku. Posto se kocka nalazi na 0, 0, -4, a koordinate lopte u odnosu na kocku su 0, 0, -4 to nam govori da se lopta sada nalazi na 0, 0, -8 (pozicija kocke + pozicija lopte). Ako sada pokrenemo program videcemo da se i kocka i lopta pokrecu iako menjamo poziciju samo kocke. Ovo je vrlo korisno znati koristiti pa eksperimentisite malo Smile

Toliko za danas!

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 16:21

Do sad su svi objekti koje smo kreirali bili sivi... sada cemo malo da im menjamo boje Smile
Pocinjemo kao i uvek... GLScene, GLSceneViewer, Camera, LightSource (secate se da je objekat bio skroz crn bez svetla... zato nam je vrlo bitno da imamo svetlo na sceni ako hocemo da vidimo boje) i jedna lopta na koordinatama 0, 0, -4. Sad imamo scenu kao u prvom primeru (mnogo brze i lakse nego na pocetku, zar ne Wink ).
Svaki objekat ima 4 vrste boje: Ambient, Diffuse, Emission i Specular.
Ambient i Diffuse se najcesce koriste. Kada postavimo svetlo na scenu ono svetli odredjenom bojom (koju mi definisemo).
Ambient vrednost je boja svetla koje se nalazi na celoj sceni... nije bitno da li je objekat obasjan izvorom svetlosti, da li je preblizu ili predaleko... ako je Ambient boja podesena na zeleno tada je cela scena obasjana zelenom bojom.
Diffuse svetlost je slicna kao Ambient samo sto zavisi od vrste svetlosnog izvora. Mi smo uvek samo postavljali LightSource bez promene parametara. Po defaultu svetlo je tipa Spot. Takvo svetlo je kao baterijska lampa... svetli u odredjenom smeru i sve sto je iza nje ili previse sa strane nije osvetljeno. Postoje jos dva tipa svetla. Omni... to je kao luster... svetli suda oko sebe... nema neki odredjen pravac. Parallel... hmmm... to je kao svetlost sa sunca... dolazi iz velike daljine i pod odredjenim uglom pada na sve objekte. Pravac i smer kod Parallel i Spot tipova svetla se definise u SpotDirection property.
Emission je boja svetlosti koja isijava iz objekta. Kad imate beli luster sa crvenom lampom i onda se vidi kao da je je i luster crven.
Specular je boja odsjaja na objektu. Kada je recimo bilijarska kugla jako izglancana onda se na njoj vidi odsjaj svetla.
Svi ovi svetlosni efekti mogu da se koriste zajedno. Jedino emission boja ne zavisi od izvora svetla dok sve ostale boje zavise. Ako je recimo diffuse boja svetla cisto crvena, a diffuse boja objekta cisto plava objekat ce izgledati crn jer nema ni mali delic svetla plave boje. Takva je situacija i sa ambient i specular bojama. Mozda sada sve zvuci malo konfuzno, ali ako budete malo ekperimentisali sa bojama sve ce vam biti jasno.
Jos jedna stvar... ambient i diffuse boja se u 99.99% slucajeva postavljaju na istu boju jer obe boje predstavljaju boju materijala objekta. Ambient vrednost svetla se postavi na neku tamno sivu tako da i ako svetlo nije upereno u objekat njegova boja se ipak malo nazire, a diffuse boja svetla se postavlja na cisto belu i objekti direktno ispred svetla se vide u svojoj prirodnoj boji.
Dosta pricanja... hajde da ofarbamo nasu lopticu Smile
Posto nismo menjali poziciju svetla ono se nalazi na 0, 0, 0, a njen pravac koji takodje nismo dirali je 0, 0, -1. Posto se nas objekat nalazi na 0, 0, -4 on se nalazi ispred svetla i zato je obasjan. Hajde da mu promenimo boju u plavo.
Boja (i neke druge stvari) se definisu u Material property. Kliknite na '...' i otvorice se material editor.



Ovde imam dosta opcija. Na vrhu mozemo da biramo da li cemo podesavati boju za prednju stranu poligona ili za zadnju (uglavnom se zadnja strana poligona ne prikazuje pa nije ni bitno sta cete tu podesiti) i mozemo podesavati texturu za objekat. Texture cemo ostaviti za kasnije. Vidimo skale za podesavanje boja i uz pomoc njih cemo naterati nasu loptu da poplavi Wink Imamo opciju da izaberemo kako ce se nas objekat iscrtavati (polygon mode). Po defaultu objekat se iscrtava kao puno telo, ali mozemo podesiti da se iscrtavaju samo ivice ili samo tacke koje definisu ivice (probajte sva tri moda i bice vam jasno sta koji radi). Zatim imamo Shininess klizac... ta osobina odredjuje koliko je objekad "izglancan" i koliki ce biti odsjaj specular boje. Poslednja opcija koja odredju kako ce objekat biti iscrtan je Blending mode... ako je mod postavljen na Opaque tada se objekat iscrtava svojom bojom i to je to. Ako je podesen na Transparency tada Alpha vrednost boja utice na providnost objekta, sto je Alpha manje to je objekat providniji. Additive mod iscrtava objekat tako sto se bojama objekta dodaju boje objekata koji su iza njega... ovaj mod morate isprobati da bi vam bilo malo jasnije sta se tu tacno desava.
Za sad hajde da podesimo ambient i diffuse boje objekta (front) na plavo. Kada kliknemo na Ok primeticete da se lopta obojila u plavo.



Vrlo jednostavno Smile
Hajde da dodamo i emission i specular boje. Postavimo emission green komponentu na 200. Sada ce nas plavi objekat izgledati kao da nesto zeleno svetli iz njega. Sad cemo jos i da mu nabacimo crvenu "tufnu". Specular boju postavimo na cisto crvenu i da se lopta ne bi bas jako sjajila postavimo Shininess na 5. Kliknimo Ok i nasa lopta vise nije samo plava... Smile Sva je nekako cudna Wink



Experimentisite malo s bojama. Probajte da postavite neki drugi blending mode i da menjate alpha vrednost.
U sledecem primeru cemo pokazati kako se lako textura postavlja na objekat kao i koriscenje Material Library komponente.

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 16:31

Uglavnom nije bas najbolja ideja da se za za svaki objekat materijal (boja) postavlja kao sto sam objasnio u proslom primeru. Kada bi imali 1000 lopti koje treba da budu plave i ako bi za svaku postavili boju kao sto sam prosli put objasnio GLScene bi napravio 1000 materiala (za svaki objekat po jedan) koji su prakticno isti i prolikom renderovanja objekata bi svaki put menjao 1, 2, 3,... 1000 materijal bez potrebe sto bi dovelo do vrlo velikog usporenja programa. Da bi se to izbeglo postoji komponenta GLMaterialLibrary. Ona je vrlo korisna jer je u njoj moguce definisati JEDAN material koji ce posle koristiti neogranicen broj objekata. Nekom ce mozda ovo biti bezveze jer ako se promeni taj material svi objekti koji ga koriste ce takodje biti promenjeni, a nekom ce to biti prednost jer nece morati da menja boje svakom objektu posebno. Ovog puta cemo koristiti Material Library i necemo samo postavljati boju za objekte nego i texturu. Textura je slika koje je "nalepljena" na objekat da bi izgledao kao da je od drveta, plastike, metala ili nekog drugog materijala.
Za pocetak postavimo na formu GLScene, GLSceneViewer, GLCadencer i GLMaterialLibrary. Postavimo u sceni kameru (0, 0, 0), svetlo (0, 0, 0) i dve lopte (2, 0, -5) i (-2, 0, -5) ove lopte ce nam sluziti kao modeli. Ne zaboravite da GLSceneViewer1.Camera postavite na kameru koju smo kreirali i GLCadencer.Scene na GLScene1 (ovo vise necu da spominjem).
MaterialLibrary ima dva propertya koja su nam zanimljiva... to su Material i TextrePaths. TexturePaths su putanje po kojima ce MaterialLibrary traziti slike ako napisete naziv fajla bez putanje (npr. "Slika.jpg"). Property Material sadrzi sve materiale koji su kreirani. Hajde da kreiramo jedan material. Kliknite na '...' u Material property i otvorice vam se mali prozorcic u kojem mozete dodavati i brisati materiale.



Dodajmo jedan material pritiskom na Add New dugme. Sada u Object Inspectoru vidimo osobine materiala koji smo kreirali. Imammo Material (isto kao i Material property kod objekata... tu cemo definisati izgled materiala), Name (naziv materiala... uvek je dobra ideja da nazovete material kako bi kasnije mogli lakse da ga pronadjete), Shader (ovde mozemo definisati mali programcic kojice iscrtavati material... primeri su BumpShader (povrsina izgleda rapavo), CelShader (izgleda kao crtani film)...), Texture2Name (moguce je dve texture stopiti u jednu i time dobiti neki novi izgled... ovde se daje ime drugog materiala koji ce se koristiti za stapanje sa ovim), TextureOffset (ako je textura velika ili ako ne zelimo da uzmemo sliku od pocetka texture ovde mozemo podesiti koliko ce textura na materialu biti pomerena u odnosu na pravu texturu), TextureScale (ako zelimo da se textura ponovi vise puta na objektu ovde to definisemo).
Hajde da podesimo material i dodamo texturu. Klik na '...' u Material property. Otvara nam se vec poznat prozor



Postavimo Ambient i Diffuse boju na cisto belo i kliknimo na Texture kako bi smo dodali sliku. Sada na vidimo sledece:



Sada mozemo da izaberemo sliku koja ce biti na objektu... to radimo uz pomoc Image opcije. Izabracemo ovu sliku



http://www.geocities.com/srki_82/Tutorial/GLScene/Tut4Pic3.JPG

Ako se nekom vise svidja neka druga slobodno moze da je izabere.
Od opcija su nam na raspolaganju sledece stvari... ImageAlpha... svaka slika moze u sebi da sadrzi i alpha kanal cime odredjuje providnost objekta na koji je postavljena. Ako je ImageAlpha na Default koristi se alpha kanal iz slike. Ako je podesen na AlphaFromIntensity ili Luminance sto je slika svetlija manje se providi, a ako je postavljen na SuperBlackTransparency tada su sve crne povrsine providne.
Sledece opcije su Min i Mag filteri. GLScene kreira manje ili vece slicice od one koje smo mi dali ako je objekat mnogo manji ili veci od njenih dimenzija. Nacin na koji skuplja i siri sliku zavisi od ovih opcija. Uvek sam bio zadovoljan default vrednostima pa nisam mnogo zalazio u ostale mogucnosti, ali ako neko vidi da mu se textura mnogo zamuti moze da proba da postavi druge vrednosti.
Sledeca opcija nam je Texture Mode... ona odredjuje kako ce textura da se "stopi" sa bojama materijala. Decal i Replace jednostavno zanemaruju boju objekta i iscrtavaju samo texturu. Modulate promeni boju texture tako da "vuce" na boju koju smo definisali dok Blend racuna srednju vrednost izmedju definisane boje i boje texture. Mi cemo postaviti Texture mode na Modulate. Texture Warp odredjuje da li ce textura da se ponavlja ako je potrebno da prekrije ceo objekat (u obcijama moze da se izabere da li i u kojim pravcima da se dozvoli ponavljanje... po defaultu je da moze u svim pravcima).
Na kraju imamo checkbox Disabled koji odredjuje da li da se textura uopste vidi. Iskljucite taj checkbox i u preview cete videti nasu texturu Smile
Kliknite na Ok. Jos jedna sitnica... u Name property upisacemo "Drvo". Eto... zavrsili smo nas material... sad da ga postavimo na loptice Smile



Kao sto vidite... kliknite na mali plus pored Material property za loptu i u MaterialLibrary izaberite GLMaterialLibrary1 (komponenta koju smo stavili na formu i u kojoj su nasi materiajli). Zatim kliknite na '...' u LibMaterialName property i izaberite material "Drvo" i loptica vec lepse izgleda Smile Sad to isto uradite i za drugu loptu.
Jedna vrlo bitna stvar!!!
Pre nego sto pokrenete program morate u Uses listu dodati unite koji omogucavaju ucitavanje slika koje smo koristili za texture. Za BMP slike nema potrebe nista da se dodaje dok za JPG treba da se doda JPEG unit, za TGA treba TGA unit...

Kada smo dodali JPEG u uses pokrecemo program i vidimo loptice Smile



Da bi smo dokazali da obe lopte koriste isti material malo cemo se poigrati s njim. U GLCadencer cemo postaviti OnProgress event na
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); var   C: Single; begin   C := Sin(newTime) * 0.5 + 0.5;   with GLMaterialLibrary1.LibMaterialByName('Drvo') do   begin     Material.FrontProperties.Ambient.Red := C;     Material.FrontProperties.Diffuse.Red := C;     TextureScale.SetPoint(C, C, C);   end; end;
Kao sto vidite menjamo material u MaterialLibrary i obe lopte menjaju svoju boju Smile
Toliko za sada... ako budem imao vremena mozda napisem jos nesto za sad.
Vi slobodno experimentisite i posaljite kod ako napravite neki zanimljiv primer!
Poz!!!

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 16:38

Mogli bi smo umesto kocki i lopti da koristimo neki 3D model... bilo bi stvarno bezveze kad bi bili ograniceni samo na osnovne oblike. Ovog puta cemo napraviti mali programcic za pregled 3DS fajlova. 3DS su fajlovi koje pravi 3D Studio... oni u sebi sadrze podatke o izgledu objekta i podatke o materijalima. Sa GLScene je vrlo lako ucitavati 3D modele... GLScene ima podrsku za razne fajlove kao sto su 3DS, Quake 2 i 3 modele, HalfLife modele, OBJ fajlove, Quake nivoe... pa da pocnemo Smile
Pacicemo na formu GLScene, GLSceneViewer, GLMaterialLibrary (ovde ce se ucitati materiali za 3d objekat), MainMenu (za meni za ucitavanje fajla) i OpenDialog. Na scenu cemo postaviti sledece stavke: kameru i svetlo (svetlo prevucite tako da mu kamera bude parent i da pozicija svetla zavisi od pozicije kamere... gde god da se nalazi kamera i svetlo ce ici za njom) i jedan FreeForm (Screen Objects->Add Object->Mesh Objects->FreeForm). FreeForm je objekat u koji ce biti ucitan nas 3DS fajl. Da bi GLScene znao gde da stavi materijale vezane za FreeForm moramo FreeForm.MaterialLibrary postaviti na GLMaterialLibrary1 koji smo vec stavili na formu. Jos malo i zavrsili smo. Postavicemo kameru na 0, 0, 200, a FreeForm ostaviti na 0, 0, 0. Uradicemo nesto sto nismo radili do sad... postavicemo GLCamera.TargetObject property na FreeForm1 sto ce naterati kameru da bude uvek okrenuta prema FreeForm objektu. Tako mozemo pomerati i FreeForm i kameru bez bojazni da cemo izgubiti objekat iz vida. Sada nista ne vidimo na formi jer 3DS fajl mozemo da ucitamo samo u runtimeu i zato cemo napraviti funkciju za ucitavanje. U MainMenu dodajte sledece stavke
Load 3DS file
-
Exit
Za Exit postavite da izadje iz programa (Application.Terminate), a za Load 3DS file napisite sledece
procedure TForm1.Load3DS1Click(Sender: TObject); var   S: Single; begin   if OpenDialog1.Execute then   begin     GLMaterialLibrary1.Materials.Clear;     GLFreeForm1.LoadFromFile(OpenDialog1.FileName);     S := 100 / GLFreeForm1.BoundingSphereRadiusUnscaled;     GLFreeForm1.Scale.SetVector(S, S, S);     GLFreeForm1.ResetRotations;   end; end;
Kao sto vidite nema puno koda, a ovo radi ceo posao oko ucitavanja 3DS fajla Smile
Prvo sto uradimo je praznjenje GLMaterialLibrarya jer je moguce da smo pre ovog vec ucitali neki objekat i ne bi zeleli da nam u ostanu stari materiali. Sledeca stvar koju radimo je ucitavanje fajla. Za to nam je potrebaj samo jedan red GLFreeForm1.LoadFromFile(OpenDialog1.FileName);. GLScene je toliko dobar da skoro sve uradi umesto nas. Posle ovog poziva u FreeForm se nalazi nas 3D objekat. Posto objekat moze da bude ogroman ili previse mali sledeca stvar koju radimo je postavljanje odgovarajuce velicine. GLFreeForm1.BoundingSphereRadiusUnscaled nam daje precnik lopte koja okruzuje ceo objekat i na osnovu nje cemo podesiti velicinu objekta da moze da stane u loptu precnika 100. Kamera ima DephOfView property. On odredjuje koliko daleko kamera moze da vidi. Po defaultu vrednost je 100, ali posto ce kraj naseg objekta biti dalje od 100 od nase kamere moracemo da povecamo ovu vrednost kako bi sve lepo videli. Stavicemo vrednost na 1000. Kada smo postavili odgovarajucu velicinu objekta ostaje nam jos samo da vratimo osnovni polozaj objekta (kasnije u kodu cemo moci da ga rotiramo). I to je to... u par redova koda mozemo da ucitamo bilo koji 3DS fajl.I jos jednom da napomenem... ako 3d objekat koristi neke slike osim BMP za texture moramo dodati unite koji ce "objasniti" Delphiu kako da ih ucita.



Sad nam ostaje jos da sredimo rotiranje objekta... to se takodje vrlo lako radi. Bice nam potrebne 2 globalne promenljive mX i mY pa ih dodajte. Obe su tipa Integer. U OnMouseMove eventu GLSceneViewera napisite sledece
procedure TForm1.GLSceneViewer1MouseMove(Sender: TObject;   Shift: TShiftState; X, Y: Integer); begin   if ssLeft in Shift then     GLCamera1.RotateObject(GLFreeForm1, mY - Y, mX - X);   mY := Y;   mX := X; end;
Zajedno sa kodom saljem i jedam mali 3DS fajl kako bi mogli da isprobate program. To je jedan cup... i primeticete da ima delova koji se "provide" bez razloga. To je zato sto u te "providne" delove gledamo s "pogresne strane". Secate se da smo mogli da zadajemo boje za Front i Back u Material Editoru... e pa ovi delovi koji se ne vide se ne vide zato sto ih gledamo sa Back strane. Po defaultu GLSceneViewer uopste ne prikazuje te Back strane. Da bi smo ga "naterali" da ih prikazuje moramo GLSceneViewer.Buffer.FaceCulling postaviti na False. Ako sada pokrenemo program videcemo da se sve lepo vidi Smile
To je sve... mX i mY pamte poslednju poziciju misa kako bi znali za koliko treba da rotiramo objekat, a RotateObject sredjuje rotaciju. Prilicno jednostavno Smile
Eto... u par linija koda imamo jednostavan viewer za 3ds fajlove. Sad vec znate mnogo vise nego sto sam ja znao kad sam poceo da radim sa GLScene Smile
Pa... sta bi voleli da naucite sledece?

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 16:46

Ahhh... bas je lepo kada te puste ranije s posla Smile Prosto uzivam... bazencic, pivce, muzika, lap-top... samo da ga ne ispustim u vodu Smile Kao sto sam obecao red je da napravimo nasu prvu malu igru. Ovog puta cemo sve sto smo naucili da stavimo u jedan program i videcemo kako je moguce kreirati i brisati objekte na sceni u runtime.
Pocecemo tako sto cemo pobacati GLScene, GLSceneViewer, GLMaterialLibrary i GLCadencer na formu i kameru i svetlo na scenu. Sad dodajmo GLDummyCube na scenu 0, 0, -4 (Scene Objects->Add object->DummyCube) i nazovimo je Tabla. Ovaj objekat je prilicno koristan. Na sceni se vidi kao providna kocka cije su ivice iscrtane isprekidanom linijom, a kada se program pokrene onda se ne vidi. Neko se moze zapitati sta ce nam objekat koji se ne vidi... secate li se kada sam pokazao kako je moguce hijerarhijski postavljati objekte. E, DummyCube se koristi uglavnom za to. Ako postavimo nekoliko lopti, kocki ili bilo kojih objekata da njihove pozicije zavise od DummyCube, pomeranjem i rotiranjem DummyCube svi ti objekti ce se takodje kretati. U kodu cete videti malo bolje o cemu pricam.



Sada nam je cilj da napravimo plocicu koja ce se okretati. Treba da ima jednu stranu obojenu jednom dok su sve ostale obojene drugom bojom. Problem je sto GLCube to bas i ne moze da uradi... ali zato 2 GLCube mogu Smile Dodajmo jednu kocku i postavimo je u DummyCube. Posto pozicija nase kocke sad zavisi od DummyCube znaci da ce se i nasa kocka naci na 0, 0, -4.
GLCube nam dozvoljava da izaberemo koje stranice kocke ce iscrtavati (Parts property) i mi cemo iskljuciti Back i tada strana koja je okrenuta od nas nije iscrtana. Sada cemo dodati jos jednu kocu u DummyCube i njoj cemo u Parts postaviti da iscrtava SAMO Back stranu tako da ce ona popuniti deo koji prva kocka nije iscrtala. I sada mozemo jednu stranu da obojimo u jednu, a ostale u drugu boju Smile Samo postavimo materijale kocki na razlicite boje (recimo jedna strana na crveno, a ostale na plavo). Problem je sto sad ne mozemo da vidimo koje je boje deo okrenut od nas... zato cemo malo da zarotiramo nase kocke. Umesto da rotiramo jednu i drugu sve sto cemo uraditi jeste postavljanje ugla za DummyCube. Postavimo TurnAngle na 140 i sta vidimo... obe kocke su zarotirane i sada vidimo i zadnju stranu. Ovaj nacin cemo koristiti u igri da postavljamo i rotiramo polja.



Pa... hajde da pocnemo... obrisimo iz scene sve osim kamere, svetla i DummyCube (koju smo nazvali Tabla). Vratimo TurnAngle Table na 0. I spremni smo da pocnemo Smile
Da bismo uopste mogli da igramo prvo moramo postaviti polja. Napravicemo nam jednu proceduru koja ce obrisati sva postojeca polja na Tabeli i postaviti nova. Proceduru cemo dodati recimo u public deo nase forme
type   TForm1 = class(TForm)     GLScene1: TGLScene;     GLSceneViewer1: TGLSceneViewer;     GLMaterialLibrary1: TGLMaterialLibrary;     GLCadencer1: TGLCadencer;     GLCamera1: TGLCamera;     GLLightSource1: TGLLightSource;     Tabla: TGLDummyCube;   private     { Private declarations }   public     { Public declarations }     procedure NovaIgra;   end;
Prva stvar koju cemo uraditi je brosanje postojecih polja. Posto ce sva polja biti u DummyCube koju smo nazvali Tabla mozemo ih obrisati sve pozivom samo jedne funkcije
Tabla.DeleteChildren;
Ovo ce obrisati sve objekte koji se nalaze u Tabla objektu. Da nismo koristili DummyCube morali bismo da cuvamo polja u nekom nizu pa da ih brisemo jedno po jedno dok ovako GLScene radi sve umesto nas.
Sledece sto treba da uradimo je da dodamo nova polja kao sto smo vec probali u designtime. Dodacemo u var deo procedure dve promenljive
var   Dummy: TGLDummyCube;   Cube: TGLCube;
One ce cuvati objkte koje budemo kreirali. Kad smo pravili polje prvo smo postavili DummyCube... to cemo uraditi i sad
Dummy := TGLDummyCube.CreateAsChild(Tabla);
Kada ovako kreiramo objekat on ce se nalaziti u objektu koji navedemo prilikom poziva CreateAsChild... znaci nas Dummy ce se nalaziti u objektu Tabla. Ako zelimo da kreiramo objekat koji nije vezan za neki drugi onda umesto CreateAsChild pozivamo samo Create.
Kad smo napravili Dummy treba da dodamo kocku koja ce iscrtavati sve sem Back strane. Da polje ne bi izgledalo previse "kockasto" malo cemo da spljostimo nasu "kocku". To bi izgledalo ovako
Cube := TGLCube.CreateAsChild(Dummy); Cube.CubeDepth := 0.2; Cube.Parts := Cube.Parts - [cpBack];
Ovaj deo svih polja ce biti iste boje pa bi bilo zgodno napraviti material u GLMaterialLibrary koji ce drzati boju za njih. Dodajmo jedan material proizvoljne boje i nazovimo ga "Pozadina". U designtime znamo kako se postavlja material objektima, a evo kako to ide u runtime
Cube.Material.MaterialLibrary := GLMaterialLibrary1; Cube.Material.LibMaterialName := 'Pozadina';
Ostaje nam jos samo da dodamo i obojenu stranu. Posto cemo praviti 12 polja to je po 6 parova koji ce imati razlicitu boju pa hajde da dodamo jos 6 materijala razlicite boje u GLMaterialLibrary i nazovimo ih 0, 1, 2, 3, 4 i 5. I obojena strana je skoro gotova
Cube := TGLCube.CreateAsChild(Dummy); Cube.CubeDepth := 0.2; Cube.Parts := [cpBack]; Cube.Material.MaterialLibrary := GLMaterialLibrary1; Cube.Material.LibMaterialName := '0';
To bi za sad bio deo koji inicijalizuje igru. Cela funkcija bi za sada izgledala ovako
procedure TForm1.NovaIgra; var   X, Y: Integer;   Mat: array[0..11] of String;   Dummy: TGLDummyCube;   Cube: TGLCube;   // Izabira material za polje   function IzaberiMaterial: String;   var     I: Integer;   begin     I := Random(12 - (X + (Y * 4)));     Result := Mat[I];     Mat[I] := Mat[11 - (X + (Y * 4))];   end; begin   // Brisemo sve objekte u Tabla   Tabla.DeleteChildren;   // Postavljamo boje za IzaberiMaterijal   for X := 0 to 5 do   begin     Mat[X] := IntToStr(X);     Mat[X + 6] := IntToStr(X);   end;   // Postavljamo plocice na tablu   for Y := 0 to 2 do     for X := 0 to 3 do     begin       // Dodajemo jedan DummyCube koji ce drzati       // pozadinu (kocku bez jedne strane) i       // zadnju stranu koja je obojena       Dummy := TGLDummyCube.CreateAsChild(Tabla);       Dummy.Position.SetPoint(-3 + X * 2, -1.5 + Y * 1.5, 0);       // Dodajemo pozadinu       Cube := TGLCube.CreateAsChild(Dummy);       Cube.CubeDepth := 0.2;       Cube.Parts := Cube.Parts - [cpBack];       Cube.Material.MaterialLibrary := GLMaterialLibrary1;       Cube.Material.LibMaterialName := 'Pozadina';       // Dodajemo obojenu stranu       Cube := TGLCube.CreateAsChild(Dummy);       Cube.CubeDepth := 0.2;       Cube.Parts := [cpBack];       Cube.Material.MaterialLibrary := GLMaterialLibrary1;       Cube.Material.LibMaterialName := IzaberiMaterijal;     end; end;
Funkcija IzaberiMaterijal koristi Random da bi odredila boju polja... mogla je da se uradi i na drugi nacin. Ostaje nam da u Form.OnCreate podesimo da se ova procedura pozove i videcemo polja sa zadnje strane ako pokrenemo program



Sada... mogli bi da pocnemo da okrecemo plocice. Posto ce nam kasnije biti potrebno da znamo kad smo okrenuli dva polja dodacemo dve promenljive koje ce cuvati polja koja se okrecu i jos jednu promenljivu koja ce nam reci da li se polja okrecu u datom trenutku
var   Okretanje: Boolean;   Izabrana1, Izabrana2: TGLDummyCube;
Polje cemo da izaberemo u OnMouseDown eventu GLSceneViewera
procedure TForm1.GLSceneViewer1MouseDown(Sender: TObject;   Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var   Obj: TGLCube; begin   // Ako se nesto desava druge ploce ne mogu da se izaberu   if Okretanje then Exit;   Obj := TGLCube(GLSceneViewer1.Buffer.GetPickedObject(X, Y));   // Uzimamo u obzir samo kocke   if Obj <> nil then   begin     // Ako nismo izabrali ni jednu onda nam je ovo prva     // i pocinjemo sa okretanjem     if Izabrana1 = nil then     begin       // Parent od kocke koja je pozadina je DummyCube koja       // sadrzi i pozadinu i boju pa kada rotiramo       // DummyCube rotira se i pozadina i boja       Izabrana1 := TGLDummyCube(Obj.Parent);       Okretanje := True;     end     else     // Ako je prva vec izabrana pazimo da je nismo izabrali     // ponovo i ako nismo onda je izabrana i druga i     // pocinjemo sa okretanjem     if Izabrana1 <> Obj.Parent then     begin       Izabrana2 := TGLDummyCube(Obj.Parent);       Okretanje := True;     end;   end; end;
Ovde nema niceg komplikovanog... kada kliknemo na neku kocku proveravamo da li je vec izabrana i ako nije uzimamo vrednost iz Parent propertya sto nam daje objekat u kojem se nasa kocka nalazi tj. DummyCube koji smo kreirali. Tako cemo u Izabrana1 ili Izabrana2 imati DummyCube koji treba da okrenemo da bi se polje videlo. Polje cemo okretati u OnProgress eventu GLCadencera
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); begin   // Okrecemo izabrano polje   if Okretanje then   begin     // Vec smo izabrali drugo polje     if Izabrana2 <> nil then     begin       // Okrecemo ga       Izabrana2.TurnAngle := Izabrana2.TurnAngle + 500 * deltaTime;       // Okrenuo se na zeljenu stranu (ili mozda malo vise)       if Izabrana2.TurnAngle < 0 then       begin         // Resetujemo rotacije i postavljamo tacnu vrednost         // koju zelimo         Izabrana2.ResetRotations;         Izabrana2.Turn(180);         // Okretanje je zavrseno i pocinje pauza da igrac         // vidi sta je uradio         Okretanje := False;         // Ovde cemo proveriti da li su polja ista       end;     end     else     begin       // Okrecemo prvo polje       Izabrana1.TurnAngle := Izabrana1.TurnAngle + 500 * deltaTime;       if Izabrana1.TurnAngle < 0 then       begin         Izabrana1.ResetRotations;         Izabrana1.Turn(180);         Okretanje := False;       end;     end;   end; end;
I ovde nema niceg komplikovanog Smile mozete primetiti da sam vrednost sa kojom uvecavam ugao mnozio sa deltaTime. To je dobro zato sto ce i na racunaru koji ima 20 FPS i na onom koji ima 200 FPS rotacija da bude iste brzine. Pokrenimo program i probajmo da okrecemo polja.



Sada cemo da napravimo da igra malo zastane kada se okrenu dva polja, da proveri da li su ista i da ih vrati ako nisu. Za sad ce funkcija za proveravanje uvek govoriti da su polja razlicita da bi lakse objasnjavao kod. Dodacemo jos neke globalne promenljive
var   Pauza: Boolean;   Vracanje: Boolean;   Cekanje: Double;
Pauza je True ako smo u pauzi izmedju okretanja, Cekanje je vreme koji je ostalo do kraja pauze i Vracanje je True kada se polja vracaju u pocetnu poziciju. Pre nego sto pocnemo modifikovacemo pocetak dela koji nam vraca koja kocka je kliknuta i pocetak ce izgledati
if Okretanje or Pauza or Vracanje then Exit;
Tako igrac nece moci da okrece novo polje kad ne bi trebalo da moze.
Dodacemo proceduru Proveri u public deo nace forme i za sad napisati samo
procedure TForm1.Proveri; begin   Vracanje := True; end;
Malo cemo modifikovati i OnProgress event tako da reaguje na Vracanje i Pauzu
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); begin   // Cekamo da istekne neko vreme   if Pauza then   begin     Cekanje := Cekanje - deltaTime;     if Cekanje < 0 then       Pauza := False;   end   else   // Vracamo polja ako su nisu ista   if Vracanje then   begin     // Okrecemo polja     Izabrana1.TurnAngle := Izabrana1.TurnAngle + 500 * deltaTime;     Izabrana2.TurnAngle := Izabrana1.TurnAngle + 500 * deltaTime;     // Ako se polje okrenulo skroz (ili mozda malo vise)     // resetujemo rotacije i vracanje je gotovo     if Izabrana1.TurnAngle < 0 then     begin       Izabrana1.ResetRotations;       Izabrana2.ResetRotations;       Izabrana1 := nil;       Izabrana2 := nil;       Vracanje := False;     end;   end   else   // Okrecemo izabrano polje   if Okretanje then   begin     // Vec smo izabrali drugo polje     if Izabrana2 <> nil then     begin       // Okrecemo ga       Izabrana2.TurnAngle := Izabrana2.TurnAngle + 500 * deltaTime;       // Okrenuo se na zeljenu stranu (ili mozda malo vise)       if Izabrana2.TurnAngle < 0 then       begin         // Resetujemo rotacije i postavljamo tacnu vrednost         // koju zelimo         Izabrana2.ResetRotations;         Izabrana2.Turn(180);         // Okretanje je zavrseno i pocinje pauza da igrac         // vidi sta je uradio         Okretanje := False;         Pauza := True;         Cekanje := 0.5;         // Proveravamo da li su polja ista         Proveri;       end;     end     else     begin       // Okrecemo prvo polje       Izabrana1.TurnAngle := Izabrana1.TurnAngle + 500 * deltaTime;       if Izabrana1.TurnAngle < 0 then       begin         Izabrana1.ResetRotations;         Izabrana1.Turn(180);         Okretanje := False;       end;     end;   end; end;
Sve je sasvim jasno ovde... posle Vracanja podesavamo izabrana polja na nil tako da ponovo mozemo bez problema da biramo i prvo i drugo polje. Krenimo igru sada... skoro kao da je gotova... ostalo nam je jos samo saznamo da li su okrenuta polja ista i da ih sakrijemo ako jesu. Najlakse nam je da samo uporedimo materijale obojene strane. Dodacemo jos jednu globalnu promenljivu koja ce nam signalizirati ako treba da sakrijemo polja
var   Nestajanje: Boolean;
I sada ce nasa Proveri procedura izgledati ovako
procedure TForm1.Proveri; begin   // Ako su boje iste vreme je za "nestajanje" :)   Nestajanje :=   TGLCube(Izabrana1.Children[1]).Material.LibMaterialName =   TGLCube(Izabrana2.Children[1]).Material.LibMaterialName;   // Ako nisu ista onda ih vracamo   Vracanje := not Nestajanje; end;
Koristili smo property Izabrana1.Children. Ona nam vraca objekte koji se nalaze u Izabrana1. U nasem slucaju Izabrana1 je DummyCube koji sadrzi dve kocke. Prvu (index = 0) koja je okvir za polje i drugu (index = 1) koja je obojena strana. Na taj nacin mozemo doci do materijala obojene strane.
Ostalo nam je jos samo da sredimo OnProgress event da reaguje na Nestajanje
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); begin   // Cekamo da istekne neko vreme   if Pauza then   begin     Cekanje := Cekanje - deltaTime;     if Cekanje < 0 then       Pauza := False;   end   else   // Vracamo polja ako su nisu ista   if Vracanje then   begin     // Okrecemo polja     Izabrana1.TurnAngle := Izabrana1.TurnAngle + 500 * deltaTime;     Izabrana2.TurnAngle := Izabrana1.TurnAngle + 500 * deltaTime;     // Ako se polje okrenulo skroz (ili mozda malo vise)     // resetujemo rotacije i vracanje je gotovo     if Izabrana1.TurnAngle < 0 then     begin       Izabrana1.ResetRotations;       Izabrana2.ResetRotations;       Izabrana1 := nil;       Izabrana2 := nil;       Vracanje := False;     end;   end   else   // Sklanjamo polja sa table ako su ista   if Nestajanje then   begin     Izabrana1.Free;     Izabrana2.Free;     Izabrana1 := nil;     Izabrana2 := nil;     // Nema vise polja... nova igra!?     if Tabla.Count = 0 then       if Application.MessageBox('Nova igra?', 'Info', MB_YESNO) = ID_YES then         NovaIgra       else         Application.Terminate;   end   else   // Okrecemo izabrano polje   if Okretanje then   begin     // Vec smo izabrali drugo polje     if Izabrana2 <> nil then     begin       // Okrecemo ga       Izabrana2.TurnAngle := Izabrana2.TurnAngle + 500 * deltaTime;       // Okrenuo se na zeljenu stranu (ili mozda malo vise)       if Izabrana2.TurnAngle < 0 then       begin         // Resetujemo rotacije i postavljamo tacnu vrednost         // koju zelimo         Izabrana2.ResetRotations;         Izabrana2.Turn(180);         // Okretanje je zavrseno i pocinje pauza da igrac         // vidi sta je uradio         Okretanje := False;         Pauza := True;         Cekanje := 0.5;         // Proveravamo da li su polja ista         Proveri;       end;     end     else     begin       // Okrecemo prvo polje       Izabrana1.TurnAngle := Izabrana1.TurnAngle + 500 * deltaTime;       if Izabrana1.TurnAngle < 0 then       begin         Izabrana1.ResetRotations;         Izabrana1.Turn(180);         Okretanje := False;       end;     end;   end; end;
To je to Smile
Kada je potrebno da polje nestane mi ga samo unistimo i vise ga nema. Na kraju proverimo da li smo unistili sva polja i ako jesmo pitamo igraca da li zeli da igra ponovo.
Bez komplikovanih stvari moze da se napravi nesto zanimljivo.
U sledecem postu cemo malo promenuti kod pa ce polja polako da postaju sve providnija umesto sto samo odjednom nestanu.

Dopuna: 19 Jul 2005 16:52

I za kraj ove igre sacuvali smo "nestajanje" polja. Nestajanje cemo izvesti tako sto cemo alpha vrednos materiala polako smanjivati dok materijal ne postane potpuno providan. Da bi alpha vrednos uopste menjala providnost materiala moramo Blend mode postaviti na Transparency i zato postavimo to za sve materiale koje smo definisali osim za material Pozadina. Problem bi bio ako bismo menjali material Pozadina sva polja bi se menjala jer smo pri kreiranju kocku koja crta okvir polja povezali sa Pozadina materijalom. Zato cemo kreirati jos jedan material "FadeOut" i napraviti ga isto kao i Pozadina osim sto ce FadeOut imati Blend mode = Transparency. Dodacemo jos dve globalne promenljive u kojima cemo cuvati materijale koje menjamo
var   MatBoja, MatFade: TGLMaterial;
MatFade mozemo postaviti na "FadeOut" material prilikom kreiranja forme
procedure TForm1.FormCreate(Sender: TObject); begin   Randomize;   // Postavlja polja na tablu   NovaIgra;   // Uzima material za "nestajanje" polja   MatFade := GLMaterialLibrary1.LibMaterialByName('FadeOut').Material; end;
Materijal boje koja treba da nestane mozemo uzeti u funkciji Proveri
procedure TForm1.Proveri; begin   // Ako su boje iste vreme je za "nestajanje" :)   Nestajanje :=   TGLCube(Izabrana1.Children[1]).Material.LibMaterialName =   TGLCube(Izabrana2.Children[1]).Material.LibMaterialName;   // Ako nisu ista onda ih vracamo   Vracanje := not Nestajanje;   if Nestajanje then   begin     // Postavljamo material za nestajanje     TGLCube(Izabrana1.Children[0]).Material.LibMaterialName := 'FadeOut';     TGLCube(Izabrana2.Children[0]).Material.LibMaterialName := 'FadeOut';     // Uzimamo materijal za boju kako bismo mogli     // polako da ga napraimo providnim     MatBoja := GLMaterialLibrary1.LibMaterialByName(       TGLCube(Izabrana1.Children[1]).Material.LibMaterialName).Material;   end; end;
Kao sto vidite u proceduri proveri takodje postavljamo material FadeOut za okvire polja koje treba da nestanu. Tako cemo moci samo njih da menjamo.
Sada cemo jos samo da izmenimo deo OnProgress eventa za Nestajanje
if Nestajanje then begin   // Smanjujemo alpha vrednost tako da pozadina postaje sve   // providnija   MatFade.FrontProperties.Diffuse.Alpha :=     MatFade.FrontProperties.Diffuse.Alpha - 1 * deltaTime;   // Smanjujemo alpha vrednost tako da boja postaje sve   // providnija   MatBoja.FrontProperties.Diffuse.Alpha :=     MatBoja.FrontProperties.Diffuse.Alpha - 1 * deltaTime;   // Malo da vrtimo polja dok nestaju ;)   Izabrana1.Turn(1000 * deltaTime);   Izabrana2.Turn(1000 * deltaTime);   // Ako je sve nevidnjivo brisemo polja   if MatFade.FrontProperties.Diffuse.Alpha <= 0 then   begin     Izabrana1.Free;     Izabrana2.Free;     Izabrana1 := nil;     Izabrana2 := nil;     // Vracamo ponovo alpha na 1     MatFade.FrontProperties.Diffuse.Alpha := 1;     MatBoja.FrontProperties.Diffuse.Alpha := 1;     Nestajanje := False;     // Nema vise polja... nova igra!?     if Tabla.Count = 0 then       if Application.MessageBox('Nova igra?', 'Info', MB_YESNO) = ID_YES then         NovaIgra       else         Application.Terminate;   end; end;
Znaci sve sto radimo je polako zmanjivanje alpha vrednosti boje materijala i nase polje ce polako da nestaje. Dodao sam i malo rotiranja kako bi sve bilo zanimljivije Very Happy
Kada objekat skroz nestane (alpha <= 0) brisemo ga i vracamo alpha vrednos materijala za nestajanje ponovo na 1 kako bi bio spreman za sledece nestajanje.
I to je sve za ovu igru.
Mozete dodati da se meri vreme za koje je igra predjena, broj okretanja, highscore tabelu, izbor slika za polja (polja mogu da imaju texture)... slobodno experimentisite Smile
Sledece sto nas ceka su "ponasanja" objekata... teracemo objekat da se krece po nekoj putanji, vrtecemo tocak na osovini... videcu sta ce mi sve pasti na pamet Smile

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 16:59

Posle zanimljive igre vracamo se dosadnim sitnicama Smile Svaki objekta moze da ima asocirane efekte i osobine koje opisuju kako ce se ponasati na sceni. I efekti i osobine zahtevaju GLCadencer jer je on zaduzen za update. Sada cemo se pozabaviti osobinom Simple Inertia. Ova osobina nam dozvoljava da zadamo ugaonu brzinu (po x, y ili z osi objekta) ili brzinu kretanja u nekom pravcu i otpor koji ce na kraju zaustaviti kretanje. Potrebno je samo da podesimo te podatke i nas objekat ce poceti da se krece ili rotira (ili i jedno i drugo) i na kraju ce se zaustaviti. U ovom primeru cemo postaviti 2 cilindra (jedan ce biti osovina, a drugi tocak) i pritiskom na gore cemo dati gas (tocak ce se vrteti u napred), na dole cemo ici u nazad i na space cemo pritisnuti kocnicu. Pocnimo postavljanjem GLScene, GLSceneViewera i GLCadencera. Dodajmo kameru i svetlo, a zatim 2 cilindra. Prvi postavimo na 0, 0, -4. Postavimo TopRadius i BottomRadius na 0.1 da bi malo stanjili osovinu i na kraju postavimo RollAngle na 90 kako bismo je polozili. Drugi cilindar postavimo na 2, 0, -4. Postavimo RollAngle na 90, BottomRadius i TopRadius na 1, Height na 0.1 i Slices na 7. Tako cemo dobiti tocak sa desne strane. Postavili smo Slices na mali broj da bi lakse uocili kako se tocak okrece.



Sad cemo dodati osobinu nasem objektu. Kliknimo desnim na drugi cilindar (onaj koji nam predstavlja tocak) i izaberimo Add behaviour->Simple Intertia. Da bismo videli koje sve osobine ima nas objekat moramo kliknuti Show Behaviours/Effects dugme na vrhu Scene Editora.



Sada mozemo da kliknemo na osobinu koju smo dodali i da vidimo sta sve mozemo da podesimo.
DampingEnable - da li da otpor zaustavlja kretanje (ako pravimo planetu koja se neprestano okrece mozemo ovo iskljuciti)
Mass - masa objekta od koje zavisi kojom brzinom ce se zaustaviti
Name - ime osobine (kasnije je mozemo pronaci na osnovu imena ako je potrebno)
Pitch, Roll i Turn speed - brzine okretanja objekta oko osa
Rotation Damping - otpor prilikom okretanja
Translation Speed - brzina kretanja po x, y i z osi
Translation Damping - otpor prilikom kretanja
Otpor moze biti konstantan, linearan i kvadratni. Kada je konstantan onda se brzina dok je veca ili manja od nule priblizava nuli konstantnom brzinom u zavisnosti od mase.
Ako je otpor linearan sto je brzina veca veci je i otpor. Odnos izmedju brzine i otpora je linearan.
Ako je otpor kvadratni sto je brzina veca veci je i otpor, ali je ovog puta odnos izmedju brzine i otpora je kvadratni (otpor je vec za vece brzine nego kad je otpor linearan).
Za sad necemo menjati ovde nista jer cemo vrednosti postavljatiu runtime u zavisnosti od pritisnutih tastera.
Trebace nam Keyboard unit pa ga ubacite u uses listu. Kada se koriste osobine moramo dodati i GLBehaviours unit inace nas program nece raditi.
Postavimo sad OnProgress event
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); var   I: TGLBInertia; begin   I := GetOrCreateInertia(GLCylinder2);   if IsKeyDown(VK_UP) and (I.TurnSpeed < 1000) then   begin     I.TurnSpeed := I.TurnSpeed + 300 * deltaTime;   end;   if IsKeyDown(VK_DOWN) and (I.TurnSpeed > -500) then   begin     I.TurnSpeed := I.TurnSpeed - 100 * deltaTime;   end;   if IsKeyDown(' ') then     I.RotationDamping.Constant := 1000   else     I.RotationDamping.Constant := 50; end;
Funkcija GetOrCreateInertia proverava osobine objekta i kada naidje na Simple Inertia vraca nam je ili ako ta osobina ne postoji kreira je. Kao sto vidite nije bilo potrebno da kreiramo Simple Inertia u Scene Editoru jer bi nam GLScene kreirao tu osobinu kad bi je zatrazili, ali nije na odmet da znamo kako se osobine dodaju i u designtime Smile
Promenljiva I je tipa TGLBInertia koja sadrzi podatke o Simple Inertia osobini. Ostatak koda je prilicno jasan.
Kada smo pritisnuli gore i brzina je manja od 1000 povecavamo brzinu okretanja. Slicno vazi i kada pritisnemo dole.
Kada pritisnemo space povecavamo otpor (pritiskanje kocnice), a ako space nije pritisnut otpor stavljamo na malu vrednost kako bi se tocak zaustavio posle nekog vremena ako ne "dajemo gas" Smile
To je to... probajte da experimentisete malo... probajte da radite i sa Translation Speed...

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 17:04

Ovaj tutorial je nisam napisao ja. Napisao ga je Jovan Prokopović

Do sada smo koristili gotove objekte (Cube, Sphere ...) i ucitavali smo objekte napravljene u nekom 3D programu, ali nakad moze da nam zatreba da kreiramo objekt u toku izvrsavanja aplikacije (u zavisnosti od proracuna, akcija korisnika ...).

Zato u GLScene postoji nekoliko klasa koje nam to omogucavaju.

Sada cemo da napravimo mali program u kome kreiramo objekte koji nastaju revolucijom (rotacijom linije) oko jedne ose.

Na formu dodajte GLScene, GLSceneViewer, Camera, LightSource,
kameru postavite na (0,0,10) i jedan RevolutionSolid (Screen Objects>Add Object>Advanced geometry>RevolutionSolid).

Dodacemo jedan taster i jos dva editbox-a,

U OnClick tastera dodajemo kod cij je zadatak da dota nod (tacku) linije koju rotiramo.
procedure TForm1.Button1Click(Sender: TObject); begin   GLRevolutionSolid1.AddNode(StrToFloat(Edit1.Text), StrToFloat(Edit2.Text),0); end;
Kao Sto vidite vrlo jednostavno, Edit1 je X kordinata, Edit2 je Y kordinata, linija se rotira oko Y ose.

Sad pokrenite program i dodajte nekoliko nodova (naprimer (0,3), (2,2), (1,1), (2,0) ...), trebalo bi da vidite neki objekt.


Dodacemo i kretanje kamere oko objekta, postavicemo GLCamera.TargetObject property na GLRevolutionSolid1, devinisemo dve globalne promenljive mX i mY i dodamo ovaj kod.
procedure TForm1.GLSceneViewer1MouseDown(Sender: TObject;   Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin   mX:=X; mY:=Y; end; procedure TForm1.GLSceneViewer1MouseMove(Sender: TObject;   Shift: TShiftState; X, Y: Integer); begin   If ssLeft in Shift then   GLCamera1.MoveAroundTarget(mY-Y, mX-X);   mX:=X; mY:=Y; end;
Sad kad pokrenemo program dodamo nekoliko nodova imamo objekt oko kog moze da kruzi kamera (znaci ne rotiramo sam objekt kao u jedno od ranijih primera).
Ali objek i nije nesto narocito lep sve linije su prave (nije zaobljen), zato cemo dodati je jedan CheckBox i ovaj kod
procedure TForm1.CheckBox1Click(Sender: TObject); begin   If CheckBox1.Checked then GLRevolutionSolid1.SplineMode:=lsmBezierSpline   else GLRevolutionSolid1.SplineMode:=lsmLines; end;
Sad imamo lepo zaobljen objek kad cekiramo checkbox.

Dodacemo jos dva ScrollBara, Position prvog ScrollBara postavite na 10, a drugog na 16, i jos malo koda
procedure TForm1.ScrollBar1Change(Sender: TObject); begin   GLRevolutionSolid1.Division:=ScrollBar1.Position; end; procedure TForm1.ScrollBar2Change(Sender: TObject); begin   GLRevolutionSolid1.Slices:=ScrollBar2.Position; end;
Division predstavlja broj segmenata linije izmedju dva noda (prilikom zaobljavanja), a Slices broj koraka prilikom rotiranja linije.

To je uglavnom to, GLRevolutionSolid ima jos nekoliko osobina ali to ostavljam vama da isprobate.

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 17:06

Posle male pauzice nastavljamo sa primerima.
Pokazacemo kako se koristi Movement controls osobina (u designtime i u runtime) kao i PointTo funkciju objekata u GLScene.
Postavimo scenu (ne zaboravite i GLCadencer), na njoj kameru i svetlo, a od objekata (Basic Geometry) GLIcosahedron (ovom objektu cemo kretanje praviti u designtime), GLDodecahedron (ovom u runtime) i (Advanced Geometry) GLArrowLine (to je samo strelica i prilicno je korisna za pokazivanje u nesto... sa njom cemo koristiti PointTo funkciju).
Posto cemo koristiti osobine objekata moram u uses ubaciti GLBehaviours unit, GLMovement jer cemo koristiti Movement controls i u runtime kao i VectorGeometry da bismo lakse postavljali vektore u runtime. Postavimo objekte na sledece pozicije GLArrowLine 0, 0, -4, a GLIcosahedron i GLDodecahedron na 0, 0, -8. Njihove pozicije i nisu mnogo bitne jer ce Movement controls da ih pomeraju, ali cisto da ih vidimo da su i oni na sceni. Kad smo ovo odradili mozemo da krenemo na nov deo.
Kliknimo desnim na GLIcosahedron i izaberimo Add behaviour->Movement controls. Izaberimo Movement controls osobinu u Scene Editoru i u Object Inspectoru mozemo da pravimo putanje za nas objekat. Moguce je spremiti vise putanja i u progrmu birati koja ce da se izvrsava. Mi cemo koristiti samo jednu, a ako nekom bude previse komplikovano da shvati kako se biraju putanje (hint: ActivePath) neka pita :)Putanja se kreira tako sto zadajemo tacke u prostoru i definisemo koliko ce objekat sa se zarotira i/ili promeni velicinu dok putuje. Dodacemo novu putanju pritiskom na '...' u Paths property i biranjem Add new u prozorcicu koji se otvorio. Sada nam preostaje da dodajemo tackice kroz koje ce objekat prolaziti (uz rotiranje i promenu velicine). Tacke dodajemo na isti nacin kao i putanje i nalaze se u Nodes property. Dodacemo sledece tacke:

Pozicija (X, Y, Z): 1, -2, -8
Rotacija (Pitch, Roll, Turn): 50, 0, 0
Scale (X, Y, Z): 1, 1, 1
Speed: 2

Pozicija (X, Y, Z): 3, 0, -8
Rotacija (Pitch, Roll, Turn): 50, 50, 0
Scale (X, Y, Z): 1, 1, 1
Speed: 2

Pozicija (X, Y, Z): 4, 1, -8
Rotacija (Pitch, Roll, Turn): 50, 50, 50
Scale (X, Y, Z): 1, 1, 1
Speed: 2

Pozicija (X, Y, Z): 2, 2, -8
Rotacija (Pitch, Roll, Turn): 0, 50, 50
Scale (X, Y, Z): 1, 1, 1
Speed: 2

Pozicija (X, Y, Z): -4, -3, -8
Rotacija (Pitch, Roll, Turn): 0, 0, 50
Scale (X, Y, Z): 1, 1, 1
Speed: 2

Pozicija (X, Y, Z): 0, 0, -8
Rotacija (Pitch, Roll, Turn): 0, 0, 0
Scale (X, Y, Z): 1, 1, 1
Speed: 2

To ce nam biti neko kretanje za nas prvi objekat. Bilo bi lepo da vidimo kako ce da se on krece, zar ne? Da bi smo izabrali aktivnu putanju u designtime postavicemo ActivePathIndex property Movement controls osobine na 0 sto bi znacilo da smo izabrali prvu putanju. Ostaje nam jos da u OnCreate eventu nase forme pokrenemo nas objekta, a to cemo uraditi ovako
procedure TForm1.FormCreate(Sender: TObject); begin   GetOrCreateMovement(GLIcosahedron1).StartPathTravel; end;
Ako pokrenemo program nas objekat ce se kretati. Prvo sto upada u oci je da se objekat ne krece uvek konstantnom brzinom iako smo Speed property svake tacke postavili na 2! To je trenutno jedan od bugova u GLScene, ali ako se tacke lepo i dovoljno blizu postave ovaj bag se skoro ne primecuje. Posto ne zelimo da se nas objekat zaustavi posle par sekundi kretanja postavicemo Looped property putanje na True. Da bi looped putanja lepo izgledala pocetna i krajnja tacka bi trebale da budu iste pa cemo dodati jos jednu tacku na putanji koja je ista kao i prva. Sada nas prvi objekat nekako nezgrapno uspeva da se krece po sceni Smile
Sad je red da to uradimo i sa drugim objektom, ali u runtime. Tacke cemo dodati u OnCreate eventu forme... event ce izgledati ovako:
procedure TForm1.FormCreate(Sender: TObject); var I: Integer; begin   Randomize;   GetOrCreateMovement(GLIcosahedron1).StartPathTravel;   with GetOrCreateMovement(GLDodecahedron1) do   begin     with Paths.Add do     begin       for I := 0 to 19 do       begin         with Nodes.Add do         begin           PositionAsVector := VectorMake(Random(10) - 5,             Random(8) - 4,             Random(3) - 8);           RollAngle:= Random(360);           PitchAngle := Random(360);           TurnAngle := Random(360);           ScaleAsVector :=VectorMake(1 + Random,             1 + Random,             1 + Random);           Speed := Random(4) + 1;         end;         Nodes.Add.Assign(Nodes[0]);         Looped := True;       end;     end;     ActivePathIndex := 0;     StartPathTravel;   end; end;
GetOrCreateMovement kreira Movement controls za nas objekat i vraca nam ga. Zatim sa Paths.Add dodajemo novu putanju i sa Nodes.Add nove tackice. Postavljamo njihove podatke i na kraju dodajemo jos jednu tacku koja je ista kao i prva. Postavljamo Looped na True kako bi se putanja pokrenula ponovo kad joj dodje kraj. Sve sto nam je preostalo je da postavimo aktivnu putanju i da pokrenemo objekat. Prosto k'o pasulj Very Happy
Hajde jos da sredimo i da strelica pokazuje na objekat ciju putanju kreiramo u runtime. Za to je dovoljna samo jedna linija u GLCadenceru
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); begin   GLArrowLine1.PointTo(GLDodecahedron1, YHmgVector); end;
Sve sto kazemo je objekat na koji zelimo da linija pokazuje i gde joj je "gore" (YHmgVector ima vrednost 0, 1, 0).
To je to za sad... sledece sto nas ceka su Time Events... sa ovom komponentom mozemo da u odredjeno vreme uradimo nesto sa objektima ili bilo cim. Moze biti prilicno korisna stvarcica za animacije u igri.
Bye!!!



[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 17:08

Izgleda forum ne dozvoljava duzi post... neka neko nesto napise pa da mogu da nastavim Smile



Registruj se da bi učestvovao u diskusiji. Registrovanim korisnicima se NE prikazuju reklame unutar poruka.
offline
  • Strog  Male
  • Stručni saradnik
    Web programiranje
  • Bojan Kopanja
  • Web & Mobile developer @ ZeusSoftware
  • Pridružio: 26 Jul 2003
  • Poruke: 2597
  • Gde živiš: Stara Pazova

Odlicno Srki, eto, sada napokon i u ovom gradu imamo mocan tut o OPenGL-u Wink. Cekamo nastavke Very Happy!



offline
  • Srđan Tot
  • Am I evil? I am man, yes I am.
  • Pridružio: 12 Jul 2005
  • Poruke: 2483
  • Gde živiš: Ljubljana

Uvek je korisno imati komponentu kojoj mozes da kazes "uradi to i to u toliko sekundi i nastavi to da radis sve do tog vremena uz pauze od toliko sekundi". To je ono sto radi Time Events komponenta. Napravicemo jednostavnu animaciju u kojoj ce jedna kocka doleteti s leva, malo se pribliziti, druga s desna, obe se priblize, treca odozgo i opet se sve malo priblize i zatim pocnu da se okrecu. Ovde je sve vrlo jednostavno... vise se vremena provede u podesavanju vremena nego u pisanju koda Smile
Postavicemo na scenu kameru, svetlo i 3 kocke. Prvu na -8, 0, -7. Drugu na 7, 0, -6. Trecu na 0, 4, -5. Time Events zahteva GLCadencer pa cemo ga postaviti na formu. Sa GLScene Utils grupe postavimo GLTimeEventsMGR komponentu na formu i Cadencer podesimo na onaj koji smo ranije stavili na formu. Sada nam ostaje da dodajemo nase evente. Svaki event ima vrstu, pocetno i krajnje vreme, pauzu (vremena su u sekundama), ime i da li je ukljucen ili nije. Od tipova imamo Continuous (poziva se od startnog do krajnjeg vremena sto je pre moguce), Periodic (slicno kao i Continuous samo sto se pravi pauza izmedju pozivanja) i OneShot (poziva se samo jednom... krajnje vreme nema znacaj). Ako zelimo da se neki event ponavlja i ponavlja... da nema kraja, krajnje vreme postavimo na -1. Sad cemo dodati nase evente (klik na '...' Events property i onda Add new u otvorenom prozorcicu).
1.
Pomera prvu kocku ka sredini
Tip = Continuous
Start = 2
End = 8
procedure TForm1.GLTimeEventsMGR1Events0Event(event: TTimeEvent); begin   GLCube1.Position.AsVector := VectorMake(-8 + Event.ElapsedTime, 0, -7); end;
Jednostavno smanjuje X koordinatu pozicije. Event.ElapsedTime je vreme koje je proslo od startovanja eventa.
2.
Malo priblizimo prvu kocku
Tip = OneShot
Start = 8.5
procedure TForm1.GLTimeEventsMGR1Events1Event(event: TTimeEvent); begin   GLCube1.Position.Translate(ZHmgVector); end;
Samo smo pomerili kocku blize kameri po Z osi.
Narednih nekoliko eventa su svi slicni... pomera se druga kocka, priblizavaju se, treca kocka... kada su sve kocke vidljive pocecemo da ih rotiramo. Rotiranje cemo vrsiti eventima tipa Periodic i koristicemo Event.TickCount property. TickCount predstavlja koliko je puta event bio pozvan do sad.
procedure TForm1.GLTimeEventsMGR1Events9Event(event: TTimeEvent); begin   GLCube1.TurnAngle := Event.TickCount * 5; end;
To je otprilike to... prilicno jednostavno za upotrebu, a zaista mocno Smile
Mozda neko moze da uradi neku animaciju za ove tutoriale pa da je ubacimo na pocetak "Parovi" i svih narednih igara koje cemo praviti ovde Smile



[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:09

Pre nego sto predjemo na vatre, dimove i slicne efekte hteo bih jos samo da spomenem par objekata za ispisivanje teksta i stavljanje slicica na scenu. Skoro u svakom programu je potrebno nesto ispisati korisniku... cudi me kako sam zaboravio na ove objekte na pocetku tutoriala, ali evo... setiosam se ipak... bolje ikad nego nikad Smile
Radicemo sa HUDSprite, HUDText i Space Text komponentama. HUDSprite i HUDText se ne nalaze u 3D vec 2D prostoru... X i Y koordinate im odredjuju polozaj i 0, 0 je gornji-levi ugao GLSceneViewera, a GLSceneViewer.Width, GLSceneViewer.Height je dodnji-desni ugao GLSceneViewera. Kao obicne VCL komponente na formi. Treba znati da koordinata predstavlja centar objekta, a ne njegov gornji-levi ugao kod HUD objekata.
Idemo sa primerom. Postavicemo GLSceneViewer dako da Width bude 688, a Height 446. Dodacemo HUDSprite (Add object->HUD objects->HUD Sprite) i postaviti ga na 344, 250, 0 tako da bude oko sredine ekrana. Width cemo postaviti na 250, a Height na 100. Za texturu sam koristio sliku sa MC pa ako je to zabranjeno neka neko kaze i stavicu nesto drugo. Kada postavimo texturu vidimo kako se nas HUD Sprite lepo iscrtao.



Sa HUD Sprite mozemo da radimo sta hocemo kao i sa ostalim objektima... da detektujemo da li je mis iznad njega, da ga rotiramo, menjamo velicinu...
Sledeci je na redu HUD Text. HUD Text je skoro isti kao i HUD Sprite samo sto umesto materijala i textura imamo text na osnovu kojeg GLScene iscrta texturu. Postavicemo ga na 344, 150, 0. Aligment cemo staviti na Center. Da bi slova mogla da se iscrtavaju potrebna nam je slika slova. Mozemo koristiti bmp slike ili pustiti GLScene da sam kreira slike na osnovu win fontova. Sada cemo zbog jednostavnosti koristiti windows fontove. Na formu cemo postaviti GLWindowsBitmapFont iz GLScene grupe. Tu mozemo izabrati zeljeni font... ja sam postavio na Tahoma, 26, Bold. GLHUDText .BitmapFont property cemo postaviti na GLWindowBitmapFont koji smo malocas postavili na formu i sada mozemo napisati text za HUDText.Text property "GLScene Tutorial 12" i walla Smile



Boja slova se moze menjati propertyem ModulateColor. Rotacija, promena velicine, menjanje pozicije... sve se moze kao i sa ostalim objektima.
Poslednji objekat za ovaj tut je Space Text... to je otprilike kao i HUD Text samo sto se mogu koristiti samo Win fontovi i mogu da imaju 3D oblik... takodje imaju i 3D koordinate kao i svi obicni objekti. Dodacemo jedan objekat tipa GLSpaceText (Add objects->Doodad objects->Space text) i postavicemo ga na -5.4, -3, -8 tako da bude otprilike pri dnu na sredini scene. Izabracemo font (tahoma, 26, bold) i napisati text "by MC Delphi Team (2005)"... i slova su se pojavila, ali ne izgledaju nista bolje od HUDTexta... fazon je u tome sto za Space Text treba svetlo da bi se lepo videlo sve i zato cemo dodati jednu lampicu na scenu. Sad vec izgleda malo lepse, a da bi dodali i 3D izgled Extrusion property cemo postaviti na 0.2. E, sad vec izgleda bolje Smile Naravno, ovde mozemo podesiti i materijal, texturu... sve sto smo mogli na kocki, lopti i ostalim objektima.



Eto, tako se ispisuju slova u GLScene... nista komplikovano, zar ne Smile Sad bi neko mogao da napravi malu animacijicu sa GLSpaceText, HUDText, HUDSprite, GLTimeEventsMGR i slicnim komponenticama za ove nase tutoriale... da vidim da li je neko nesto naucio Smile Posle kad budemo radili i zvuk bice jos bolje... ako neko uradi Smile

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:12

Doslo je vreme i za slatke male efekte... vecinu cemo raditi sa cesticama (particle). Sa cesticama mozemo kreirati kisu, vatru, dim i slicne efekte. Cestica je u sustini obican objekat (lopta, kocka, ploca) koja se krece na osnovu nekih podatka... kada je tu samo jedna cestica to i nije bas neki "efekat", ali kad imamo 10... 20... 100... 1000 cestica onda vec mozemo imati neku lepu scenicu. Napravicemo jedan slican programcic kao demo za vatru koji ide sa GLScene.
Dodacemo na formu GLScene, GLSceneViewer, GLCadencer, a na scenu kameru, svetlo, loptu ( 0, 0, -6 ) i torus (Add object->Advanced Geometry->Torus). Torus cemo postaviti isto na 0, 0, -6, a MajorRadius na 2 i MinorRadius na 0.3. Dodacemo jos kod u OnProgress event GLCadencera da se torus okrece
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); begin   GLTorus1.Turn(deltaTime * 20);   GLTorus1.Pitch(deltaTime * 30); end;
Jedna od bitnih stvari prilikom kreiranja efekata je svetlost... posto je vatra otprilike narandzaste boje i svetlost bi trebala da bude takva... zato cemo diffuse boju svetla postvaiti na clrOrange i pomericemo svetlost na 0, 0, -4 kako bi izgledalo kao da svetlost dolazi iz vatre.



Sada nam je pozadina scene nekako bezveze obojena u sivo... podesimo GLSceneViewer.Buffer.BackgroundColor na clrBlack kako bi izgledalo da je oko nasih objekata samo mrak Smile



Sada nam ostaje jos samo da napravimo tu vatricu. Prvo sto treba da uradimo je da postavimo GLFireFXManager (GLScene PFX grupa) na formu. Postavimo Cadencer property na GLCandencer1 koji smo vec kreirali. Sada imamo komponentu koja ce nam prikazivati vatru... treba jos samo da je povezemo sa nasim objektom (lopta). Kliknimo desnim na GLSphere1 i u Add efect meniju izaberimo Fire FX. U Scene Editoru izaberimo Fire FX efekat i za Manager property postavimo GLFireFXManager1 koji smo vec kreirali. Da bi nam vatrica izgledala lepse u GLFireFXManageru podesimo FireRadius na 0.4, ParticleInterval na 0.01, ParticleLife na 2 i ParticleSize na 0.4. Pokrenimo sad programcic... iiiiii... vatrica gori, ali nesto nije uredu... vatra je nekako uvek iza torusa iako tako ne bi trebalo. Problem je u tome sto Alphablended objekti moraju da se iscrtavaju na kraju. Da bi smo to ispravili izaberimo GLSphere1 u Scene Editoru i pritisnimo Ctrl+D (ili Move Object Down dugme u tool baru) da bi smo je pomerili na poslednje mesto na sceni. Ako sada pokrenemo program sve ce biti ok Smile



Probajte malo da se igrate propertyima u GLFireFXManageru... vidite kakvu vatru mozete napraviti Wink

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:14

Jos jedan lep efekat (meni jos lepsi i laksi za koriscenje od vatre) je ThorFX. To je simulacija munje. Na raspolaganju nam stoji izbor debljine munje, boje, koliko ce munja da oscilira, koliko da se razbacuje... Pokazacemo na prostom primeru kako to izgleda.
Postavicemo na scenu kameru, svetlo i dve lopte na pozicijama -3, 0, -5 i 3, 0, -5. Sad cemo dodati GLThorFXManager sa GLScene PFX palete. Ova komponenta je zaduzena za definisanje izgleda munje. Da bi mogla da radi moramo joj podesiti Cadencer property na GLCadencer komponentu koja je na formi. Sledece sto radimo je dodavanje Thor efekta nasoj prvoj lopti ( -3, 0, -5 ). Desni klik na GLSphere1->Add Effect->ThorFX. Jedino sto mozemo da podesimo za ThorFX evekat su ime i Manager. Postavimo manager na GLThorFXManager koji je na formi. Ovo je sve sto je potrebno da bi se munja videla... ali nismo jos postavili na koju stranu i koliko daleko da se vidi munja. To nam odredjuje GLThorFXManager.Target property. Moramo samo obratiti koju koordinatu tu pisemo jer to nije apsolutna koordinata mete nego relativna u odnosu na nasu loptu tj. objekat koji ima ThorFX efekat. Postavicemo Target na 6, 0, 0 sto znaci da ce munja de se vidi 6 jedinica desno od nase prve lopte sto znaci da ce drugi kraj biti u centru druge. Da munja ne bi izgledala previse velika postavicemo GlowSize na 0.1. I to je to... pokrenimo program i neka munja seva Smile



Experimentisite malo sa osobinama ThorFX efekta (menjajet boje, vibration, velicinu...). Mogu se bas lepi efekti stvoriti ovom komponentom.

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:17

Ovog puta pravimo kisu. Pocnimo postavljanjem scene i na njoj kameru, svetlo i jednu kocku koja ce se nalaziti na 0, 0, -4, a CubeDepth = 2, CubeHeighte = 0.2 i CubeWidth = 5. Ovo ce biti nas oblak iz kojeg ce da pada kisa (i bice to bas jak pljusak). Kisu cemo kreirati GLPointLightPFXManager komponentom sa GLScene PFX palete. Svi PFX manageri rade na istom principu samo koriste drugacice cestice... PointLight koristi sprajt sa texturom (krug koji je na sredini beo, a sto se ide dalje sve je tamniji), Polygon koristi poligone (moze se birati broj strana i centralni vertex je beo, a krajnji su crni), Custom moze da koristi bilo koji objekat, CustomSprite koristi sprajt sa bilo kakvom texturom, Perlin koristi perlin noise algoritam da bi napravio texturu za sprajt, Line koristi linije. To je otprilike to... sve sto cemo raditi sad sa GLPointLightPFXManagerom moze se raditi i sa bilo koji drugim managerom i rezultati ce biti skoro isti.
Sad cemo podesiti osobine cestica. Podesimo Acceleration na 0, -5, 0 kako bi kapljice brzo padale, AspectRatio na 0.1 da bi cestica bila vertikalno izduzena, ColorInner na belo (to je boja koju cestica ima kad se kreira), ParticleSize na 0,05 jer nam ne trebaju ogromne cestice. Treba jos da definisemo koliko ce dugo cestica biti vidljiva. To radimo uz pomoc LifeColors propertya. Kliknimo na '...' i otvorice nam se prozorcic u kojem pise vreme i boje cestica. Vreme predstavlja vreme u sekundama od nastanka cestice, a boja odredjuje u koju boju ce se cestica promenuti kad dodje to definisanog vremena. Vreme poslednjeg unosa je tagodje i vreme kada ce cestica nestati. Nase kapi ne treba da menjaju boju tako da cemo ColorInner postaviti na belo, a treba samo kratko da se vide pa cemo postaviti vreme na 0.5 sekundi. Skoro da smo zavrsili.
Da bi PFX Manager mogao da se iscrtava moramo na scenu ubaciti PFX Renderer (Add object->Particle systems->PFX Renderer). On je zaduzen za iscrtavanja i ima nekoliko propertya, ali ce nam njihova default vrednost skoro uvek odgovarati pa necemo sad o tome. Postavimo Cadencer i Rendere property za PointLightPFXManager i sada je spreman.
Sve sto nam ostaje je da povezemo cestice sa nasim oblakom. To cemo uraditi tako sto cemo dodati PFX Source efekat nasoj kocki i podesiti proertye. Manager cemo postaviti na PointLightPFXManager koji smo postavili na formu, InitialVelocity na 0, -5, 0 kako bi kapljice odmah imale neku brzinu kad se kreiraju (odmah padaju), ParticleInterval na 0.001 i imacemo pljusak jer ce cestice da se pojavljuju bas brzo, PositionDispersionRange na 3, 0, 1 i PositionDispersion na 0.8 tako da ce cestice da se rasporedjuju po povrsini kocke (random u x i z pravcima), ali nece ici ispod i iznda jer smo Y postavili na 0. To je skoro to. Za kraj podesimo da se forma svaki put iscrtava kako bi smo videli nas efekat
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); begin   GLSceneViewer1.Invalidate; end;
Pokrenimo program i uzivajmo u kisi Smile



Eksperimentisite malo s osobinama PointLightPFXManagera i PFX Source efekta... malim modifikacijama moze se napraviti kao da pada sneg, da duva vetar gok kisa pada... da pada krv iz kocke Very Happy Experimentisite Wink

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:20

Sledeci efekat je dim. Koristicemo isti princip kao i kod stvaranja kise samo sa drugim parametrima i ovog puta cemo koristiti PolygonPFXManager, ali, kao sto rekoh, mogli smo koristiti i neki grugi (mozda Perlin... imao bi bas lepe texture za dim). Znaci scena, PolygonPFXManager, na sceni kamera, svetlo, kocka i PFX Renderer. Kocku cemo staviti na -2, -1, -4 i to ce nam biti odzak. Cestice dima cemo ovako da podesimo... Acceleration 0.3, 0, 0 tako da ce dim da ide na desno, ColorInner na belo, ParticleSize na 0.4 i u LifeColor cemo ostaviti samo jedan unos. Boju cemo istaviti na Transparent pa ce dim vremenom da postaje sve providinji, a vreme cemo postaviti na 5 sekundi. Sad jos da podesimo PFX Source efekat za kocku. InitialPosition postavimo na 0.4 tako da se cestice kreiraju malo ispod gornje ivice kocke, InitialVelocity na 0, 0.5, 0 i VelocitiDispersion na 0.1 tako da dim krece na gore, ali da cestice imaju malo razlicite brzine, ParticleInterval na 0,03 da imamo lep gust dim, PositionDispersionRange na 1, 0, 1 i PositionDispersion na 0.2 da dim ne izlazi samo iz jedne tacke i to je to. Napisimo samo jos i OnProgress event
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); begin   GLSceneViewer1.Invalidate; end;
Pokrenimo program i dim ce da izlazi iz odzaka Smile



Probajte da menjate verdnosti managera i efekta da vidite kako uticu na izgled dima.

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:23

Ucitavanje 3d objekta i animacija iz fajla kao i menjanje texture objektu u runtime.
Radicemo sa GLActor objektom. On je dizajniran tako da se fajlovi lako ucitavaju i animacije lako biraju i pustaju.
Postavicemo na formu scenu i cadencer, a na sceni ce biti kamera, svetlo i jedan GLActor objekat (Add object->Mash objects->Actor). Postavicemo ga na 0, 0, -4, posto je objekat prilicno velik moracemo da ga malo smanjimo pa cemo Scale postaviti na 0.05, 0.05, 0.05 i jos cemo PitchAngle postaviti na 90 jer je orientacija Quake 2 modela (koristicemo Quake 2 model... samo da znate) malo drugacija od GLScene. Model mozete skinuti ovde. Sada cete videti kako je lako ucitati objekat i njegovu texturu. Napisimo OnCreate event za formu
procedure TForm1.FormCreate(Sender: TObject); begin   GLActor1.LoadFromFile('waste.md2');   GLActor1.Material.Texture.Image.LoadFromFile('waste.jpg');   GLActor1.Material.Texture.Disabled := False; end;
I to je to Smile



Ovo cak i ucitava animacije iz Quake 2 modela. Jedino sto moramo da uradimo je da dodamo u unit deo GLFileMD2 i JPEG unite da bi fajlovi mogli da se ucitaju. Prilicno lako, zar ne?
Sada cemo napraviti da se textura objekta menja kliknom na formu. Zajedno sa modelom se nalaze i dve texture Waste.jpg i WasteCell.jpg. WasteCell.jpg je malo modivikovana verzija obicnog skina za nas model i klikom na formu ce se ove texture menjati. Dodacemo jednu globalnu promenljivu
var   TextureName: String;
Malo modifikovati OnCreate event forme
procedure TForm1.FormCreate(Sender: TObject); begin   GLActor1.LoadFromFile('waste.md2');   GLActor1.Material.Texture.Image.LoadFromFile('waste.jpg');   GLActor1.Material.Texture.Disabled := False;   TextureName := 'waste.jpg'; end;
i dodati OnClick event za SceneViewer
procedure TForm1.GLSceneViewer1Click(Sender: TObject); begin   if TextureName = 'waste.jpg' then     TextureName := 'wastecell.jpg'   else     TextureName := 'waste.jpg';   GLActor1.Material.Texture.Image.LoadFromFile(TextureName); end;
Opet nista komplikovano... jednostavno ucitavamo novu texturu umesto stare Smile
I za kraj... konacno... animacija Smile Dodacemo jedan ComboBox pomocu kojeg cemo birati animacije i postavicemo Style na DropDownList. Prva stvar je da napunimo ComboBox nazivima animacija. Za to ce nam posluziti Funkcija GLActor.Animations.SetToStrings. Ona ubacuje u bilo koju promenljivu tipa TStrings (ili neke klase koja je nasledjuje) nazive animacija. Sledece sto treba da uradimo je da prilikom promene izabrane stavke u ComboBoxu pustimo animaciju. Animacija se pusta tako sto se izabere ime animacije ili njen redni broj funkcijom GLActor.SwitchToAnimation i postavi zeljeni nacin pustanja animacije GLActor.AnimationMode koji moze biti aamNone (nema animacije), aamPlayOnce (animacija se samo jednom pusti), aamLoop (animacija se stalno vrti), aamBounceForward (ide od pocetka do kraja, pa od nazad do pocetka), aamBounceBackward (od nazad ka pocetku, pa od pocetka prema kraju) ,aamLoopBackward (vrti se unazad), aamExternal (animacija stoji i pozivanjem NextFrame ili PrevFrame menjamo trenutni frejm).
Modifikovacemo malo OnCreate event forme i dodati OnChange evet ComboBoxu
procedure TForm1.FormCreate(Sender: TObject); begin   GLActor1.LoadFromFile('waste.md2');   GLActor1.Material.Texture.Image.LoadFromFile('waste.jpg');   GLActor1.Material.Texture.Disabled := False;   TextureName := 'waste.jpg';   GLActor1.Animations.SetToStrings(ComboBox1.Items);   ComboBox1.ItemIndex := 0;   ComboBox1Change(ComboBox1); end;
procedure TForm1.ComboBox1Change(Sender: TObject); begin   GLActor1.SwitchToAnimation(ComboBox1.Text);   GLActor1.AnimationMode := aamLoop; end;
I to je sve... objekat se animira i mozemo da mu menjamo texturu i to prilicno lako Smile



Sledeci ce biti neverovatno laki, ali i prilicno korisni tutoriali. Uradicemo GLBlur (zamucuje scenu ili samo neki objekat) i GLTrial (pravi trag iza objekta) komponente. Nece biti potrebno da kucamo program... sve cemo zavrsiti u Scene Editoru i ObjectInspectoru u designtime Very Happy

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:29

Ovaj primer nisam ja uradio. Uradio ga je Sasa Popovic

Prosao sam kroz vecinu lekcija, a malo sam i sam eksperimentisao i napravio sam malu animaciju...

Koristio sam nekoliko novih stvari:

1) Scene Objects->Add object->Doaded Objects->Tree. Oblik drveta mozete promeniti podesavanjem parametara drveta (depth, branch*, leaf*, seed, ...). Da bi listovi bili zeleni a stablo i grane braon boje neopodno je koristiti GLMaterialLibrary u kome cete napraviti potrebne materijale/boje i obavezno im dati imena. U polja LeafMaterialName i BranchMaterialName treba uneti zeljene materijale (OVA POLJA SU CASESENSITIVE!!!).

2) AsyncTimer (sa palete GLSceneUntils), koji se ponasa isto kao i standardni tajmer sa palete System. AsyncTimer-u mozete podesavati prioritet i to je cini mi se jedina razlika u odnosu na TTimer.

3) Scene Objects->Add object->Basic Geometry->Points. Tacku sam koristio kao izvor za grom i vatru

4) Scene Objects->Add object->Basic Geometry->Plane. Ravan je sluzila kao sivo nebo koje je izvor kise i cini mi se da je ovo malo stedljivije resenje od GLCube. Pomocu ravni sam napravio i zelenu podlogu.

Boju pozadine GLSceneViewer-a je ista kao i boja neba!

GLPoint1, koja je izvor groma se nalazi malo iznad ravni koja predstavlja nebo. Dok grom udara u drvo, dva puta mi se menjaju koordinate za Target i tako je dobijen efekat "setanja" groma.

GLPoint1/2/3, koje su izvor vatre se nalaze "negde na drvetu". Tri razlicita izvora i tri razlicite vatre sam koristio kako bih napravio "realistican" efekat sirenja vatre, postepenim paljenjem jednog po jednog izvora. Negde u centru drveta nalazi se i jedan narandzast iyvor svelosti koji je na pocetku animacije ugasen, pa se postepeno pojacava kako se vatra siri.

AsyncTimer aktivira i gasi efekte, a cini mi se da je sve moglo da se odradi jednostavnije i udobnije komponentom TimeEvents (sa tog casa sam povegao:-)).

Pitanja: Kako napraviti dim sive boje. Ja sam probao, ali ne umem.

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:31

Pricao sam vam o texturama i blending modovima, zar ne? Smile
Po defaultu BlendingMode za PFX efekte stoji na Aditive sto znaci da se boja cestice sabere sa bojom pozadine i tako se dobije nova boja... posto je siva boje jednostavno zatamnjena bela kada je postavimo dim samo posvetli pozadinu... logicno Smile Da bi boja bila siva potrebno je BlendingMode postaviti na Transparency. Evo primera sa dimom koji koristi PerlinPFXManager... svi podaci su isti kao i kod prethodnog primera sa dimom jedino sto se koristi drugi generator i drugi BlendingMode.



[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:34

U ovom primeru cemo raditi sa GLBlur objektom. On "zamucuje" objekta u koji je postavljen. Postoje nekoliko modova u kojima moze da radi. Vrlo je bitno samo postaviti GLSceneViewer.Buffer.BackgroundColor na crno inace ce GLBlur da zezne celu scenu (cela scena ce biti boje pozadine sa nekim mrljama... probajte pa cete videti). Postavicemo scenu i cadencer i na sceni kameru, svetlo, kocku (na 0, 0, -3 sa zutom bojom) i u kocki GLBlur (Add object->Speciao objects->GLBlur). I to je to Smile Nista vise nije potrebno da bi blur radio. Da smo ga postavili direkno na scenu tada bi cela scena bila zamucena. Pogledajte property Presets i probajte da ga menjate i vidite kako sve objekat moze da bude zamucen.
Da scena ne bi bila bas nepomicna dodacemo Simple Inertia behaviour kocki i podesiti PitchSpeed na 20 i RollSpeed na 30. Moracemo samo da dodamo u unit deo i GLBehaviours.
Pokrenimo program i gledajmo kako se kocka zamucuje Smile



Ovako je lako koristiti i GLTrial... videcete u sledecem primeru Smile

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:40

Jos jedan ultra lak za napraviti efekat Smile GLTrail objekat ostavlja trag iza objekta koji se pomera (cesto se koristi taj efekat u borilackim igrama kada se igrac pomera neveroavtno brzo i slicno). Hajde da probamo da uradimo primercic sa ovom komponentom. Postavimo scenu i cadencer, a na sceni kameru, svetlo, DummyCube (0, 0, -4) i u njoj npr. GLIcosahedron (0, 1.5, 0). Na kraju dodajmo i GLTrial (ovaj objekat ne bi trebalo da se nalazi u drugim objektima jer trag moze da se pomeri na neku bezveznu poziciju), a TrialObject na GLIcosahedron koji smo kreirali. Ovo je sve sto je potrebno da bi TrialObject radio... ustvari... da bi videli trag objekat mora da se krece. Zato smo postavili DummyCube... dodacemo joj Simple Inertia i postaviri RollSpeed na 120. Da Simple Inertia moze da radi moramo u uses dodati GLBehaviours (to je jedino sto moramo da kuckamo u programu) i pokrenimo ga Smile



Prilicno lako i jednostavno Smile
Sledece na repertoaru su zvukovi (2d i 3d).

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 20:45

Danas ce se u nasem i vasem GLScene tutorialu po prvi put pustati TON FILMOVI Very Happy
Konacno i malo zvuka... pocecemo sa direknim pristupom BASS Sound engine-u. Necemo koristiti nikakve komponente jedino Bass unit iz GLScene.
Evo nekih informacija o BASS Sound Engine

Da pocnemo... postavite dva dugmeta na formu. Prvo ce nam sluziti za pustanje, a drugo za zaustavljanje muzike. Dodajte jedan CheckBox... kada bude "ukljucen" fajl ce se ponavljati, a ako ne bude odsvirace jednom i kraj. Za kraj dodacemo jos i OpenDialog da bi smo lakse nalazili fajlove za pustanje, a sad kod.
Da bi BASS radio moramo dodati u uses deo Bass unit
uses   Bass;
Podesimo OnCreate event za formu
procedure TForm1.FormCreate(Sender: TObject); begin   BASS_Load(BASS_DLL);   BASS_Init(1, 44100, 0, Application.Handle, nil);   BASS_Start; end;
Kao prvo moramo ucitati Bass.dll i to radi BASS_Load funkcija. BASS_DLL je samo konstanta (string) definisana u Bass.pas unitu i ima vrednost 'bass.dll'. Ako budete menjali ime dlla ne onda cete umesto BASS_DLL upisati to novo ime.
Sledece je incijalizacija engine-a. BASS_Init uzima kao prvi parametar redni broj uredjaja na kojem ce se pustati zvuk, zatim frekvencija zvuka (44100 se koristi za snimanje CD-ova), zatim Handle prozora koji ce se koristiti za poruke (Application.Handle se moze uvek koristiti), i na kraju mozemo uneti pointer na GUID kartice koju zelimo da koristimo... ako postavimo nil koristice se default kartica (uglavnom svi imaju samo jednu karticu pa uvek mozemo stavljati nil).
Na praju pokrecemo engine (pritiskamo play) pozivom na BASS_Start.

Sad cemo dodati OnDestroy event za formu
procedure TForm1.FormDestroy(Sender: TObject); begin   BASS_Stop;   BASS_Free;   BASS_Unload; end;
Ovde je sve jasno... zaustavljamo engine, oslobadjamo memoriju koju jeengine zauzeo i na kraj ga oslobadjamo dll koji smo na pocetku ucitali.

Hajde da pustimo neku muzikicu Smile Da bi smo mogli da pustimo muziku moramo imati jednu promenljivu koja ce drzati trenutno aktivni fajl pa cemo dodati globalnu promenljivu
var   S: HStream;
Podesimo sada OnClick event drugog dugmeta (ono dugme koje ce zaustavljati muziku)
procedure TForm1.Button2Click(Sender: TObject); begin   if S <> 0 then BASS_StreamFree(S);   CheckBox1.Enabled := True; end;
Kada ni jedan fajl nije ucitan S ima vrednost 0, a ako ima neku drugu vrednost oslobadjamo taj fajl i on se zaustavlja.
Sad ide ton Smile OnClick event prvog dugmeta izgleda ovako
procedure TForm1.Button1Click(Sender: TObject); begin   if OpenDialog1.Execute then   begin     Button2.Click;     S := BASS_StreamCreateFile(False, PChar(OpenDialog1.FileName), 0, 0, BASS_STREAM_AUTOFREE);     if CheckBox1.Checked then       BASS_StreamPlay(S, False, BASS_SAMPLE_LOOP)     else       BASS_StreamPlay(S, False, 0);   end;   CheckBox1.Enabled := False; end;
Ako izaberemo neki fajl u OpenDialogu prvo zaustavljamo muziku klikom na Button2 i zatim otvaramo fajl funkcijom BASS_StreamCreateFile. Prvi parametar oznacava da li je fajl ucitan u memoriju (npr. imate neki buffer u koji ste prethodno ucitali fajl i pustate muziku iz njega). Drugi parametar je naziv fajla ako pustamo sa diska, a ako pustamo iz memorije onda je to pointer na pocetak buffera. Sledeca dva parametra oznacavaju pocetak i duzinu u fajlu koji ce se svirati u semplovima (ako je fajl snimljen u 44100Hz onda je 1 sekunda 44100 semplova). Ako su oba parametra 0 svira se zeo fajl. I na kraju je flag koji oznacava kako se fajl svira. BASS_STREAM_AUTOFREE znaci da ce fajl biti automatski oslobodjen cim se odsvira do kraja. To je to vezano za ucitavanje. Sledece je na redu pustanje... funkcija BASS_StreamPlay pusta fajl koji mu prosledimo kao prvi parametar. Drugi parametar oznacava da li da se svi podaci snime u fajl pre pustanja ako je nesto bilo snimljeno u njemu pre pozivanja BASS_StreamPlay funkcije. I na kraju imamo flag koji moze da natera fajl da se pusta iz pocetka, da svira kao da je mono zvuk, kao da je 8bit, 16bit, 32bit, itd... Nama je sad interesantan BASS_SAMPLE_LOOP koji govori engine-u da stalno ponavlja zvuk.

I to je to... pokrenite program i probajte da nesto pustite. BASS zahteva da imate instaliran bar DirectX 3 pa... ako nemate nece raditi Smile

[url=https://www.mycity.rs/must-login.png

offline
  • Strog  Male
  • Stručni saradnik
    Web programiranje
  • Bojan Kopanja
  • Web & Mobile developer @ ZeusSoftware
  • Pridružio: 26 Jul 2003
  • Poruke: 2597
  • Gde živiš: Stara Pazova

Hehe, mislim da je DX3 nas problematican ovih dana Very Happy. 'Ajde, samo nastavi Wink.

offline
  • Srđan Tot
  • Am I evil? I am man, yes I am.
  • Pridružio: 12 Jul 2005
  • Poruke: 2483
  • Gde živiš: Ljubljana

Sada cemo koristiti komponentu GLSMBASS koja ce umesto nas odraditi svu inicijalizaciju kao i oslobadjanje memorije na kraju. Takodje cemo pokazati kako se pustaju 3D zvukovi.
Odmah da napomenem... muzika koju smo pustali u proslom primeru moze da bude mono, stereo, 5.1... ne bitno je, ali kada se zvik pusta u 3D prostoru mora biti mnono. Ako zvuk nije mono program ce prijaviti gresku. Malo je nemoguce pustiti stereo zvuk iz jedne tacke u protoru, zar ne? Smile Zvuk ce se automatski prebacivati sa levog na desni ili na neki drugi ako imate vise zvucnika u zavisnosti od mesta gde je zvuk nastao i mesta u prostoru gde se nalazi objekat koji prima zvukove.
Pocecemo postavljanjem scene, cadencera i jos dve komponente koje do sad nismo koristili... GLSoundLibrary i GLSMBass. Bitno je da prvo postavimo GLSMBass jer on mora da se kreira pre ostalih komponenti koje koriste zvuk. GLSoundLibrary je otprilike kao i GLMaterialLibrary samo sto ne cuva texture i boje nego zvukove. GLSMBass je sound manager i on je zaduzen da pusta zvukove. Sound Manager moze pustati samo zvukove koji su u SoundManageru. Naravno, koriscenjem funkcija za ucitavanje i pustanje muzike koje smo koristili u proslom primeru moguce je pustati i zvukove koji nisu u SoundLibrary. Jos nesto da napomenem... sve fajlove koje ubacimo u SoundLibrary bice snimljeni zajedno sa exe fajlom.
Hajde prvo da dodamo neki fajl u SoundLibrary. Kliknimo na '...' u Samples propertyu. Otvorice nam se prozorce u kojem cemo videti sve fajlove koje smo ucitali. Kliknimo na Add new. Svaki fajl tj. sample ima 2 propertya... Data (podaci koji su potrebni za sviranje) i Name (naziv sempla). Kliknimo na '...' u Data property i izaberimo fajl koji hocemo da ucitamo. SoundLibrary podrzava samo mp3 i wav fajlove pa smo ograniceni na njih. Izabracemo, recimo, C:\Windows\Media\RingOut.wav... taj fajl bi svi trebalo da imaju (zapamtite, mora da bude mono). To nam je dovoljno za nas primer.
Sledece sto cemo da uradimo je da graficki prikaz polozaja zvuka i mesta odakle slusamo. Dodajmo kameru, svetlo, ArrowLine, DummyCube i u njoj Sphere na scenu. Za ArrowLine postavimo poziciju na 0, 0, -10, Direction na 0, 1, 0 i Up na 0, 0, 1. DummyCube postavimo na 0, 0, -10, a Sphere na 0, 5, 0. Da bi strelica bila objekat koji "slusa" postavimo GLSMBass.Listener na ArrowLine koji smo kreiarli. Kad smo vec tu postavimo i GLSMBass.Cadencer na cadencer objekat koji je na formi i Active na True da bi uopste nesto culi Smile
Jos malo i zavrsili smo Smile Sada treba da pustimo zvuk iz lopte. Dodacemo Sound Emitter iz Add behaviour menija. Kliknimo na Sound Emitter u Scene Editoru da bi smo editovali propertye. Postavimo Source.SoundLibrari na GLSoundLibrary1 objekta koji je na formi, a Source.SoundName na 'ringout.wav'. NbLoops oznacava koliko ce se puta zvuk ponavljati. Ova funkcionalnost jos nije zavrsena pa za sve brojeve preko 1 zvuk se ponavlja dok ga mi ne zaustavimo. Postavicemo NbLoops na 2 da nam zvukic stalno svira. Poslednje sto cemo uraditi ovde je postavljanje Playing propertya na True Smile
Ovde postoje jos nekoliko korisnih propertya koje nismo koristili. Volume je vrednost od 0 do 1 koja ozvacava glasnocu. Min i Max Distance odredjuju koliko daleko od izvora se cuje zvuk... experimentisite malo s osobinama da ih bolje razumete.
Da zvuk ne bi dolazio samo iz jednog smera postavicemo Simple Inertia za DummyCube objekat i staviti RollSpeed na 20 (moramo dodati u uses GLBehaviours, ne zaboravite). I pokrenimo sada primer... kao sto vidite kako se lopta okrece oko strelice tako i zvuk kruzi sa desnog na levi zvucnik i obrnuto Smile
Ne znam za vas, ali meni je bilo zaista drago kad sam ukapirao kako se lako koriste 3D zvukovi Smile
GLSMFMOD se koristi POTPUNO ISTO kao i GLSMBASS. Ako neko zeli moze probati da uradi isti ovaj primer, ali sa GLSMFMOD objektom. Nemojte samo zaboraviti da Sound Manager objekat mora prvi da se stavi na formu inace zvuk nece raditi.

[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 21:22

Pa... sad znamo dosta stvari koje nam mogu olaksati pravljenje 3d aplikacija... ali jos ne znamo kako da detektujemo sudar dva objekta i sad cemo to da naucimo. Kao i sve ostalo u GLScene i ovaj problem je jednostavno resiti Smile
Koristicemo CollisionManager komponentu sa GLScene Utils palete i ona ce proveravati umesto nas da li se nesto sudarilo na sceni.
Pre nego sto pocnemo vrlo je bitno znato da CollisionManager nije savrsen... ovo je tabela koja nam govori sta radi precizno, a sta ne



Da pocnemo... postavimo sve sto nam treba za scenu (ukljucujuci i cadencer) i dodajmo CollisionManager. Dodajmo na scenu kameru, svetlo, DummyCube ( -3, 0, -10 ) i u njoj GLSphere ( -5, 0, 0 ), i jos jednu DummyCube ( 4, 0, -10 ) i u njoj GLCube ( 3, 0, 0 ). DummyCube ce nam sluziti da rotiramo nase objekte kako bi se oni s vremena na vreme dodirnuli. Dodajmo za DummyCube sa loptom Simple Intertia behaviour i postavimo RollSpeed na 50, i dodajmo za DummyCube koja sadrzi kocku takodje Simple Inertia behaviour i postavimo RollSpeed na 120. Posto smo koristili Simple Inertia moramo u uses dodati GLBehaviours unit. Pokrenimo program i videcemo kako se lopta i kocka okrecu i dodiruju se u odredjenim trenucima. Sada cemo dodati deo koji ce detektovati sudar. Dodajmo za loptu i kocku Collision behaviour. Ova osobina povezuje objekte sa CollisionManagerom i omogucava mu da odradjuje kad su se dodirnuli. Podesimo prvo Collision behaviour za loptu. Podesimo prvo Manager property na CollisionManager1 koji smo postavili na formu. Ovaj property oderdjuje koji ce manager biti zaduzen za ovaj objekat. Zatim BoundigMode postavimo na Sphere. Ovo je nacin na osnovu kojeg ce se odredjivati da li se objekat sudario. Kada je ovaj property on se tretira kao kocka u koju moze da stane ceo objekta, ako je Ellipsoid onda je to izduzena lopta, ako je Faces onda se koristi bas oblik objekta (ovo je najsporiji nacin), ako je Point koristi se samo tacka u sredini objekta (ubedljivo najbrzi i najneprecizniji nacin), i ako je sphere koristi se lopta u koji staje ceo objekat. Posto koristimo loptu logicno je da cemo izabrati Sphere. GroupIndex je property koji odredjuje sa kojim objektima ce biti proveravano da li su sudareni. Samo objekti sa istim GroupIndexom ce biti provereni da li se dodiruju. GroupIndex necemo dirati. Za kocku cemo postaviti Manager, a BoundingMode postaviti na Cube.
To je dovoljno informacija za CollisionManager da oderdi da li se nasi objekti dodiruju. Dodajmo sada globalnu promenljivu Sudar: Boolean koja ce biti True ako su se objekti sudarili i postavimo CollisionManager.OnCollision event na
procedure TForm1.CollisionManager1Collision(Sender: TObject; object1,   object2: TGLBaseSceneObject); begin   Sudar := True; end;
Ovaj event nam prosledjuje koji su se objekti sudarili. Ovo nam je vrlo vazno ako imamo vise objekata, ali u nasem slucaju imamo samo 2 pa znamo da su se oni sudarili i postavljamo Sudar na True.
Moramo i vizuelno prikazati da li su se objekti sudarili ili ne i to cemo uraditi bojama. Dodajmo jedan GLMaterialLibrary i napravimo material No koji ce biti plave boje i materijal Yes koji ce biti crvene. Postavimo za pocetak i za loptu i za kocku material No. Sada cemo u GLCadencer.OnProgress da detektujemo sudar i da promenimo boju objekata ako je potrebno
procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime,   newTime: Double); var   oldSudar: Boolean; begin   oldSudar := Sudar;   Sudar := False;   CollisionManager1.CheckCollisions;   if Sudar <> oldSudar then     if Sudar then     begin       GLSphere1.Material.LibMaterialName := 'Yes';       GLCube1.Material.LibMaterialName := 'Yes';     end     else     begin       GLSphere1.Material.LibMaterialName := 'No';       GLCube1.Material.LibMaterialName := 'No';     end; end;
oldSudar nam sluzi samo da ne bismo postavljali nov material pri svakom iscrtavanju jer do znatno smanjuje FPS. Prvo postavljamo Sudar na False (predpostavljamo da se objekti nisu sudarili) i onda pocivamo CollisionManager.CheckCollisions da proveri da li ima nekih sudara. Ako ima poziva se OnCollision event koji u nasem slucaju postavlja Sudar na True. U zavisnosti od vrednosti Sudar promenljive postavljamo boje nasih objekata. To je sve Smile



[url=https://www.mycity.rs/must-login.png

Dopuna: 19 Jul 2005 21:25

Napravio sam jedan kratak demo u kojem sam koristio ovo sto smo do sad odradili... ucitavanje 3d objekata, postavljanje textura, pomeranje i rotiranje objekata, efekte sa cesticama, zvukovi (Sound Emitter + pozadinska muzika)... mozda jos nesto, ali mislim da je to to... demo traje oko 60 sekundi, ali je exe (nema koda ovog puta... probajte sami da napravite nesto slicno Wink ) "malo" tezi zbog modela, textura i zvukova... ima oko 3MB. Nadam se da ce vam se svideti bar malo... izgubih skoro pola sata rada na ovome Smile
GeoCities nesto ne dozvoljava da se ovako velik fajl skine van njega morate otici ovde da bi ste skinuli program.
Imate u zipu sve sto je potrebno da pokrenete program. Model mozete slobodno koristiti u nekomercijalnim programima... pa... mozda neko napravi neki mnogo bolji demo od mene.

Ako neko nema dovoljno dobru karticu da pokrene demo evo par slicica







I... kako vam se cini demo?

Dopuna: 19 Jul 2005 21:28

U ovakvoj animaciji bi prilicno lepo izgledalo da Enterprise ispali laserski zrak na neki od asterioida i da se on raspadne. Zrak bi mogao vrlo lako da se naprvi koriscenjem ThorFX... vatra u eksploziji nekim od ParticlePFX managerom i sa nekim crvenim svetlom, ali raspad 3d objekta i nije bas tako lak... ili... da li je? Smile
U GLScene postoji ExplosionFx koji sluzi da "explodira" neki 3d objekat. Imajte na umu da ne mogu svi objekti da koriste ovaj efekat... samo oni koji sadrze podatke o mesh-u (vertexi, normale, koordinate textura) kao sto su GLFreeForm i GLActor.
Opet cemo koristiti Waste model. Postavimo na scenu kameru, svetlo i jedan GLFreeForm (0, 0, -4) objekat. Posto je Waste.md2 malo velik postavimo Scale na 0.05, 0.05, 0.05 i zbog razlike u orientaciji PitchAngle na 90. Sada da ucitamo nas model, a to vec znate kako se radi Smile
uses   GLFileMD2; procedure TForm1.FormCreate(Sender: TObject); begin   GLFreeForm1.LoadFromFile('waste.md2'); end;
Sada dodajmo ExplosionFx efekat GLFreeForm objektu.
Direction property odredjuje na koju stranu ce parcici objekta biti "oduvani". Ako je Directino 0, 0, 0 onda se razlecu na sve strane.
MaxSteps odredjuje koliko ce dugo u "koracima" ce explozija da traje dok objekat ne postane nevidljiv.
Speed je brzina kretanja delova.
Ovo je jedan od komponenti koja ima bug... sve sto se podesi u designtime ne utice na ExplosionFx tako da se svi parametri moraju podesavati u runtime... nista nije savrseno Smile
Bacimo jedan TButton na formu u kojem cemo podesiti sve sto nam je potrebno i pokrenuti exploziju
uses   GLExplosionFx; procedure TForm1.Button1Click(Sender: TObject); begin   with TGLBExplosionFx(GLFreeForm1.Effects.Items[0]) do   begin     MaxSteps := 0;     Speed := 0.1;     Enabled := True;   end; end;
U Cadencer.OnProgress dodajmo da svaki put iscrtava scenu (GLSceneViewer1.Invalidate) i pokrenimo program. Kada kliknemo da dugme objekat se raspada Smile



Problem je ako zelimo da imamo sacuvane podatke o objektu i posle explozije jer jexplizija menja koordinate vertexa i oni se vise ne mogu vratiti... zato ako je potrebno prvo treba napraviti kopiju objekta i tak onda pokrenuti exploziju. Dodacemo jos jedan GLFreeForm objekat koji ce nam cuvati podatke i u OnCreate eventu forme napisati
procedure TForm1.FormCreate(Sender: TObject); begin   GLFreeForm1.LoadFromFile('waste.md2');   GLFreeForm2.Assign(GLFreeForm1);   GLFreeForm2.Visible := False; end;
Time cemo sve podatke iz GLFreeForm1 prebaciti u GLFreeForm2 i postaviti da se drugi objekat ne vidi.
Sada jos samo da malo promenimo OnClick event dugmeta i mocicemo da klikcemo koliko hocemo i da nas objekat svaki put explodira iz pocetka
procedure TForm1.Button1Click(Sender: TObject); begin   TGLBExplosionFx(GLFreeForm1.Effects.Items[0]).Reset;   GLFreeForm1.Assign(GLFreeForm2);   GLFreeForm1.Visible := True;   with TGLBExplosionFx(GLFreeForm1.Effects.Items[0]) do   begin     MaxSteps := 0;     Speed := 0.1;     Enabled := True;   end; end;
Prvo sto radimo je zaustavljanje explozije, zatim prebacujemo podatke o izgledu objekta u GLFreeForm1 i postavljamo VIsible na true da bi se video... ostatak je poznat. Probajte sad program Smile

Explozija i nije mnogo realna... ali bar se lako koristi i bolja je nego nista Smile

[url=https://www.mycity.rs/must-login.png

offline
  • Pridružio: 01 Okt 2004
  • Poruke: 351
  • Gde živiš: Qrshumliya

Nikako ne mogu da instaliram zadnji GLScene. Fali mi neki dcu. PlugIn<Nesto>.dcu mislim da bese. Ima li jos neko ovih problema??

@Srki_82: Bravo care! Bas si me obradovao ovim!

offline
  • Strog  Male
  • Stručni saradnik
    Web programiranje
  • Bojan Kopanja
  • Web & Mobile developer @ ZeusSoftware
  • Pridružio: 26 Jul 2003
  • Poruke: 2597
  • Gde živiš: Stara Pazova

Jesi li dodao putanju do foldera u kojem ti je GLScene u Delphi okruzenje? Moras to uraditi ne samo za osnovni dir, nego i za svaki poddir pojedinacno, i onda mora da ti radi.

Znaci Tools>Enviroment Options... pa ondaidi na karticu Library i tu u polju Library Path dodaj putanje do svakog dira iz Source Direktorijuma iz direktorijuma GLScene.

Ajde javljaj ako opet zapne, pa da vidimo sta se dalje desava Smile.

offline
  • Srđan Tot
  • Am I evil? I am man, yes I am.
  • Pridružio: 12 Jul 2005
  • Poruke: 2483
  • Gde živiš: Ljubljana

Ako si skinuo ceo paket (zipovan ili slicno) onda je u najnovijoj verziji taj fajl zaboravljen, ali uopste nije bitan za rad GLScene. Ni jedan primer ga ne koristi... ustvari... niko, cak ni kreator GLScene, ne koristi taj unit tako da slobodno mozes da ga izbacis iz paketa i da kompajliras tako.

offline
  • Pridružio: 01 Okt 2004
  • Poruke: 351
  • Gde živiš: Qrshumliya

Proradilo
Hvala

offline
  • Strog  Male
  • Stručni saradnik
    Web programiranje
  • Bojan Kopanja
  • Web & Mobile developer @ ZeusSoftware
  • Pridružio: 26 Jul 2003
  • Poruke: 2597
  • Gde živiš: Stara Pazova

U cemu je bio problem, kako je proradilo? Ajde opisi ovde to malo, ako jos nekome zatreba...

Ko je trenutno na forumu
 

Ukupno su 1153 korisnika na forumu :: 53 registrovanih, 7 sakrivenih i 1093 gosta   ::   [ Administrator ] [ Supermoderator ] [ Moderator ] :: Detaljnije

Najviše korisnika na forumu ikad bilo je 3466 - dana 01 Jun 2021 17:07

Korisnici koji su trenutno na forumu:
Korisnici trenutno na forumu: 357magnum, A.R.Chafee.Jr., babaroga, Bluper, Bobrock1, bokisha253, cavatina, comi_pfc, Dannyboy, Dežurni pod palubom, Dimitrije Paunovic, djboj, dragan_mig31, Excalibur13, FOX, Georgius, HrcAk47, ikan, Ivica1102, kikisp, Krusarac, ljuba, Mali Veseljak, Mcdado, mercedesamg, mikrimaus, Millennium, milutin134, MiroslavD, Mlav, mnn2, Nemanja.M, nenad81, nick79, operniki, ozzy, pein, procesor, repac, ruso, sabros, Simon simonović, stagezin, Stefan M, StefanNBG90, styg, USSVoyager, Valter071, W123, zdrebac, zillbg, zziko, 79693