Grafikk
Børre Stenseth
Å tegne:>Smultring

Torus

Hva

Smultringen er komplett beskrevet ved de to aktuelle radiene: en hovedradius på R og radien i selve smultringens kropp r. Vi ønsker å finne to parametre som kombinerer de to rotasjonene som er nødvendige for å identifisere et punkt entydig, en om hovedaksen og en om selve smultiringkroppens akse.

newtorus

Vi lar w beskrive rotasjonen om selve smultringens hovedakse, "hullet", og lar v beskrive rotasjonen rundt selve smultringkroppen. Vi tegner smultringen i to projeksjoner:

torus

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)
  
dobeltorus

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.

_Torus.java
zoomable

Form

Deler av hovedklassen

_TorusAgain.java

The renderer:

_GLRenderer.java

kode

  • Det animerte, musedrevne prosjektet(JOGL/Netbeans): https://svnit.hiof.no/svn/psource/JOGL/torus
  • prosjektet med grafikken på en form(JOGL/Netbeans): https://svnit.hiof.no/svn/psource/JOGL/torusAgain
Vedlikehold
Modifisert april 2010, Børre Stenseth
Å tegne:>Smultring
til toppen