Børre Stenseth
Forklaring av>Modell til skjerm>3D-Applet

En 3D-Applet

Hva
Applet failed to run. No Java plug-in was found.
En 'hjemmelaget' applet som framstiller enkel 3D, uten bruk av OpenGL. Grunnleggende transformasjonene fra modell til skjerm

Hensikten er ikke å lage en komplett 3D-pakke eller å konkurrere med de 3D-appletene som finnes tilgjengelig, se f.eks. anfy, blaxxun eller shout3d. Hensikten er å lage noe som er enkelt, oversiktlig og utvidbart.

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.

perspec

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.

Referanser
  • Modulen Modell til skjerm
  • Kildekoden til klassen gob: gob.java
  • Komplett applet: a3dboxes.java
Vedlikehold
Modifisert juni 2002, Børre Stenseth
(Velkommen) Forklaring av>Modell til skjerm>3D-Applet (Falling)