Torus
Vi lar w beskrive rotasjonen om selve smultringens hovedakse, "hullet", og lar v beskrive rotasjonen rundt selve smultringkroppen. Vi tegner smultringen i to projeksjoner:
Ved å studere de to projeksjonene kan vi overbevise oss om at punktet p's koodinater er:
z=r.sin(v) y=(R+r·cos(v))sin(w) x=(R+r·cos(v))cos(w)
Vi kan altså beskrive et vilket som helst punkt på smultringensoverflate ved de tre parametriske ligningene ovenfor. Da er vi også i stand til å avgrense flater på smultringoverflaten med nødvendig presisjon.
Flatene i smultringen kan genereres som polygoner der vi lar de to rotasjonsvinkelene gjennomløpe en full sirkel i en dobbeltløkke. Normalen i hvert punkt kan vi finne ved å tenke oss en "omhyllende" smultring. Normaler vil gå fra den indre smultringen til den ytre, med samme vinkelverdier.
public void drawTorus(float R, float r, int N, int n) { int maxn= 1000; // max precision n=Math.min(n,maxn-1); N=Math.min(N,maxn-1); float rr=1.5f*r; double dv=2*Math.PI/n; double dw=2*Math.PI/N; double v=0.0f; double w=0.0f; // outer loop while(w<2*Math.PI+dw) { v=0.0f; gl.glBegin(GL.GL_TRIANGLE_STRIP); // inner loop while(v<2*Math.PI+dv) { gl.glNormal3d( (R+rr*Math.cos(v))*Math.cos(w)-(R+r*Math.cos(v))*Math.cos(w), (R+rr*Math.cos(v))*Math.sin(w)-(R+r*Math.cos(v))*Math.sin(w), (rr*Math.sin(v)-r*Math.sin(v))); gl.glVertex3d((R+r*Math.cos(v))*Math.cos(w), (R+r*Math.cos(v))*Math.sin(w), r*Math.sin(v)); gl.glNormal3d( (R+rr*Math.cos(v+dv))*Math.cos(w+dw)-(R+r*Math.cos(v+dv))*Math.cos(w+dw), (R+rr*Math.cos(v+dv))*Math.sin(w+dw)-(R+r*Math.cos(v+dv))*Math.sin(w+dw), rr*Math.sin(v+dv)-r*Math.sin(v+dv)); gl.glVertex3d((R+r*Math.cos(v+dv))*Math.cos(w+dw), (R+r*Math.cos(v+dv))*Math.sin(w+dw), r*Math.sin(v+dv)); v+=dv; } // inner loop gl.glEnd(); w+=dw; } //outer loop }
Tegnestrategien over kan klart effektiviseres. Ved å ta vare på verdier for "neste" runde kan vi redusere antall beregninger. Vi bør dessuten absolutt lage dislaylister.
DisplayLister
Introduksjon displaylists er gansle rett fram. Vi produserer lista når vi initialiserer:
final static int THE_TORUS=5; ... theTorus=new oneTorus(gl); gl.glNewList(THE_TORUS, GL.GL_COMPILE); theTorus.drawTorus(3.0f, 1.0f, 20, 20); gl.glEndList();
Vi bruker listene når vi tegner:
... stdMaterials.setMaterial(gl, stdMaterials.MAT_EMERALD, GL.GL_FRONT); gl.glCallList (THE_TORUS); gl.glTranslatef(4.0f,0.0f,0.0f); gl.glRotatef(90.0f,1.0f,0.0f,0.0f); stdMaterials.setMaterial(gl, stdMaterials.MAT_GOLD, GL.GL_FRONT); gl.glCallList (THE_TORUS); ...
Dette programmet inneholder bådetegnemetodene og main i samme kodefil. Koden er ganske lik standard programmet som genereres av NetBeans: JOGL Application. Det som er lagt til er MouseListenerog MouseMotionListener.
Form
Deler av hovedklassen
The renderer: