Prikaz jedne kocke
Uobičajen način crtanja kocke ili bilo kojeg drugog elementa poput kugle, valjka, piramide i dr. jeste crtanje mreže trokuta koja će to tijelo obuhvatiti i definirati. Pošto je HOOPS 3D alat više razine od OpenGl-a i DirectX-a osim ovakvog načina crtanja postoji i napredniji način, tj. postoje već ugrađene funkcije za crtanje jednostavnijih oblika. To nije samo jednostavna mreža koju program stvori umjesto nas već posve novi objekt sa svojim svojstvima i mogućnostima. Nešto poput objekata u objektno orjentiranim jezicima.
key_box = HUtility::InsertBox( max, min );
Za stvaranje objekta kocke koristimo ovu naredbu. Njena namjena je stvaranje kvadra pomoću dvije suprotne prostorne koordinate. Laički rečeno, pomoću gornjeg lijevog stražnjeg i donjeg desnog prednjeg vrha kvadra. Posebno treba paziti na redoslijed zadavanja vrhova jer oni određuju orijentaciju normala na svakoj od šest strana kvadra, tj. određuju orijentaciju samog kvadra.
Ovako stvorene kocke nisu samo mreža trokuta spojenih na način da predstavljaju kocku. Čitava mreža s osvjetljenjem, rubovima, prikazom, vlastitim lokalnim koordinatnim sustavom i dr. čini jedan objekt, odnosno jednu geometriju. Ova geometrija se dalje nalazi unutar nekog segmenta koji predstavlja skup geometrija i drugih segmenata koji su na neki način međusobno povezani. Čitav prikaz u samom HOOPS 3D alatu je jedan segment. Na ovaj način HOOPS 3D raščlanjuje sve elemente prikaza. Može se reći da je čitav prikaz stablasta struktura segmenata i geometrija.
Manipulacija svojstvima objekata
Sve se opcije, poput boje, osvjetljenja, prikaza pojedinih elemenata i dr, mogu mijenjati na razini segmenta ili geometrije. Ako postavimo neke opcije na vrhovnom segmentu svi podsegmenti i njihove geometrije će naslijediti te opcije. No, ako promijenimo neku opciju na nižoj razini, bilo na nižem segmentu ili geometriji, ta opcija će prevladati nad opcijom zadanoj na višoj razini, odnosno u roditeljskom segmentu. Problemi nastaju kad ponovno pokušamo promijeniti neku od opcija u roditeljskom segmentu koju smo već mijenjali na segmentu ili geometriji niže razine. Promjena na segmentu više razine neće nadjačati promjenu na nižoj razini. Da bismo to postigli moramo onemogućiti promjenu na nižoj razini.
Na slici su prikazani neki rezultati manipilacije samo tri svojstva, prikaza ruba (engl. edge), prikaza poligona (engl. face) i korištenja osvjetljenja. Korišteni kod za ovu manipulaciju je sljedeći:
HC_Set_Visibility( "edges=on, faces=off, lights=off " );
HC_Set_Visibility( "edges=off, faces=on, lights=off" );
HC_Set_Visibility( "edges = on, faces = on, lights = off" );
HC_Set_Visibility( "edges = on, faces = on, lights = on" );
Primijećeno je da ovakva manipulacija svojstava ima velikog utjecaja na brzinu iscrtavanja. Jednostavna promjena iscrtavanja rubova objekta može imati velikog utjecaja na brzinu iscrtavanja ovisno o broju objekata koje se iscrtava.
Selekcija pojedinih kocaka oktalnog stabla
Selekcija prikazanih objekata unutar HOOPS 3D prikaza nije tako složena kako bi se očekivalo. Dok bismo kod OpenGl-a sami morali računati selekciju kod HOOPS 3D alata je ona gotovo automatska. Sve što je potrebno je izabrati željenu selekciju i unijeti potrebne koordinate. Koordinate koje se unose su iz lokalnog koordinatnog sustava pogleda. HOOPS 3D će napraviti potrebnu pretvorbu iz lokalnog u globalni koordinatni sustav.
Osnovna naredba za selekciju je sljedeća:
int pom = HC_Compute_Selection( "?picture", 0, "^", event.GetMouseWindowPos().x, event.GetMouseWindowPos().y );
Ova naredba služi samo za pokretanje procesa selekcije. Predajemo joj koordinate na kojima želimo izvršiti selekciju i daljnji posao prepuštamo njoj. Nakon što se ona izvrši pokrećemo proces dohvata rezultata. Ova naredba nam ne vraća rezultat selekcije. Naredba vraća samo oznaku da li je selekcija bila uspješna, odnosno da li je nešto selektirano ili ne.
Proces dohvata rezultata selekcije je sljedeći:
if( pom > 0 )
{
HC_KEY* key = new HC_KEY[ pom ];
int* d1 = new int[ pom ];
int* d2 = new int[ pom ];
int* d3 = new int[ pom ];
HC_Show_Selection_Element( key, d1, d2, d3 );
}
Nakon provjere da li je uopće došlo do selekcije možemo tražiti konkretnu selekciju. Rezultat selekcije dobivamo pomoću skupa naredbi „Show_Selection()“. Ove naredbe nam služe za povrat informacija o izvedenim selekcijama.
Naravno, osim selekcije jednog elementa možemo vršiti i selekcije većeg broja elemenata. Navedena naredba nam neće selektirati samo jedan element već će nakon pronalaska jedne selekcije nastaviti pretragu za drugim elementima koji se nalaze na istim koordinatama. Jedina razlika ove selekcije i selekcije jednog elementa je u dohvatu rezultata:
if( pom > 0 )
{
do
{
HC_KEY* key = new HC_KEY[ pom ];
int* d1 = new int[ pom ];
int* d2 = new int[ pom ];
int* d3 = new int[ pom ];
HC_Show_Selection_Element( key, d1, d2, d3 );
} while( HC_Find_Related_Selection() );
}
Jedina razlika je u petlji koja se vrti dok god u memoriji ima selektiranih elemenata. Rutina „Show_Selection()“ vraća informaciju o najboljem selektiranom elementu. Pod najboljim elementom se smatra onaj najbliži pokazivaču prilikom selekcije (koordinatama selekcije). Ako se ispod pokazivača nalazi više od jednog elementa onda je to onaj najbliži kameri (očištu). Rutina „Find_Related_Selection()“ traži sljedeću najbolju selekciju pri svakom pozivu i odbacuje trenutnu najbolju. Kad više nema selektiranih elemenata rutina vraća laž (engl. false).
Možemo zaključiti da ovaj algoritam nije optimalan za situacije kada želimo selektirati samo jedan element, a ispod pokazivača se nalaze milijuni drugih elemenata. Ovaj oblik selekcije bi bespotrebno zauzimao previše resursa i bespotrebno bi usporavao čitav proces. Da se takve stvari ne bi dešavale uvedena je opcija ograničenja dubinske pretrage selekcije. Opcija se postavlja pomoću sljedeće naredbe:
void Set_Heuristics (const char *list)
„Heuristika“ u HOOPS-u je pretpostavka o prikazu koju programer predaje sustavu. Razlog postojanja ovih pretpostavki je smanjenje vremena potrebnog za osvježenje prikaza, smanjenje vremena potrebnog za spremanje podataka u bazu podataka ili veličina baze podataka potrebna da se svi ti podaci spreme. Generalno, da biste dobili što efikasniji rad programa trebate sustavu predati sve optimizacijske pretpostavke koje znate. Lista heuristika se sustavu predaje kao znakovni niz pri čemu su različite specifikacije odvojene zarezom.
Što se tiče specifikacija za selekcije, zanimljiva nam je samo jedna:
HC_Set_Heuristics( "related selection limit = broj_ograničenja" );
Ova specifikacija nam govori koliko daleko da idemo sa potragom za elementima koje možemo selektirati. Ako ništa ne odaberemo imat ćemo inicijalnu specifikaciju koja kaže da pretraga traje dok osim prvog elementa ne nađemo još dodatnih pet osim ako dođemo do kraja pretraživanja. Vidimo da specifikaciju ne možemo postaviti na nula elemenata jer bi takva selekcija bila beskorisna. Možemo naznačiti samo koliko daleko da se ide nakon prvog pronađenog elementa. Ukoliko želimo selektirati samo jedan element umjesto da stavljamo da je broj_ograničenja jednak nuli možemo napisati i sljedeću naredbu:
HC_Set_Heuristics( "no related selection limit" );
Kod naredbe „Set_Heuristics()“ postoji jedna značajna razlika od ostalih naredbi. Razlika je u mjestu pisanja ove naredbe. Dok se ostale naredbe pišu unutar segmenta modela „Set_Heuristics()“ se piše unutar segmenta pogleda. Ako se ipak napiše unutar segmenta modela među ostalim naredbama neće imati nikakvog utjecaja na rad samog programa. Dodatna primjedba na rad ove naredbe je ta da sustav ne mora prihvatiti specifikacije zadane putem ove naredbe.
Osim točkaste selekcije gdje selektiramo jedan element koji se nalazi direktno ispod pokazivača ili cijeli niz elemenata koji se sijeku sa pravcem koji prolazi kroz vrh pokazivača i okomit je na ekran imamo i druge vrste selekcija:
int Compute_Selection_By_Key ( const char * action, const char * start_seg, HC_KEY key, const float * matrix )
Ova selekcija se koristi za računanje kolizije zbog svoje specifičnosti selektiranja. Naredbi se predaje volumen definiran svojom ljuskom na osnovu kojeg se dohvaćaju informacije svih objekata koji diraju zadani volumen.
int Compute_Selection_By_Shell (const char *action, const char *start_seg, const int pcount, const HC_POINT *points, const int flist_length, const int *face_list)
Slično naredbi Compute_Selection_By_Key s tim da ne zahtijeva već postojeću ljusku.
int Compute_Selection_By_Ray (const char *action, const char *start_seg, const HC_POINT *start_point, const HC_POINT *direction)
Zraka je definirana sa svojom početnom točkom i smjerom. Kao selekcija se uzimaju svi objekti „probodeni“ tom zrakom.
int Compute_Selection_By_Area ( const char * display, const char * start_seg, const char * action, double left, double right, double bottom, double top )
Selekcija nad područjem definiranim pravokutnikom. Parametri „left“, „right“, „bottom“ i „top“ označavaju koordinate koje čine taj pravokutnik. Koordinata (left, top) čini gornji lijevi kut dok koordinata (right, bottom) čini donji desni kut pravokutnika. Pretpostavka je da su stranice pravokutnika paralelne sa stranicama zaslona.
int Compute_Selection_By_Polygon ( const char * display, const char * start_seg, const char * action, int pcount, const HC_POINT * points )
Slično kao kod prošle selekcije samo što područje selekcije nije pravokutnik već poligon.
int Compute_Selection_By_Polylin ( const char * display, const char * start_seg, const char * action, int pcount, const HC_POINT * points )
Istovjetno sa prošlom selekcijom.
int Compute_Selection_By_Volume ( const char * display, const char * start_seg, const char * action, double left, double right, double bottom, double top, double hither, double yon )
Slično Compute_Selection_By_Area s tim da u ovom slučaju selekcija nije određena plohom već volumenom. Dok smo kod selekcije s pravokutnikom selektirali sve što se nalazilo unutar pravokutnika neovisno o dubini selekcije ovdje smo i dubinski ograničeni.