En 3D-Applet
Den 3-dimensjonale modelleringen er implementert i en klasse gob, med tre indre klasser, hjelpeklasser, p3D, matrise og polygon. Et gob-objekt koples opp mot et Component-objekt i Java. Det innebærer at en applet kan inneholde andre ting enn det området som viser fram projeksjonen av en 3D-modell. I prinsipp kan det være flere gob-objekter aktive samtidig i en applet.
gob benytter de vanlige 2D-rutinene i Java.awt ved rendering.
Metoder
Metodene i gob-klassen er:
- gob(Component comp)
Setter opp et grafisk objekt mot componentet comp. Setter opp defaultverdier for polygonfarge og bakgrunnsfage. Setter opp en parallellprojeksjon og en viewport som er lik componentens dimensjoner. - clearAll()
Nullstiller modelmatrisa og fjerner lista over polygoner som skal rendres. - drawBox(float dx, float dy, float dz, int mode)
Dette er en hjelpefunksjon som tegner en boks med sidene dx,dy og dz, med antatt origo i sentrum. Mode kan være gob.FILL eller gob.FRAME. - flush()
Rendrer alle oppgitte polygoner til skjermen. - pBegin(int mode)
Oppretter et polygon og er klar til å ta imot polygonets hjørner. mode kan være gob.FILL eller gob.FRAME. - pEnd()
Avslutter et polygon. - popMatrix()
Popper siste matrise av stakken, og bruker denne som modellmatrise. - pushMatrix()
Pusher nåværende modelmatrise på stakken. - rotateX(float v)
Roterer v radianer om x-aksen. - rotateY(float v)
Roterer v radianer om y-aksen. - rotateZ(float v)
Roterer v radianer om z-aksen. - scale(float sx,float sy,float sz)
Skalerer med faktorene sx, sy, sz, om origo. - translate(float tx,float ty,float tz)
Paralellforskyver med faktorene tx, ty, tz, om origo. - setBackground(Color c)
Setter bakgrunnsfargen til c - setImage(Image im)
Legger bildet im i bakgrunnen, justert oppe til venstre i viewport - setColor(Color c)
Gir denne fargen til polygoner som tegnes før neste farge eventuelt settes. - setIdentityMatrix()
Setter modelmatrise til identitetsmatrisa. - setOrtho(float xl, float yt, float dx, float dy)
Paralellprojeksjon ned i xy-planet. Den delen av xy-planet som er avgrenset av parametrene mappes til viewport. - setPerspective(float xv, float yv)
Angir "linseåpning" ved en perspektivprojeksjon. xv og yv oppgis i grader. Øyet i origo, synsretning langs den negative z-aksen. Ingen klipping. - setViewport(float xl,float yt,float w, float h)
Angir hvor projeksjonen skal mappes. Parametrene er relativt til gob-objektets Component. - vertex(float x, float y, float z)
Angir et hjørne i et polygon.
Lys
Det finnes kun en lyskilde. Den gir retingsbestemt lys langs z-aksen. Siden øyet er plassert i origo og synsretningen er nedover z, så opptrer lyset som en hodelykt. Lyset er hvitt.
Det kan være en fornuftig utvidelse og introdusere en bedre lysmodell
Skjulte flater
Polygonene sorteres etter fjerneste punkt, og lista med polygoner tegnes bakfra. Fjerneste punkt betyr det punktet i polygonet som har størst negativ z-verdi, siden vi har øyet fast i z og ser nedover z-aksen. Dette er en slags implementasjon av Painters algoritme.
Dette er ikke vanntett, men går bra for de fleste "rimelige" figurer. Konkave polygoner kan skape problemer, og vi får av og til problemer med flater som ligger i et bestemt forhold til hverandre.
Det kan være en fornuftig utvidelse og introdusere en bedre flatesortering
Klipping
Det foregå ingen klipping internt i gob. Den eneste klippingen som foregår er når projeksjonen mappes til viewport. Viewportkantene klippes med hjelp av Java.awt mekanismer når det rendres til bakgrunnsbufefren, se nedenfor.
Projeksjon
Det er to alternative projeksjoner: parallellprojeksjon (angitt ved setOrtho) og perspektivprojeksjon (angitt ved setPerspective).
Paralellprojeksjonen er rett fram: z-koordinaten fjernes og vi sitter igjen med et 2D-polygon som mappes fra World til Viewport.
Perspektivprojeksjonen er litt mer involvert. Avstanden fra øyet må tas i betaktning.
Vi bestemmer oss for å projisere inn i et område som ligger d fra øyet, og vi bestemmer oss for at projeksjonsplanet er 0.5 x 0.5. Vi skal altså finne Q.
Vi kan sette opp:
- tg(Vx)=0.5/d
- P.x/P.z=Q.x/d.
Vi eliminerer d og finner Q.x=(P.x*0.5)/(tg(Vx)*P.z). Vi kan gjør et helt tilsvarende resonnement for y.
Så kan vi mappe fra kvadratet (-0.5,-0.5) - (0.5,0.5) til viewport.
Viewport
Viewport kan i prinsipp ordens på en av to måter. Enten kan viewport alltid settes til hele den komponeneten gob arbeide mot, eller så kan viewport spesifiseres som en del av denne komponeneten. Det er den siste varianten som er valgt. Det gir en ekstra frihetsgrad til å arbeide på en komponent, feks. kan vi legge tekst utenfor selve 3D tegningen i komponenten. default er viewport lik hele komponenten.
Dobbel buffering
Metoden flush rendrer alle polygonene til en egen bakgrunnsbufefr. Når denne jobben er gjort kopieres bakgrunnsbufferen ut til gobs komponent.
//Image Buffer.. er satt like stor som komponenten .. Graphics tmpg=Buffer.getGraphics(); tmpg.setColor(BKColor); // fill background tmpg.fillRect(< viewport>); // possible background image if(theImage!=null) tmpg.drawImage(< viewports uppeleft>,BKColor, null); // polygons in list for(int ix=0;ix< drawList.size();ix++) ((polygon)drawList.elementAt(ix)).render(tmpg); // copy to viewport g.clipRect(< viewport>); g.drawImage(Buffer,0,0,null);
Merk at for å unngå flimring så må den appleten som bruker gob implementere:
public void update(Graphics g) { paint(g); }
Dette kortslutter den blankingen som awt ellers legger inn.
Bruker Applet
Du står selvsagt fritt i hvordan du benytter gob. En typisk applet, som kan tjene som et skjelett er denne som slår sammen gob og klossehandteringen: a3dboxes.java Det er denne som kjører på toppen av siden. Du vil finne andre eksempler på de neste sidene.
Hvorvidt du ønsker å benytte gob som egen package eller om du vil slå sammen gob og appleten i en package er opp til deg.