Bezier
Kenneth Stigen / Student 2002
Å tegne:>Bildebok

Bildebok

Hva
closed
Demonstrasjon av bezier, teksturer og animasjon

Hensikten er å modellere en bok som det skal være mulig å bla i. Boken skal oppføre seg som en vanlig bok, der siden bøyes når en blar. Temaer som denne modulen kommer til å sette fokus på, vil da være bezierflater og teksturbehandling. Målet med modulen er at leseren enkelt og greit skal kunne sette seg ned og lage en enkel applikasjon med en bezierflate og legge tekstur på denne. Det er også meningen at leseren skal få et innblikk i hvordan en kan sette opp et enkelt skjelett for animasjon.

Modulen er bygget opp med en gjennomgang av grunnleggende operasjoner med både bezierflater og teksturer. Jeg vil prøve å legge ut en "tutorial" med små enkle eksempler om de aktuelle temaene. Jeg vil til slutt prøve å summere alt opp i mitt ferdige program som er bildeboken.

Bezierflate

En bezierflate er en flate spesifisert av x,y og z koordinater. Man bruker en slik flate i tilfeller der en ikke kan klare seg med enkle figurer som sylindre, sirkler o.l.

Det kan først være en ide å beskrive en bezierkurve og hvordan kontrollpunktene fungerer. La oss tenke oss at vi har en kurve som har 4 kontrollpunkter. Et punkt på hver ende av linjen, og to midt på. Dette kan illustreres slik:
kurve1
Linjen vil alltid henge fast i endepunktene, men ikke nødvendigvis i de to på midten. For å få en annen kurve på linjen kan man flytte på disse punktene:
kurve2
Det samme prinsippet gjelder når en lager en bezier-flate. Endepunktene henger også her fast, mens alle andre kontrollpunkter er punkter som er med på å forme kurven.

For å lage en slik flate er det et par ting som må gjøres:

  1. Sett opp kontrollpunkter
  2. Kall map
  3. Kall mapGrid
  4. Kall evalMesh

Et eksempel på prosessen å tegne ut en slik flate kan være:

...
float kontrollpunkter[] = {
	0.6f, -2.0f,0.0f,  4.0f,-2.0f,0.0f,
	0.6f, -1.0f,0.0f,  4.0f,-1.0f,0.0f,
	0.6f, 1.0f,0.0f,  4.0f,1.0f,0.0f,
	0.6f, 2.0f,0.0f,  4.0f,2.0f,0.0f,
};

gl.glMap2f(GL_MAP2_VERTEX_3,0.0f,1.0f,3,2,0.0f,1.0f,6,4, kontrollpunkter);
gl.glMapGrid2f(20,0.0f,1.0f,20,0.0f, 1.0f);
gl.glEvalMesh2(GL_LINE, 0, 20, 0, 20);
...
			

Denne koden vil tegne ut denne flaten:
bezier1
Det er nødvendig å forklare litt mer om metoden gl.glMap2f. Denne metoden tar inn en del parametre:

                                      1 2           3 4
gl.glMap2f(GL_MAP2_VERTEX_3,0.0f,1.0f,3,2,0.0f,1.0f,6,4, kontrollpunkter);
			

Legg merke til verdiene i kommandoen som har tall over seg. Dette er de viktigste parametrene som en må forstå for å kunne tegne ut en enkel flate. Forklaringen er som følger:

  1. Antall verdier for hvert punkt
  2. Antall punkter for hver del av flaten
  3. Antall koordinater for hver del (a*b)
  4. Antall deler

Tekstur

Denne delen tar for seg en grunnleggende del av det å bruke teksturer. Den vil fokusere på å legge en tekstur på bezierflate.

For å legge en tekstur på en flate trenger man å gjøre følgende operasjoner

  1. Gjøre klart bildet
  2. Laste det
  3. Spesifisere kontrollpunkter for bildet
  4. "Mappe" det
  5. Tegne det ut

Et viktig moment med tanke på selve bildet er at det må være på et spesielt format. Bildet må være av størrelse 2x x 2y. Dette er typisk et bilde med for eksempel width: 128, height: 256.

Før en kan tegne ut bildet må man laste det. Her har man mange forskjellige opsjoner en kan velge. Jeg kommer ikke til å gå inn på disse her. En måte å laste bildet på er å lage en metode som tar inn et parameter; filnavn, og som gjør resten av jobben med lastingen. En slik metode kan være:

public void loadGLTexture(String filename){
	PngTextureLoader texLoader = new PngTextureLoader(gl, glu);
    texLoader.readTexture(filename);
    if(texLoader.isOk()){
    	gl.glGenTextures(1, texture);
    	gl.glBindTexture(GL_TEXTURE_2D, texture[0]);
    	gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
      	gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      	gl.glTexImage2D(GL_TEXTURE_2D,
        	0,
        	3,
        	texLoader.getImageWidth(),
        	texLoader.getImageHeight(),
        	0,
        	myParent.GL_RGB,
			myParent.GL_UNSIGNED_BYTE,
        	texLoader.getTexture()
		);
	}
}
		

En ting som er verdt å nevne i sammenheng med denne metoden, er at denne laster bilder som er på png-format. Man er ikke begrenset til å bare bruke png-bilder, men jeg vil ikke omtale, andre formater her.
Man kaller da metoden slik:

loadGLTexture("picture.png");
		

Det neste som må gjøres, er å spesifisere kontrollpunkter for bildet. For å få et bilde til å dekke hele flaten vil kontrollpunktenen kunne være slik:

float txpts[] =  {
	-1.0f, -1.0f,  0.0f, -1.0f,
	-1.0f, 0.0f,    0.0f, 0.0f
};
			

For å tegne ut bildet, trenger du å mappe det. Dette gjøres med denne kommandoen:

                                          a  b        c  d
gl.glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, txpts);
			

a, b, c og d er på samme måte her som når en mapper en bezierflate. For å tegne ut flaten med texturen på, kaller man på samme metode som for å tegne ut bare flaten.

gl.glMapGrid2f(20,0.0f,1.0f,20,0.0f, 1.0f);
gl.glEvalMesh2(GL_FILL, 0, 20, 0, 20);
			

En flate tilsvarende den som er beskrevet over med textur, kan for eksempel se slik ut:

texture1

Animasjon

Animasjon kan gjøres på mange måter. En ting som er nødvendig når det er snakk om bevegelse i javaprogrammer, er threading. Man oppretter threads for å kunne ha animasjon gående, samtidig som resten av programmet fortsatt er fullt brukbart. Måten som dette kan implementeres på er som følger:

  1. La Canvas klassen implementere runnable
  2. Opprett en ny Thread av Canvaset i den kjørbare klassen (Thread t = new Thread(canvas);)
  3. kall t.start()

Animasjon med openGL foregår som regel med en løkke av et slag, som forandrer koordinatene til et objekt. Et pseudokode-eksempel på dette kan være:

float distance = 0.0f;
...
public void display(){
	...
	gl.glTranslatef(0.0f, 0.0f, distance);
	tegnObject
	...
}

...
for(int i = 0; i < 100; i++){
	distance += 1.0f;
	repaint();
}
...
			

Matematikk

Det som er verdt å nevne om matematikk i denne modulen er teorien bak en sirkel. En sirkel kan beskrives slik:

y(t)=r·sin(2·pi·t)
x(t)=r·cos(2·pi·t)

			

Bildebok

[ Perm ] [ Sidene ] [ Åpning av perm ] [ Blaing ] [ Begrensninger/Utvidelser ]

Perm

Når det gjelder permen, så var det flere muligheter å vurdere før jeg fant ut at jeg ville ha permen stiv som tykke bøker. Jeg kunne velge å ha en ringperm, eller jeg kunne lage et blad, som ikke har stiv perm. Jeg har valgt å ha permen stiv, da dette ser penere ut. Valget med å ha stiv perm, gir meg litt flere utfordringer, enn jeg ville fått med å ha en ringperm, eller å ha boken som et hefte. Disse problemstillingene tar jeg opp når jeg forklarer hvordan boken blir åpnet.

Jeg har bygget opp permen helt og fullt av bezier-flater. For å få permen til å se tykk ut, og mest mulig lik en ekte bok, har jeg lagt alt dobbelt. Måten dette er gjort på i pseudo-kode er:

1. Push
2. tegn flate
3. flytt 0.5 ned
4. tegn flate
5. Pop
		

Som sagt, så er hele boken bygget opp av bezierflater. Toppen, og bunn av boken er bygget opp med disse kontrollpunktene:

float topPerm[] = {
	0.6f, -2.0f,0.5f,  4.0f,-2.0f,0.5f,
	0.6f, -1.0f,0.5f,  4.0f,-1.0f,0.5f,
	0.6f,  1.0f,0.5f,  4.0f, 1.0f,0.5f,
	0.6f,  2.0f,0.5f,  4.0f, 2.0f,0.5f,
};
			

Jeg tegner så toppen, og deretter bunnen. Jeg har en metode som tar for seg å tegne denne flaten to ganger med et mellomrom på 0.05f. Deretter "translater" jeg -0.5f på z-aksen og kaller på metoden som tegner flatene igjen. Dette vil se slik ut:
topBot1

I tillegg til disse flatene, må jeg tegne noe som binder disse sammen, slik at det ser ut som en perm, som er litt tykk. Dette gjøres med bezierflater også. Jeg definerer her tre flater, som skal binde de to sidene sammen. Disse er:

float topPermFrontSide[] = {
	0.6f, -2.0f, 0.5f,    4.0f, -2.0f, 0.5f,
	0.6f, -2.25f, 0.47f,  4.0f + 0.25f, -2.25f, 0.47f,
    0.6f, -2.0f, 0.45f,   4.0f, -2.0f, 0.45f
};

float topPermBackSide[] = {
	0.6f, 2.0f, 0.5f,    4.0f, 2.0f, 0.5f,
	0.6f, 2.25f, 0.47f,  4.0f + 0.25f, 2.25f, 0.47f,
	0.6f, 2.0f, 0.45f,   4.0f, 2.0f, 0.45f
};

float topOuter[] = {
	4.0f, -2.0f, 0.5f,
	4.0f, 0.0f, 0.5f,
	4.0f, 2.0f, 0.5f,

	4.25f, -2.25f, 0.47f,
	4.25f, 0.0f, 0.47f,
	4.25f, 2.25f, 0.47f,

	4.0f, -2.0f, 0.45f,
	4.0f, 0.0f, 0.45f,
	4.0f, 2.0f, 0.45f
};

			

Ved å tegne ut disse flatene, så vil topp og bunn på boken se slik ut:
Flatene som er heltrukket med farge er bindeleddene.
topBot2

For å få permen til å se mest mulig naturtro ut, valgte jeg å ta med den lille bøyen som er på bøker før man kommer til ryggen. Dette måtte jeg også lage dobbelt. Punktene er som følger:

float topCurl[] = {
	0.5f, -2.0f,0.5f,
	0.55f,-2.0f,0.45f,
	0.6f, -2.0f,0.5f,

	0.5f, -1.0f,0.5f,
	0.55f,-1.0f,0.45f,
	0.6f, -1.0f,0.5f,

	0.5f, 1.0f,0.5f,
	0.55f,1.0f,0.45f,
	0.6f, 1.0f,0.5f,

	0.5f, 2.0f,0.5f,
	0.55f,2.0f,0.45f,
	0.6f,2.0f,0.5f,
};

float botCurl[] = {
	0.5f, -2.0f,0.0f,
	0.55f,-2.0f,0.05f,
	0.6f, -2.0f,0.0f,

	0.5f, -1.0f,0.0f,
	0.55f,-1.0f,0.05f,
	0.6f, -1.0f,0.0f,

	0.5f, 1.0f,0.0f,
	0.55f,1.0f,0.05f,
	0.6f, 1.0f,0.0f,

	0.5f, 2.0f,0.0f,
	0.55f,2.0f,0.05f,
	0.6f,2.0f,0.0f,
};

float curlSide[] = {
	0.5f, -2.0f, 0.5f,
	0.5f, -2.25f, 0.47f,
	0.5f, -2.0f, 0.45f,

	0.55f, -2.0f, 0.45f,
	0.55f, -2.25f, 0.42f,
	0.55f, -2.0f, 0.40f,

	0.6f, -2.0f, 0.5f,
	0.6f, -2.25f, 0.47f,
	0.6f, -2.0f, 0.45f,
};


			

Disse punktene tegnet ut, utgjør bøyen som ser slik ut:
curl1

Til slutt tegnet jeg opp ryggen på boken. Denne består som resten av permen av to flater, som blir bundet sammen. Punktene er som følger:

float innerZFirst = 0.0f;
float innerZLast = 0.45f;
float innerXSec = 0.45f;
float innerXThird = 0.45f;


float backPerm[] = {
	0.5f, -2.0f,-0.05f,  0.4f,-2.0f,0.15f,
	0.4f, -2.0f,0.3f,  0.5f,-2.0f,0.5f,

	0.5f, -1.0f,-0.05f,  0.4f,-1.0f,0.15f,
	0.4f, -1.0f,0.3f,  0.5f,-1.0f,0.5f,

	0.5f, 1.0f,-0.05f,  0.4f,1.0f,0.15f,
	0.4f, 1.0f,0.3f,  0.5f,1.0f,0.5f,

	0.5f, 2.0f,-0.05f,  0.4f,2.0f,0.15f,
	0.4f,2.0f,0.3f,  0.5f,2.0f,0.5f,
};

float backPermInner[] = {
	0.5f, -2.0f,innerZFirst,  innerXSec,-2.0f,0.15f,
	innerXThird, -2.0f,0.3f,  0.5f,-2.0f,innerZLast,

	0.5f, -1.0f,innerZFirst,  innerXSec,-1.0f,0.15f,
	innerXThird, -1.0f,0.3f,  0.5f,-1.0f,innerZLast,

	0.5f, 1.0f,innerZFirst,  innerXSec,1.0f,0.15f,
	innerXThird, 1.0f,0.3f,  0.5f,1.0f,innerZLast,

	0.5f, 2.0f,innerZFirst,  innerXSec,2.0f,0.15f,
	innerXThird,2.0f,0.3f,  0.5f,2.0f,innerZLast,
};

			

Det som er verdt å nevne med denne delen, er at backPermInner, bruker noen variabler i arrayen. Hvorfor det er sånn, kommer jeg tilbake til i delen som forklarer hvordan åpningen av boken foregår.
Når ryggen på boken er tegnet ut, er permen fullstendig. Uten textur vil permen se slik ut, åpen og lukket:

permOpened permClosed

Sidene

Jeg har trikset litt for å lage sidene i boken. Her har jeg tre bezierflater, som forandres ettersom man blar i boken. Jeg vil først forklare hvordan disse sidene er bygget opp, deretter tar jeg for meg hvordan jeg har bygget opp innholdet til å se ut som om boken er full.

Den siden som vises når en åpner boken refereres til som aktiv. I tilleg har jeg to andre sider som er forrige side, og neste side. Disse er bygget opp på følgende måte:

float textPage[] = {
	txt1X, 2.0f, txt1Z, txt2X, 2.0f, txt2Z,
	  txt3X, 2.0f, txt3Z, txt4X, 2.0f, txt4Z,
	txt1X, 1.0f, txt1Z, txt2X, 1.0f, txt2Z,
	  txt3X, 1.0f, txt3Z, txt4X, 1.0f, txt4Z,
	txt1X,-1.0f, txt1Z, txt2X, -1.0f, txt2Z,
	  txt3X, -1.0f, txt3Z, txt4X, -1.0f, txt4Z,
	txt1X,-2.0f, txt1Z, txt2X, -2.0f, txt2Z,
	  txt3X, -2.0f, txt3Z, txt4X, -2.0f, txt4Z,
};

float prevPage[] = {
	prev1X, 2.0f, prev1Z, prev2X, 2.0f, prev2Z,
	  prev3X, 2.0f, prev3Z, prev4X, 2.0f, prev4Z,
	prev1X, 1.0f, prev1Z, prev2X, 1.0f, prev2Z,
	  prev3X, 1.0f, prev3Z, prev4X, 1.0f, prev4Z,
	prev1X,-1.0f, prev1Z, prev2X, -1.0f, prev2Z,
	  prev3X, -1.0f, prev3Z, prev4X, -1.0f, prev4Z,
	prev1X,-2.0f, prev1Z, prev2X, -2.0f, prev2Z,
	  prev3X, -2.0f, prev3Z, prev4X, -2.0f, prev4Z,
};

float nextPage[] = {
	next1X, 2.0f, next1Z, next2X, 2.0f, next2Z,
	  next3X, 2.0f, next3Z, next4X, 2.0f, next4Z,
	next1X, 1.0f, next1Z, next2X, 1.0f, next2Z,
	  next3X, 1.0f, next3Z, next4X, 1.0f, next4Z,
	next1X,-1.0f, next1Z, next2X, -1.0f, next2Z,
	  next3X, -1.0f, next3Z, next4X, -1.0f, next4Z,
	next1X,-2.0f, next1Z, next2X, -2.0f, next2Z,
	  next3X, -2.0f, next3Z, next4X, -2.0f, next4Z,
};

				

Disse tre sidene består bare av den ene flaten. Jeg har valgt å ikke lage dem doble, grunnet at en side i en bok er såpass tynn at det ikke er nødvendig. Variablene som er brukt i disse tre sidene, kommer jeg til å forklare nærmere under delen som omhandler blaing. Ved å tegne ut textPage med textur på, så vil denne se slik ut:
page1

For å få det til å se ut som om det er en bok full av sider har jeg bygget opp fem flater. Se illustrasjon:
allPages

Åpning av perm

Når permen skal åpnes dukker det opp en del problemstillinger. Hvor langt skal permen åpnes? Hvordan henger sidene fast? For å ta det første først. En har flere muligheter når det gjelder hvordan permen skal åpnes.

  1. Åpne den helt opp så permen ligger flat
  2. Åpne den delvis opp, så ryggen fortstatt står ca. 90 grader på bakpermen.

Alternativ 1

Når permen åpnes, må sidene henge fast i ryggen. Man må da lage en algoritme som gjør dette mest mulig naturlig. Man må forandre verdiene på sidene slik at de får den nødvendige bøyen, samtidig som permen må åpne seg.

Alternativ 2

Dette vil bli en litt mer avansert metode å åpne boken på. Selve åpningen vil gå greit, men det vil bli en ganske mye mer kompleks prosess når en blar sidene. Permen må da etterhvert som man blar pga. tyngden av arkene falle mer og mer ned mot bordet.

Mitt valg

Jeg har valgt alternativ 1 som en løsning i mitt prosjekt. Grunnen til dette, er at den er mindre kompleks, men ser allikevel naturlig ut.

Åpningen av permen foregår på en slik måte:

1. Så lenge i er mindre enn 90
   1.1 Roter rygg med i grader
   1.2 Roter topen av boken med i*2 grader
   1.3 Juster punktene i sidene
				

Tegningen av boken foregår slik:

1.  public void drawBook(){
2.     myColor.setLightBlueMaterial();
3.     gl.glPushMatrix();
4.        gl.glTranslatef(0.5f, -2.0f,-0.05f);
5.        gl.glRotatef(deg, 0.0f, -1.0f, 0.0f);
6.        gl.glTranslatef( -0.5f, 2.0f, 0.05f);
7.
8.        gl.glPushMatrix();
9.           gl.glTranslatef(0.5f, -2.0f,0.5f);
10.          gl.glRotatef(deg, 0.0f, -1.0f, 0.0f);
11.          gl.glTranslatef( -0.5f, 2.0f, -0.5f);
12.          drawTopOfBook(true);
13.          drawTopCurl();
14.          drawTopOuter();
15.       gl.glPopMatrix();
16.
17.       drawBack();
18.       drawBackCurl();
19.       drawLeftKant();
20.    gl.glPopMatrix();
21.
22.    gl.glPushMatrix();
23.       gl.glTranslatef(0.0f, 0.0f, -0.5f);
24.       drawTopOfBook(false);
25.       drawTopOuter();
26.    gl.glPopMatrix();
27.    drawBotCurl();
28.    drawKanter(true, true);
29. }
				

Variabelen "deg" som du finner på linje 5 og 10, blir i utgangspunktet satt til å være 0.0. Når boken åpnes går det en løkke fra 0 til 90, som plusser på deg med 1 for hver gang. Det vil til slutt resultere i at boken har blitt åpnet. I tillegg til dette må punktene til flatene som skal representere innholdet forandres. De forandres etter følgende linjer med kode:

xFUp=(float)(pagesRadUp*Math.cos((Math.PI/2)*(double)((i+90)/90)));
zFUp=(float)(pagesRadUp*Math.sin((Math.PI/2)*(double)((i+90)/90)))
     - 0.055f;

xFMid2=(float)(pagesRadMid2*Math.cos((Math.PI/2)*(double)((i+90)/90)));
zFMid2=(float)(pagesRadMid2*Math.sin((Math.PI/2)*(double)((i+90)/90)))
     - 0.055f;

xFMid1=(float)(pagesRadMid1*Math.cos((Math.PI/2)*(double)((i+90)/90)));
zFMid1=(float)(pagesRadMid1*Math.sin((Math.PI/2)*(double)((i+90)/90)))
     - 0.055f;

xFDown=(float)(pagesRadDown*Math.cos((Math.PI/2)*(double)((i+90)/90)));
zFDown=(float)(pagesRadDown*Math.sin((Math.PI/2)*(double)((i+90)/90)))
    - 0.055f;

myPage.setBotPages( (xFDown), (xFMid1), (xFMid2),
                    (xFUp), (zFDown + toAdd), (zFMid1 + toAdd),
                    (zFMid2 + toAdd), (zFUp + toAdd) );
				

pointsClosed
Som illustrasjonen over viser, så er det punktene FUp, FMid2, FMid1 og FDown som forandres etterhvert. Punktene som forandres følger en sirkel når de beveges. Dette kan sees slik:(tegningen er unøyaktig)
permRotering
Som vi ser ut i fra tegningen, så har de forskjellige sirklene en forskjellig radius. Dette kommer til uttrykk i koden som variablene pagesRadUp, pagesRadMid2, pagesRadMid1 og pagesRadDown.

pagesRadUp er radius til FUp,
pagesRadMid2 er radius til FMid2,
pagesRadMid1 er radius til FMid1 og
pagesRadDown er radius til FDown

Andre ting som er verdt å nevne i sammenheng med åpningen av boken er at når boken åpnes, blir første siden i boken gjort klar.

En snap-shot serie av åpningen av boken ser slik ut:
opening1

Blaing

Når deg gjelder blaingen er det også flere angrepsmetoder.

  1. Ta tak i nedre høyre hjørne og bla derfra
  2. Ta tak i øvre høyre hjørne og bla derfra
  3. Ta tak midt på siden og bla derfra
  4. Skyve siden fra midten og over.

Mitt valg

Jeg har valgt å bla etter fremgangsmåte 3. Grunnen til dette er at det vil være litt mer trivielt å få til med tanke på den tekniske biten. Et alternativ kunne vært å bruke fremgangsmåte nummer 4. Grunnen til at jeg ikke har valgt denne metoden, er at jeg synes det er mer naturlig å bla etter metode nummer 3.

Før jeg beskriver hvordan en side blas, er det nødvendig å illustrere hvordan siden er bygget opp.
blaing1
Som illustrasjonen viser, tar jeg hensyn til tre akser gjennom siden. Den aksen lengst til venstre, tar jeg ikke hensyn til, da denne ikke skal forandres. (Siden rives ikke løs fra boken). De tre aksene er outer, midOuter og midInner. For å få en nødvendig bøy/blafring i arket, kan ikke disse tre aksene forandre seg i samsvar med hverandre. Blaingen foregår på følgende måte:

1. evig løkke
   1.1 Hvis outer har krysset midInner:
      1.1.1 Hvis midInner er på plass:
         1.1.1.1 Stopp med å forandre midInner.
      1.1.2 Forandre midInner etter sirkelformel med høyeste hastighet

   1.2 Hvis outer har krysset midOuter:
      1.2.1 Hvis midOuter er på plass:
         1.2.1.1 Stopp med å forandre midOuter
      1.1.2 Forandre midOuter etter sirkelformel med høy hastighet

   1.5 Hvis outer er på plass:
      1.5.1 Slutt å bla og returner
   1.6 Forandre outer i etter sirkelformel med normal hastighet
				

Denne prosessen sørger for at outer er den første aksen som starter med å bevege seg, og den siste som "kommer i mål". midOuter er nummer to til å starte, og nummer to til å komme i mål. midInner er nummer 3 til å starte, og nummer 1 til å komme i mål.

Denne animasjonen følger linjen til en sirkel.
Aksene følger en radius som er tilsvarende så langt fra roteringspunktet som de ligger. Avstanden fra origo til roteringspunktet blir lagt til for å få riktig rotering.

For at boken skal virke naturlig er det ganske mange andre ting som må skje når en side blas. For å liste opp disse:

  • Minske tykkelsen på høyre side av boken
  • Øke tykkelsen på venstre side av boken
  • Tegne ut neste side, slik at den ligger klar når første side er bladd.
  • Tegne ut venstresides øverste side

Jeg har definert en viss tykkelse på hvert ark. Så minskingen og økningen blir påvirket av denne tykkelsen.

En serie snap-shots av blaingen ser slik ut:
blaing2

Begrensninger/Utvidelser

For å rekke å bli leveringsklar, har jeg tatt et par begrensninger til boken.

  1. Kan bare bla 6 sider
  2. Gjennomsiktige sider
  3. Lukke igjen boken
  4. Automatisk generering av innhold

1 - 6 siders blaing

Taktikken som er brukt for å løse bla-problemet, er rimelig lett å utvide til at man kan bla seg gjennom boken. Noe av grunnen til at jeg stopper her, er at tiden begynner å bli knapp. Har ikke flere sider å vise heller... Jeg ser det som viktigst å ha et produkt som er ferdig, i motsetning til å ha et halvferdig program, med en metode som ikke er skikkelig implementert. Dette er en utfordring som jeg gjerne vil løse når jeg får tid.

2 - Gjennomsiktige sider

Jeg har hatt et problem med å legge to teksturer på samme bezierflate. Dette problemet har jeg ikke fått løst, og jeg har valgt å ikke bruke samme teknikk på sidene som på permen. Å lage doble sider ville blitt veldig tungvint, og unødvendig. Det må finnes en løsning på problemet annet enn å lage doble sider.

3 - Lukke igjen boken

Dette er også en funksjon som jeg gjerne ville hatt med. Logikken for å lukke boken, blir mer eller mindre lik som for å åpne boken. For å en fullstendig bok, burde dette vært implementert

4 - Automatisk generering av innhold

En funksjon som kunne vært interessant å legge til var muligheten for å spesifisere størrelsen og innholdet på boken i runtime. F.eks gjennom at du har en katalog med bilder som du gjerne vil ha som innhold i boken.

Referanser
  1. Latest 'NEHE' NewsNEHE, NeonHelium ProductionsOpenGL-tutorials.nehe.gamedev.net/14-03-2009
  1. The OpenGL Programming Guide, 6 editionDave Schreiner, Mason Woo,Jackie Neider,Tom Davies2007Addison-Wesley Professional0321481003www.opengl.org/documentation/red_book/14-03-2010
  1. OpenGL, Architecture Review BoardControl of the development of OpenGLwww.opengl.org/about/arb/14-03-2009
  1. Computer Graphics Appletswww.cs.princeton.edu/~min/cs426/applets.html14-04-2010

Kildekode

BildeBokCanvas.java BildeBokFrame.java Perm.java
PagePainter.java TexturLaster.java FargeGen.java
AboutBox.java AboutCanvas.java CloseWindow.java
CloseWindowAndExit.java

Alle filene inklusive teksturer: alt.zip.

Dokumentasjon:Javadoc

Prosjektet skrevet om til JOGL , B. Stenseth mai 2010 (Netbeans prosjekt):
https://svn.hiof.no/svn/psource/JOGL/book

Vedlikehold
Skrevet av student Kenneth Stigen 2002
Kun redaksjonelle endringer og JOGL-versjon: B. Stenseth mai 2010
(Velkommen) Å tegne:>Bildebok (Tennis)