<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">

<html>
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org">

    <title>GLUT Programmeren: Windows Management</title>
  </head>

  <body>
    <h1>GLUT Programmeren: Windows Management</h1>

    <h4>ArticleCategory: [Choose a category for your article]</h4>
    Graphics 

    <h4>AuthorImage:[Here we need a little image from you]</h4>
    <img src="../../common/images/Miguel-S.jpg" alt=
    "[Miguel Sepulveda]" width="129" height="168"> 

    <h4>TranslationInfo:[Author and translation history]</h4>

    <p>original in en <a href=
    "mailto:Miguel.Sepulveda@disney.com">Miguel A Sepulveda</a></p>

    <p>en to nl <a href=
    "nospam:ghs(at)linuxfocus.org">Guus Snijders</a></p>

    <h4>AboutTheAuthor:[A small biography about the author]</h4>
    Afgestudeerd aan de Universiteit van Washington (VS) in 1993.
    Werkzaam in wetenschappelijk onderzoek in Spanje, Isra&euml;l,
    Japan en de VS. Ontdekte Linux voor het eerst rond kernel 0.98
    (Liefde op het eerste gezicht). Is nu hoofd-redacteur van het
    LinuxFocus magazine in zijn vrije tijd.

    <h4>Abstract:[Here you write a little summary]</h4>
    Dit artikel beschrijft het gebruik van de GLUT windows (vensters
    dus ;) management sub-API.

    <h4>ArticleIllustration:[This is the title picture for your
    article]</h4>
    <img src="../../common/images/transpix.gif" alt=
    "[Illustratie]" hspace="10" width="1" height="1"> 

    <h4>ArticleBody:[The article body]</h4>

    <h3><font color="#660033">Introductie</font></h3>

    <p>Dit artikel gaat verder met onze serie over GLUT, de GL
    Utility Toolkit van Mark Kilgard voor OpenGL applicaties.
    Zoals genoemd in ons vorige artikel (<a href=
    "../January1998/article16.html">Vensters en Animaties</a>),
    is GLUT een erg interessante en bruikbare toolkit voor iedere
    OpenGL ontwikkelaar omdat het je toestaat portable (overdraagbare)
    code te schrijven. GLUT schermt de ontwikkelaar af voor de 
    details van de onderligende windows manager en GUI interface.</p>

    <p>GLUT is verdeeld in een aantal subAPIs. In dit artikel zullen
    we de <i>Windows Management</i> subAPI. Zoals de naam al aangeeft,
    zorgt deze voor taken die gerelateerd zijn aan de vensters die
    worden gebruikt voor je OpenGL applicatie: cre&euml;ren, 
    vernietigen, minimaliseren van een venster; pushing, popping,
    verbergen, verplaatsen; en het instellen van titels, posities,
    enz... </p>
    <a name="section2"></a> 

    <h3><font color="#660033">Windows Management 
    Sub-Api</font></h3>

    <p>Hier is een volledige lijst van de functies die ondersteund
    worden door het windows management in GLUT (sinds versie 3.6):
    </p>

    <table border="0">
      <tr>
        <td><tt>int glutCreateWindow(char *name)</tt> </td>

	<td>Cre&euml;ert een nieuw top-level venster</td>
      </tr>

      <tr>
        <td><tt>int glutCreateSubWindow(int win,<br>
         &nbsp;&nbsp; int x, int y, int breedte, int hoogte)</tt>
        </td>

	<td>Cre&euml;ert een sub-venster</td>
      </tr>

      <tr>
        <td><tt>void glutSetWindow(int winId)</tt> </td>

	<td>Zet het venster met ID winID als huidig venster</td>
      </tr>

      <tr>
        <td><tt>int glutGetWindow(void)</tt> </td>

	<td>Vraag de identificatie op van het huidige venster</td>
      </tr>

      <tr>
        <td><tt>void glutDestroyWindow(int winId)</tt> </td>

	<td>Vernietigd het venster met het opgegeven winID</td>
      </tr>

      <tr>
        <td><tt>void glutPostRedisplay(void)</tt> </td>

	<td>Verteld de GLUT gebeurtenis processor dat het huidige
	venster opnieuw weergegeven dient te worden</td>
      </tr>

      <tr>
        <td><tt>void glutSwapBuffers(void)</tt> </td>

	<td>Wisselt (swap) de buffers voor het huidige venster
	om</td>
      </tr>

      <tr>
        <td><tt>void glutPositionWindow(int x, int y)</tt> </td>

	<td>Vraagt een verandering aan voor de positie van het
	venster</td>
      </tr>

      <tr>
        <td><tt>void glutReshapeWindow(int breedte, int hoogte)</tt>
        </td>

	<t>Vraagt een verandering aan in de afmetingen van het
	venster</td>
      </tr>

      <tr>
        <td><tt>void glutFullScreen()</tt> </td>

	<td>Vraagt om het huidige venster op volledig beeld
	    weer te geven</td>
      </tr>

      <tr>
        <td><tt>void glutPopWindow(void)<br>
         void glutPushWindow(void)</tt> </td>

	<td>Push of Pop het huidige venster relatief aan de anderen
	in de stack</td>
      </tr>

      <tr>
        <td><tt>void glutShowWindow(void)<br>
         void glutHideWindow(void)<br>
         void glutIconifyWindow(void)</tt> </td>

	<td>Geef weer, verberg of minimaliseer het huidige venster</td>
      </tr>

      <tr>
        <td><tt>void glutSetWindowTitle(char *name)<br>
         void glutSetIconTitle(char *name)</tt></td>

	<td>Geeft de titel balk voor venster of geminimaliseerde
	venster</td>
      </tr>
    </table>
    <a name="section3"></a> 

    <h3><font color="#660033">Sub-Windows gebruiken</font></h3>

    <p>Het gebruik van de meeste van de bovenstaande functies is
    erg simpel. Sommige zijn besproken in ons eerste artikel:
    <tt>glutPostRedisplay, glutCreateWindow, glutPositionWindow,
    glutSwapBuffers,..</tt>enz. Andere zijn, ondanks dat ze nieuw
    zijn, eenvoudig te begrijpen en de bovenstaande beschrijvingen
    vertellen ongeveer wat ze doen, zoals <tt>glutSetIconTitle, 
    glutFullScreen, ...</tt>enz. Het gebruik van sub-Windows is
    echter niet zo eenvoudig, zodat we besloten om je een simpel
    voorbeeld te geven en de details van de implementatie te 
    bespreken.</p>

    <p>Hier is de bron code voor een kleine OpenGL-GLUt demo (<a
    href="../../common/March1998/example1.c">example1.c</a>, <a
    href="../../common/March1998/Makefile">Makefile</a>). Het doel
    is om je te laten zien: (a) Hoe een subwindow te behandelen,
    (b) Hoe je je toetsenbord kan gebruiken voor interactie met je
    OpenGL applicatie, (c) Hoe tekst te renderen in een OpenGL
    venster.</p>
    <i>(Print alsjeblieft de bron code van uit, of zorg dat je hem
    bij de hand hebt terwijl we verder gaan met de bespreking.)</i>
    <br><br>

    <center>
      <a href="../../common/March1998/glut1.jpg"><img src=
      "../../common/March1998/glut2.jpg" border="1" width="305"
      height="313" alt="[Afbeelding van example1 tijdens uitvoering]"
      ></a><br>
    </center>

    <p>Laten we eerst eens kijken naar de main() functie. Deze start
    als iedere andere GLUT applicatie met initialisaties: de 
    opdrachtregel opties parsen, de weergave modus selecteren en 
    positie en afmetingen van het initi&euml;le venster zetten. Daar
    onze applicatie meer dan een venster gaat gebruiken, moeten we
    de integer window ID, geretourneerd door het 
    <tt>glutCreateWindow</tt> statement, oplsaan. De variabele
    <b>winIdMain</b> is een window handle. Dan is het tijd om de
    callback functies op te zetten voor de gebeurtenissen die we willen
    associ&euml;ren met het venster <b>winIdMain</b>; er worden 
    meerdere callback functies gedefinieerd en deze vervullen alle 
    een taak op het main window: een weergave functie
    (<tt>mainDisplay</tt>) die de scene tekent, een reshape (veranderen
    van de afmetingen) functie (<tt>mainReshape</tt>) welke 
    transformaties van het window frame afhandeld, keyboard om de 
    acties die via het toetsenbord worden getriggerd af te handelen
    en idle voor het beheren van de animatie als er geen andere
    gebeurtenissen wachten. (zie <a href=
    "../January1998/article16.html">Vensters en Animaties</a> voor
    een gedetailleerdere beschrijving van de rol van <b>idle</b>;
    </p>

    <p>Het eerste belangrijke ding om te weten, is dat in een GLUT
    applicatie er maar <em>een</em> idle callback functie kan zijn.
    De idle functie is globaal voor alle vensters in de applicatie.
    Let hier dus op bij het ontwerpen van <tt>idle()</tt> functies,
    deze moeten het verversen van alle vensters en subvensters in
    je applicatie voor hun rekening nemen.</p>

    <p>Vervolgens komt in de code het cre&euml;ren van een sub-window
    (<b>winIDSub</b>). Om een sub-venster te maken, moet je het ID
    van het bovenste (top level)  venster geven, in ons geval 
    <b>winIDMain</b>, de x en y co&ouml;rdinaten in pixels voor het
    sub-venster, relatief aan de interne co&ouml;rdinaten van 
    <b>winIDMain</b>, en de breedte en hoogte in pixels van het
    gevraagde sub-venster. Na het cre&euml;ren van het sub-venster
    retourneert GLUT een handle aan ons programma en zijn we klaar
    om de gewenste callback functies voor <b>winIDSub</b> op te zetten.
    In onze demo zetten we twee callback functies: een display
    (subDisplay) en een reshape (subReshape). </p>

    <p>Wanneer GLUT een subvenster opent, voorziet het deze van een
    volledige OpenGL context. Er treedt dan wel een beperking van 
    de performance op omdat de driver van de grafische kaart het
    geheugen gebied voor ieder venster in verschillende stappen moet
    verversen. Door de onafhankelijke OpenGL contexts heeft ieder
    venster bijvoorbeeld wel een eigen co&ouml;rdinaten systeem.
    In ../../common/March1998/example1.c worden de co&ouml;rdinaat
    systemen respectievelijk in <tt>mainDisplay()</tt> en 
    <tt>subDisplay()</tt> opgegeven. Bestudeer deze beide weergave
    functies, ze zijn vrij eenvoudig en als je ons january artikel
    over OpenGL hebt gevolgt 
    (<a href="../January1998/article17.html">"Eenvoudige Polygoon
    Rederinging"</a>), zul je geen problemen ondervinden bij het
    begrijpen ervan. </p>

    <p>De functie <tt>mainDisplay()</tt> tekent een driehoek met
    Rode, Groene en Blauwe vectoren. OpenGL interpoleert kleuren
    tussen de drie vectoren om de polygoon te vullen. Nog voor
    het renderen van de driehoek hebben we een <tt>glRotate</tt>
    statement toegevoegd die de driehoek rond zijn z-as roteerd
    (loodrecht op het venster), de rotatie hoek (<b>spin</b>)
    wordt langzaam verhoogd in <tt>idle()</tt> om de illusie van
    een draaiend figuur te cre&euml;ren.</p>

    <p>Wat betreft de weergave functie die is geassocieerd met
    <b>winIdSub</b>, deze is ook recht-toe-recht-aan. Eerst 
    schoont het de achtergrond op met een grijze kleur, dan tekent
    het een groene rand om het subvenster en rendert tenslotte wat
    tekst. Hoe de tekst rendering werkt onder GLUT, zullen we later
    bekijken. Voor het moment is het voldoende op te merken dat
    <tt>glRasterPos2f(x,y)</tt> de positie aangeeft waar getekend
    gaat worden, merk ook op dat de gebruikte x, y co&ouml;rdinaten
    relatief zijn aan het co&ouml;rdinaten systeem van het subvensters
    (gedefinieerd in <tt>subReshape()</tt>). </p>

    <p>Het subvenster doet dienst als tekst bord voor data die uit 
    de animatie komt. Het is een malle applicatie; we zouden gewoon
    het tekst bord op het hoofdvenster kunnen tekenen en zo het 
    zelfde resultaat (zelfs effici&euml;nter) bereiken. Onder
    bepaalde omstandigheden zijn er redenen om een subvenster voor
    de tekst uitvoer te gebruiken. Als bijvoorbeeld de animatie in
    3D is met lichten en omgevingseffecten, wil je waarschijnlijk
    niet dat je tekst wordt vervormd met irritante lichten, 
    perspectief effecten, schaduwen, mist, enz. Onder deze 
    omstandigheden is een subvenster handig, omdat deze volledig
    ge&iuml;soleerd is van de 3D animatie. </p>

    <p>Er is een cruciaal verschil tussen de reshape callback functie
    voor een bovenliggend venster en voor een subvenster. Als er een
    callback functie wordt geactiveerd, wordt alleen de reshape
    callback functie voor het bovenliggende venster gestart, in ons
    voorbeeld dus <tt>mainReshape()</tt>. We moeten de reshape 
    callback functie <tt>subReshape</tt> vanuit <tt>mainReshape</tt>
    aanroepen. Dit is duidelijk omdat de locatie en vorm van
    subvensters gebonden zijn aan de grootte en vorm van hun
    bovenliggende vensters. Als je dus nu de code leest, zie je dat
    we eerst de projectie matrix voor het bovenliggende venster 
    instellen en vervolgens overschakelen op het <b>winIDsub</b>
    subvenster en dan de reshape functie van dit subvenster aanroepen
    met de breedte en hoogte relatief aan <b>winIDMain</b>. </p>

    <p>Het was al eerder gemeld dat de <tt>idle()</tt> callback 
    functie alle bovenliggende en subvensters in de OpenGL applicatie
    moet updaten. In ons voorbeeld, update <tt>idle()</tt> eerst
    de status variabelen van de animatie (<b>time</b> en <b>spin</b>)
    en dan verzoekt het de herweergave van zowel de hoofd- als de
    subvensters. </p>
    <a name="section4"></a> 

    <h3><font color="#660033">Het toetsenbord</font></h3>

    <p>Ik heb twee actieve toetsen toegevoegd aan het programma. Door
    op de "i"-toets te drukken kun je het tekst bord in- en 
    uitschakelen en met de "q"-toets kun je de applicatie afsluiten.
    Probeer ze :) </p>

    <p>Iedere keer dat je een toets op je toetsenbord indrukt, 
    registreert GLUT's gebeurtenis-verwerkings driver een toetstenbord
    gebeurtenis. Deze gebeurtenissen (events) worden afgehandeld 
    door de callback functies voor het toetsenbord. In principe 
    heeft ieder venster zijn eigen callback functie. Als de muis zich
    op een locatie (x, y) binnen een bepaald venster (of subvenster) 
    is en er wordt een toetsenbord event gestart, zal de keyboard 
    callback functie voor dat venster worden aangeroepen. Deze
    callback functie neemt als argument de ASCII <i>unsigned char</i>
    die geassocieerd is met de toets en de x, y locatie van de cursor
    op dat moment. In ../../common/March1998/example2.c is er geen
    gebruik voor x, y, maar ik weet zeker dat je applicaties kunt
    bedenken waarin je je voordeel kunt doen met deze aardige feature.
    </p>

    <p>In onze demo heeft alleen het bovenste venster een keyboard
    callback. Als je de toetsen "i" of "q" indrukt terwijl de cursor
    zich in het subvenster bevindt, zul je merken dat er niets
    gebeurd. Standaard is het zo, dat als er een venster wordt 
    gecre&euml;erd en er geen keyboard callback functies worden
    geregistreerd, dat dan alle toetsaanslagen worden genegeerd.
    Houdt dit in de toekomst in gedachten als je meerdere vensters
    gebruikt en een actief toetsenbord wilt. </p>

    <p>Tenslotte nog de opmerking dat het generen van keyboard
    callbacks uitgeschakeld kan worden door NULL aan 
    <tt>glutKeyBoradFunc()</tt> mee te geven. </p>
    <a name="section5"></a> 

    <h3><font color="#660033">Tekst Renderen</font></h3>

    <p>Het renderen van tekst onder OpenGL en GLUT zuigt! Sorry dat
    ik dat zo zeg, maar het is waar. Het is me niet helemaal duidelijk
    waarom tekst-rendering is genegeerd in de OpenGL library. De oude
    GL library van SGI had een paar high-level functies voor het 
    renderen van tekst in graphische modus en er was een aanvullende
    hulp-library voor het veranderen van fonts. OpenGL biedt alleen
    erg primitieve richtlijnen voor het renderen van bitmaps, dat
    betekend dus dat je je eigen library van bitmaps moet aanleggen
    voor ieder karakter, rekening houdend met de resolutie, schalen
    van fonts... noem maar op!</p>

    <p>GLUT lost het dillemma van tekst gebruiken met OpenGL enigzins
    op. Het biedt <tt>glutBitmapCharacter</tt> die een enkel karakter
    op het scherm renderd op de locatie die wordt aangegeven door
    <tt>glRasterPos</tt>. Ik heb enkele functies toegevoegd,
    <tt>drawString()</tt> en <tt>drawStringBig()</tt> die je het leven
    iets eenvoudiger maken, wat betreft het renderen van karakter
    strings.</p>
    <a name="section6"></a> 

    <h3><font color="#660033">Conclusie</font></h3>

    <p>Dit sluit een erg simpele introductie van het gebruik van GLUT
    subvensters af. Op dit punt moet ik melden dat hoewel het geod
    is om ermee te experimenteren en testen op verschillende platformen,
    GLUT subvensters niet in alle omgevingen volledig functioneel zijn.
    Gebruikers met 3Dfx gebaseerde kaarten zullen merken dat subvensters
    nog niet werken door hardware beperkingen. Ook is gebleken dat het
    op sommige platformen subvensters een aanslag op de performance
    leveren. Op mijn Linux Alpha met een 2Mb Matrox Millenium maakt het
    gebruik van subvensters de applicatie ongeveer twee zo traag, 
    waarschijnlijk doordat de X server voor Alpha's nog steeds geen
    hardware acceleratie ondersteund. Aan de andere kant werkt dezelfde
    applicatie onder windows 95 met een 2Mb ATI RageII met SGI's OpenGL
    driver wonderwel. </p>

    <p>Daar de ontwikkelingen in Linux zo snel gaan, is het mogelijk
    dat in de nabije toekomst veel van deze performance problemen zijn
    opgelost en incompatibiliteiten zullen verdwijnen. Houdt voor het
    moment in gedachten dat ze bestaan en wees dus voorzichtig met het
    gebruik van meerdere vensters. </p>

    <p><i>Geavanceerdere gebruikers kunnen natuurlijk altijd een manier
    om de subvensters heen vinden door te spelen met de matrix stack
    maar omdat we die nog niet bestudeerd hebben, vergeef je me hopelijk
    dat ik die achterwege heb gelaten...  ;)</i>).</p>
    <hr size="2" noshade>
    <br>
     <b>Voor meer informatie</b>:<br>
     

    <ul>
      <li>Lees andere artikelen in deze serie: <a href=
      "../January1998/article16.html">"GLUT programmeren: Vensters
      en Animaties"</a>.</li>

      <li>Andere artikelen van dezelfde auteur: <a href=
      "article28.html">"OpenGL Programmeren: Meer over Lijnen"</a>
      .</li>
    </ul>
  </body>
</html>