Bezier
Plan
Grafikk
Børre Stenseth
Å tegne:>Påskeegg

Påskeegg

Hva

Problemet er kort og godt å tegne et påskeegg. Vi skal tegne et egg helt og delt med og uten en kylling.

chick

La oss begynne med å gjøre noen betraktninger av formen på et egg.

proegg

Vi regner med at egget kan framstilles som rundt, sirkulært, på tvers av lengderetningen. I lengderetningen finner vi en form som burde kunne framstilles ved et polygon. Vi har mange måter å lage sirkler på og en mulig framgangsmåte må være å lage en rekke sirkler med varierende radius, avhengig av polygonet, og på denne måten bygge en "maske" av så små flater som vi måtte ønske. Vi kunne så tegne disse flatene med glBegin(GL_TRIANGLE_STRIP) og med glatting skrudd på. Dette er en framgangsmåte som ligner på den vi som er brukt i framstillingen av en smultring i modulen Smultring.

Vi vil imidlertid i dette eksempelet se om det er mulig å gjøre dette med mindre "håndarbeid".

Bezierkurver

Vi vil prøve å modellere egget ved hjelp av en Bezierflate. Vi begynner resonnementet med å slå fast at vi har en form som er symmetrisk om et plan som går gjennom eggets lengdeakse. Dette må vi kunne benytte når vi leter etter en formulering av Bezierflaten.

Vi begynner med å betrakte de to formene, sirkelen på tvers av lengderetningen og den "skjeve" ellipsen langs lengderetingen. Du kan eksperimentere med to enkle 4-punkts Bezierkurver nedenfor for å se litt på mulighetene:

Applet failed to run. No Java plug-in was found.

Som du oppdager er det lagt inn noen sperrer på bevegelsen for å opprettholde noen føringer som må være tilstede for å sikre en form som er egglik. Føringener i korthet slik at den deriverte i kurvenes endepunkter er vinkelrette på snittaksen. Da oppnår vi en glatt form i eggets ender og vi oppnår at vi ikke får diskontinuitet i vårt forsøk på å skjøte to halvsirkler.

Nå vil vi få problemer med å lage en matematisk korrekt halvsirkel med en slik Bezierkurve. Det trenger kanskje ikke bekymre oss siden det ser ut til at vi kommer tilstrekkelig nær en sirkelform til at det er akseptabelt for å vise fram et egg.

Vi ser imidlertid at vi har et annet problem. Vi får ikke kontrollpunktene langs de to snittene til å harmonere slik at samme punktsett kan bidra til både å lage en passe stor "sirkel" og en fornuftig eggform i lengderetningen.

En Bezier-flate

Vi prøver å løse problemet med å bruke flere kontrollpunkter. Figuren endenfor viser et forsøk på å beskrive et "skrog" av kontrollpunkter som vi kan eksperimenetere med.
skrog

Data beskrivelsen av dette skroget kan være som følger:

// dimensions and controlpoints
float EGGLENGTH    =7.0f;
float ctr1=0.3f*EGGLENGTH;
float ctr2=0.7f*EGGLENGTH;
float ctr3=0.3f*EGGLENGTH;
// offset along z
float ctz1=0.0f*EGGLENGTH;
float ctz2=0.3f*EGGLENGTH;
float ctz3=1.0f*EGGLENGTH;
float ctz4=EGGLENGTH;
// factor for circlecompensation
float rf=1.35f;
//M[UN][VN][3]
float []M=    // ctrl point map
{
        //u=0 -> endpoint z=0
        0.0f,    0.0f,    0.0f,//v=0
        0.0f,    0.0f,    0.0f,//v=1
        0.0f,    0.0f,    0.0f,//v=2
        0.0f,    0.0f,    0.0f,//v=3
        0.0f,    0.0f,    0.0f //v=4
    ,
        //u=1
        ctr1,    0.0f,    ctz1,//v=0
        ctr1,    ctr1,    ctz1,//v=1
        0.0f,    rf*ctr1,    ctz1,//v=2
        -ctr1,    ctr1,    ctz1,//v=3
        -ctr1,    0.0f,    ctz1 //v=4
    ,
        //u=2
        ctr2,    0.0f,    ctz2,//v=0
        ctr2,    ctr2,    ctz2,//v=1
        0.0f,    rf*ctr2,    ctz2,//v=2
        -ctr2,    ctr2,    ctz2,//v=3
        -ctr2,    0.0f,    ctz2 //v=4
    ,
        // u=3
        ctr3,    0.0f,    ctz3,//v=0
        ctr3,    ctr3,    ctz3,//v=1
        0.0f,    rf*ctr3,    ctz3,//v=2
        -ctr3,    ctr3,    ctz3,//v=3
        -ctr3,    0.0f,    ctz3 //v=4
    ,
        //u=4  -> endpoint z=EGGLEN
        0.0f,    0.0f,    ctz4,//v=0
        0.0f,    0.0f,    ctz4,//v=1
        0.0f,    0.0f,    ctz4,//v=2
        0.0f,    0.0f,    ctz4,//v=3
        0.0f,    0.0f,    ctz4 //v=4
    
};

De interessante verdiene som vi kan eksperimenetere med er:

EGGLENGTH=eggL;
EGGLENGTH	=7.0f;

ctr1=0.3f*EGGLENGTH;
ctr2=0.7f*EGGLENGTH;
ctr3=0.3f*EGGLENGTH;
// offset along z
ctz1=0.0f*EGGLENGTH;
ctz2=0.3f*EGGLENGTH;
ctz3=1.0f*EGGLENGTH;
ctz4=EGGLENGTH;

Gitt denne databeskrivelsen kan et enkelt egg tegnes slik:

_oneEgg.java

Et delt egg

Dette løser vi ved å tegne egget to ganger med klippeplan. OpenGL lar oss definere klippeplan i modellen. Algoritmen nedenfor er basert på at eggets lengderetning er langs z-aksen. Plan er definert som: ax+by+cz+d=0. Koeffisientene a, b, c angir normalen på planet og d finner vi dersom vi setter inn for et punkt i planet. a, b, c og d setter vi opp med funksjonen glClipPlane.

Vi ser nedenfor at det første planets normal faller sammen med den negative z-aksen og at det ligger i avstanden CutOff fra xy-planet.

_oneEgg.java

Programmet egg tegner dessuten ut en kylling når egget er delt.

Programmet (JOGL/Netbeans): https://svnit.hiof.no/svn/psource/JOGL/egg
Vedlikehold
B.Stenseth, revidert april 2010
Å tegne:>Påskeegg
til toppen