Computer graphics/2014-2015/Laborator 2

From Wikiversity
Jump to navigation Jump to search

Linkuri Rapide: Prima Pagină; Laboratoare agenda, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, JOGL template.



Bazele JOGL[edit]

Ce este JOGL?[edit]

JOGL este o librărie (wrapper library) care permite folosirea OpenGL (binding) din limbajul Java folosind Java Native Interface (JNI) pentru call-urile a OpenGL C API.

Compararea OpenGL și JOGL[edit]

Nu există diferențe mari între OpenGL și JOGL cel puțin când vine vorba de sintaxă.


JOGL folosește limbajul Java pentru a efectua call-uri pentru OpenGL versiunea 4.5.

JOGL păstrează nomenclatura metodelor (funcțiilor) din API-ul principal OpenGL din limbajul C. Astfel dacă cineva știe să folosească API-ul din C un utilizator poate să înțeleagă și să scrie cod folosind JOGL. Orice tutorial pentru scene 2D sau 3D scris pentru OpenGL sunt reutilizabile în JOGL, deoarece logica programului este aceeași. Una din diferențele minore nu ține de JOGL ci de Java. Printre acestea enumerăm handling-ul ferestrelor, controlul mouse și tastatură, elemente de rețelistică și sunet. Cunoștințele dobândite în cadrul acestui laborator pot fi folosite în OpenGL iar cunoștințele OpenGL pot fi folosite în JOGL. Un mare plus în folosirea JOGL față de OpenGL este portabilitate codului. Nu este necesară rescrierea unei aplicații create pe sistemul de operare Windows pentru a rula pe Linux. Mai mult de atât, nu necesită un mediu special de dezvoltare.

JOGL nu folosește datatype-uri speciale.


Toate metodele JOGL sunt înfășurate (wrapped) într-o interfață numită GL (peste 1000 de metode). Acestă înfășurare este necesară deoarece în C o funcție poate fii apelată directi dar acest lucru nu este posibil în Java. O metodă trebuie să fie declarată în clasa curentă sau într-o superclasă. Prin înfășurare putem să instanțiem un object de tip GL și să apelăm metodele acesteia.

Link-uri Utile:

OpenGL ca și "state machine"[edit]

JOGL este un state machine. Astfel programatorul trebuie să știe în ce stare se află JOGL în orice moment dat. Aceste stări sunt importante pentru că:

  • unele operații sunt executabile în anumite stări
  • stările contin valori care controlează cum este randată (redată) o scenă (matrix transformations, light characteristics, material properties, polygon drawing characteristics, etc.)

Stările în JOGL sunt compuse din variabile bine definite. Toate variabilele au valori implicite astfel putem ignora variabilele care nu ne interesează și schimbăm doar cele care sunt relevante pentru o anumită scenă. Aceste variabile rămân la valorile date până nu sunt activate/deactivate în mod explicit prin apelarea; glEnable sau glDisable. Aceste variabile se pot interoga folosind glGet*v unde * poate avea valorile: Boolean, Integer, Float sau Double. De asemenea există functii specifice pentru anumite variabile de stare: glGetLight*(),glGetError(), sau glGetPolygonStipple(). Nu este recomandată folosirea acestora.

Salvarea și interogarea valorilor a variabilelor de stare se face prin funcțiile (metodele) glPushAttrib și glPopAttrib. Aceste funcții (metode) manipulează stiva de atribute care are o adâncime de 16 elemente. Folosire metodei glPopAttrib pe o stivă goală va rezulta într-o eroare. Același lucru este valabil și pentru aplicarea glPushAttrib pe o stivă plină.

Link-uri utile:

Nomenclatură[edit]

Nomenclatura JOGL o respectă pe cea din OpenGL.


Funcții[edit]

  • Fiecare funcție(metodă) începe cu gl
  • Restul cuvintelor sunt scrise folosind camel case convention
  • Unele funcții (metode) au un sufix -- ex: 3f -- care reprezintă numărul de argumente (3) și tipul (f) acesteia; (astfel este posibil să ave aceeași functie cu argumente diferite ; această caracteristică este contrară programării orientată Obiect (OOP) unde se folosește method overloading dar mentine sintaxa și logica OpenGL.

Tipurile posibile:

    • b -- byte -- 8 bit integer
    • s -- short -- 16 bit integer
    • i -- int -- 32 bit integer
    • f -- float -- 32 bit float
    • d -- double -- 64 bit float
    • ub, us, ui -- unsigned byte, short, int
  • Unele funcții (metode) au un v la sfârșit, acesta denotă faptul că funcția așteaptă un array de n valori.

Exemple de funcții (metode):

  • glBegin -- începutul unei primitive dată de o listă de noduri (vertices)
  • glEnd -- finalul primitivei
  • glVertex2i -- denotă coordonatele unui nod ca int (coordonata z este 0)
  • glVertex3f -- denotă coordonatele unui nod ca float
  • glColor3b -- denotă o culoare RGB cu valori între 0 și 255 bytes -- Atenție în Java byte este definit -128 până 127.
  • glColor4f -- denotă o culoare RGBA utilizând float de la 0.0 la 1.0 (A vine de la Alpha -- factor de transparență)
  • glColor4fv -- la fel cași cazul precedent doar că acceptă un singur argument -- float array

Constante[edit]

  • Fiecare constantă începe cu GL_
  • Cuvintele sunt scrise cu majuscule
  • Cuvintele sunt separate folosind underscore: _

Exemple de constante:

  • GL_COLOR_BUFFER_BIT
  • GL_LINES
  • GL_TEXTURE

Tipuri de Variabile[edit]

OpenGL are următoarele tipologii de variabile: GLbyte (signed char), GLshort (short), GLint and GLsizei (int și long), GLfloat și GLclampf (float), GLdouble și GLclampd (double), GLubyte și GLboolean (unsigned char), GLushort (unsigned short), GLuint și GLenum și GLbitfield (unsigned long). Acestea nu sunt prezente în JOGL din cauza limitărior limbajului Java. Astfel codul scris este mult mai portabil (cross platform)

Crearea primei șcene utilizănd JOGL și AWT[edit]

Următorii pași sunt obligatorii pentru a crea o aplicație JOGL minimală:


  • Instalarea librăriei JOGL
  • Crearea unei aplicații Java AWT
  • Inițializarea JOGL
  • Implementarea funcțiilor callback (methods)

Instalarea librăriei JOGL[edit]

Acesta implică:

  • Installarea -- sau verificarea -- runtime-ului OpenGL
  • Downloadarea distribuției JOGL (version 2.2.4) aceasta este o archivă 7z:
  • http://jogamp.org/deployment/webstart/
  • este recomandat să citiți fișierul Userguide.html aflat în arhivă
  • Dacă nu există creați folderul lib în proiectul vostru
  • Copiați toate fișierele în acest folder /lib
  • Adăugați jogl.all.jar și glugen-rt.jar CLASSPATH-ului proiectului -- acest pas depinde de IDE:
    • Pentru Eclipse expandați folderul lib și dați click-dreapta pe jogl.all.jar din meniul contextual alegeți opțiunea Add to build path
    • Dacă folosiți unelte în linie de comandă puteți include folderul lib' în variabila de mediu (environmental variable) CLASSPATH
  • Adăugarea folderului lib la variablia de mediu java.library.path în momentul rulării aplicației:
    • Din Eclipse selectați Run -> Open Run Dialog... -> Java Application -> New Configuration (sau numele dat configurației) -> Arguments tab -> adăugați linia -Djava.library.path=lib sau folderul unde se află dll-urile) în textbox-ul VM arguments
    • Dacă folosiți unelte în linie de comandă setați variabila de mediu LD_LIBRARY_PATH astfel încât să includă fodler-ul lib
  • Pentru informații mai detaliate consultați [1]

Următorul paragraf este preluat din fișierul Userguide.html găsit în arhiva librăriei (valabil pentru Windows):

The JOGL distribution for developers comes in the form of a zip archive which contains the Java classes to call OpenGL from Java, as well as the associated JNI native libraries. JOGL depends on some run-time support classes and native code provided by the GlueGen project; these classes and native code are also provided in the zip bundles.
If you are developing a new application which uses JOGL, download the zip archive for your platform (for example., jogl-[version]-windows-i586.zip) and unzip it. Modify your CLASSPATH environment variable to include the full paths to jogl.all.jar, nativewindow.all.jar, gluegen-rt.jar, and optionally newt.all.jar; for example, ".;C:\Some\Other\Package\foo.jar;C:\Users\myhome\jogl-[version]-windows-i586\lib\jogl.all.jar;C:\Users\myhome\jogl-[version]-windows-i586\lib\nativewindow.all.jar;C:\Users\myhome\jogl-[version]-windows-i586\lib\gluegen-rt.jar;C:\Users\myhome\jogl-[version]-windows-i586\lib\newt.all.jar". (If you did not previously set the CLASSPATH environment variable, you may want to make sure that ".", the current directory, is on your new CLASSPATH.) Modify your PATH environment variable (Windows), LD_LIBRARY_PATH environment variable (Solaris and Linux), or DYLD_LIBRARY_PATH environment variable (Mac OS X) to contain the full path to the "lib" directory; for example, on Windows, add "C:\Users\myhome\jogl-[version]-windows-i586\lib" to your PATH using the System control panel, Advanced tab, Environment Variables button. At this point your Java installation should be able to see the JOGL class files. Users of IDEs such as NetBeans and Eclipse should consult the IDE's documentation to see how to add jar files and native libraries to their current project.
Dropping the JOGL jar and native library into the extension directory of the JRE is strongly discouraged. Doing so can cause conflicts with third-party applications launched via Java Web Start, and causes confusion later when upgrading the distribution.

La următoarele linkuri găsiti alte instrucțiuni de instalare -- unele se referă la versiuni mai vechi JOGL:

Creare unei ferestre AWT[edit]

JOGL ne pune la dispoziție două clase pentru afișarea unei șcene:

  • GLCanvas -- componentă AWT
  • GLJpannel -- componentă Swing

Ambele clase implementează interfața GLAutoDrawable, astfel se pot folosii ambele variante; este recomandat să folosiți componente AWT -- GLCanvas -- de oare ce aceasta are o performanță mai bună. În cazul unor calculatoare mai vechi overheadul cauzat de Java + compnenta Swing poate duce la performanțe drastic reduse.

În cadrul Laboratoarelor vom folosi componenta AWT; dacă doriți puteți să o înlocuiți cu componentaa Swing.

Link-uri utile:

Pentru a crea o aplicatie AWT trebuie să creăm două clase:

  • MainFrame -- frame-ul (cadrul) aplicației
  • Test -- entry point-ul aplicației
MainFrame[edit]
[...]

public class MainFrame
		extends JFrame
{
	public MainFrame()
	{
		super("Java OpenGL");
		
		this.setLayout(new BorderLayout());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		this.setSize(800, 600);
		
		// This method will be explained later
		// this.initializeJogl();
		
		this.setVisible(true);
	}
}

Remarcați call-ul setVisible(true) după initializeJogl. Acesta este obligatoriu, dacă este omis starea internă a librariei este coruptă la runtime.

Test[edit]
public class Test
{
	public static void main(String[] arguments)
	{
		new MainFrame();
	}
}

Initializare JOGL[edit]

Odată ce avem fereastra AWT putem continua cu setările relevante pentru JOGL:

  • Crearea unui profil nou GL
  • Setarea unor parametrii JOGL -- denumite capacităti în OpenGL/JOGL
  • Crearea obiectului GLCanvas și adăugarea acestuia la fereastră
  • ÎnregistrareaGLEventListener


Astfel avem metoda initializJogl care are ca și scop:

  • Obținerea unui nou GLProfile
  • Setarea diferitelor variabile -- folosind instanța GLCapabilities. Aici putem modifica:
    • Hardware acceleration: on / off
    • Double buffering: on / off
    • Rendering mode/Modul de Randare
    • Randarea unui singur canal de culori
    • etc.
  • Crearea unei instanțe GLCanvas care va fi folosită pentru randare
  • Adăugarea instanței GLCanvas în mijlocul frame-ului
  • Înregistrarea GLEventListener la noul canvas: în cazul nostru clasa MainFrame implementează interfață GLEventListener
[...]

public class MainFrame
		extends JFrame
		implements GLEventListener
{
	
	[...]
	
	private void initializeJogl()
	{
		// Obtaining a reference to the default GL profile
		GLProfile glProfile = GLProfile.getDefault();
		// Creating an object to manipulate OpenGL parameters.
		GLCapabilities capabilities = new GLCapabilities(glProfile);
		
		// Setting some OpenGL parameters.
		capabilities.setHardwareAccelerated(true);
		capabilities.setDoubleBuffered(true);
		
		// Creating an OpenGL display widget -- canvas.
		this.canvas = new GLCanvas();
		
		// Adding the canvas in the center of the frame.
		this.getContentPane().add(this.canvas);
		
		// Adding an OpenGL event listener to the canvas.
		this.canvas.addGLEventListener(this);
	}
	
	[...]
	
	private GLCanvas canvas;
}

Link-uri Utile:

Funcții callback (metode)[edit]

JOGL folosește funcții (metode) callback pentru operațiuni asupra ferestrei de randare(window resizing, rendering, inițializarea scenei, etc) Există 4 funcții (metode) callback în JOGL:

  • init -- chemat la inițializare (canvas)
  • reshape -- chemat când fereastra (canvas) este redimensionată sau mutată
  • displayChanged -- chemat când modul de randare este schimbat
  • display -- chemat când scena trebuie descrisă


[...]

public class MainFrame
		extends Frame
		implements GLEventListener
{
	[...]
	
	public void init(GLAutoDrawable canvas)
	{
		return;
	}
	
	public void display(GLAutoDrawable canvas)
	{
		return;
	}
	
	public void reshape(GLAutoDrawable canvas, int left, int top, int width, int height)
	{
		return;
	}
	
	public void displayChanged(GLAutoDrawable canvas, boolean modeChanged, boolean deviceChanged)
	{
		return;
	}
	
	[...]
}

Link-uri utile:

Desenarea[edit]

Probabil cea mai importantă componentă JOGL. Pentru a desena avem nevoie de implementarea metodelor display, init și reshape definite în interfața GLEventListener.

Această metoda este chemată de fiecare dată JOGL redesenează scena/imaginea. De asemenea ne dă o referință către GLAutoDrawable care este instanța canvas unde a fost înregistrat listener-ul din metoda initializeJogl.


[...]

public class MainFrame
		extends Frame
		implements GLEventListener
{
	[...]
	
	public void display(GLAutoDrawable canvas)
	{
		// Retrieve a reference to a GL object. We need it because it contains all the useful OGL methods.
		GL2 gl = canvas.getGL().getGL2();
		
		// Each time the scene is redrawn we clear the color buffers which is perceived by the user as clearing the scene.
		// Clear the color buffer
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		
		[...]
		
		// Forcing the scene to be rendered.
		gl.glFlush();
		
	}
	
	[...]
}

Metoda init va fi detaliată în secțiunea depre tipurile de proiecție. Dar merită să menționăm anumite aspecte ce sunt initializate în această metodă:

  • View-ul
  • Culoarea de fundal
  • Sursele de lumină
  • etc.

Metoda reshape va fii detaliată în aceeași secțiune. Scopul acesteia este ca scena randată să iși păstreze proporțiile când fereastra este manipulată (micșorată, mărită).

Animația[edit]

Metoda display este invocată când o scenă trebuie redesenată; dar dacă dorim să creăm o animație această metodă trebuie chemată de câteva ori pe secundă (cu cât este mai mare frecvență cu atât este animația mai realistă). Butem realiza acest lucru prin crearea unui fir de execuție special care forțează rerandarea imaginii dar o altă soluție -- și cea recomandată -- este de a folosi clasa Animator (care folosește un fir de executie special).

Pentru acesta trebuie să creăm un membru al clase Animator și să includem acest membru în funcția (metoda) initializeJogl:

  • Creara instanței
  • Adâugarea animatorului în canvas (suprafața de randare)
  • Pornirea animatorului
	private void initializeJogl()
	{
		[...]
		
		this.animator = new Animator();
		
		this.animator.add(this.canvas);
		
		this.animator.start();
	}

Link-uri Utile:

Șablon pentru aplicații JOGL[edit]

Puteți găsii șablonul pentru aplicații JOGL la link-ul: Grafica -- 2014-2015 -- info.uvt.ro/JOGL-Template.

Bazele graficii 2D (Partea 1)[edit]

Sistemul de Coordonate (JOGL vs. AWT)[edit]

În forma cea mai simplă sistemul de coordonate folosite este cel Cartezian cu cele 3 axe (X, Y, Z). În realitate OpenGL are o a patra coordonate care funcționează ca și factor de scalare -- homogeneous coordinates.

Este important să ținem minte că punctul de start este situat în partea din stânga jos a suprafeței de randat (de acum încolo va fi numită canvas). Pentru AWT și Swing punctul de start este partea din stânga sus fiind astfel inversa situației din OpenGL.

Link-uri Utile:

Proiecții (ortogonal, perspectiva), Viewport and View Volume[edit]

Proiecții[edit]

JOGL ne oferă două tipuri de proiecții:

  • Perspectiva -- definită de un centru de proiecție și un plan de proiecție unde obiectele sunt proiectate (în engleză projection center și projection plane )
    • În JOGL acesta se poate obține folosind următoarele funcții (metode):
      • glFrustum(left, right, bottom, top, near, far) -- din instanțele GL
      • gluPerspective(fovy, aspect, near, far) -- din instanțele GLU
    • Este perfect pentru scene 3D
  • Ortogonal -- un tip de proiecție definită pintr-o direcție și un plan al proiecției. Acest tip de proiecție poate fii văzut ca o proiecție în prespectivă unde centru proiecției este la infinit.
    • În JOGL acest tipde proiecție se obtine prin functia (metoda) glOrtho(left, right, bottom, top, near, far)
    • Good for 2D scenes

Viewport și View volume[edit]

Viewport este o zonă dreptunghiulară -- în cadrul ferestrei JOGL -- unde se randează scenele/imaginile. Este măsurată în pixeli, și este poziționată față de colțul din stânga sus a componentei.

În mod implicit viewport-ul este setat să acopere toată suprafața componentei (canvas). Astfel dacă fereastra este redimensionată și viewport trebuie redimensionat -- folosind funcția (metoda) glViewport.

Când redăm o scenă trebuie să definim și viewing volume -- un paralelipiped dreptunghic (proiecție ortogonala) sau o piramidă trunchiată (perspectivă) -- care va fi afișată în viewport. Oricare obiect care nu se află în cadrul acestui volum nu este afișat (clipped). Fiecare parte a acestui volum este numit un clip plane.

Putem să definim și alte limite în cadrul acestor volume folosind funcția (metoda) glClipPlane(int plane, double[] equation). Parametrul equation se referă la coeficienții care corespund limitei (clip plane).

Aceste limite adiționale se pot activa și dezactiva folosind gl.glEnable(GL.GL_CLIP_PLANE1) și gl.glDisable(GL.GL_CLIP_PLANE1).


[...]

public class MainFrame
		extends JFrame
		implements GLEventListener
{
	double equation[] = { 1f, 1f, 1f, 1f};

	[...]
	
	public void init(GLAutoDrawable canvas)
	{
		// Obtain the GL instance associated with the canvas.
		GL2 gl = canvas.getGL().getGL2();
		
		[...]

		// Enable additional Clip plane.
		gl.glEnable( GL2.GL_CLIP_PLANE1 );

		// Set clip plane to be defined by the 	equation arguments
		gl.glClipPlane( GL2.GL_CLIP_PLANE1 , equation, 0 );
		
		[...]
	}
}

În general raportul de aspect (aspect ration) a viewport și view volume este același. În caz contrar imaginea/scena va apare distorsionată.

JOGL folosește matrici pentru a administra view:

  • projection view -- matricea este folosită pentru a definii viewing volume-ul, folosind funcția (metoda) glMatrixMode(GLMatrixFunc.GL_PROJECTION).
  • model view -- matricea care este folosită pentru transformări geometrice a obiectelor (translation, rotation, scaling, etc.) căt și orientarea viewport-ului. Pentru aceasta se folosește funcția (metoda) glMatrixMode(GLMatrixFunc.GL_MODELVIEW)

Aceste matrici sunt modificate de fiecare dată o scenă este modificată, ea se poate reseta aplicând matricea identitate (unitate) matricii curente. Pentru acesta se folosește funcția (metoda) glLoadIdentity().

Cum se folosesc în JOGL?[edit]

Matricea de proiecție (projection matrix) este folosită în cadrul funcției (metodei) reshape și inițializată în init. Acest lucru este posibil de oare ce evenimentele de modificare a dimensiunii se rezolvă în funcția reshape. La fiecare eveniment de redimensionare trebuiesc modificate proiecțiile și aspec ratio.

După ce modificăm matricea de proiecție trebuie să schimbăm (switch) pe modul modelview.

Următorul fragment de cod exemplifică acest lucru:

[...]

public class MainFrame
		extends JFrame
		implements GLEventListener
{
	[...]
	
	public void init(GLAutoDrawable canvas)
	{
		// Obtain the GL instance associated with the canvas.
		GL2 gl = canvas.getGL().getGL2();
		
		// Set the clear color -- the color which will be used to reset the color buffer.
		gl.glClearColor(0, 0, 0, 0);
		
		// Select the Projection matrix.
		gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
		
		// Clear the projection matrix and set it to be the identity matrix.
		gl.glLoadIdentity();
		
		// Set the projection to be orthographic.
		// It could have been as well chosen to be perspective.
		// Select the view volume to be x in the range of 0 to 1, y from 0 to 1 and z from -1 to 1. 
		gl.glOrtho(0, 1, 0, 1, -1, 1);
	}
	
	[...]
	
	public void reshape(GLAutoDrawable canvas, int left, int top, int width, int height)
	{
		GL2 gl = canvas.getGL().getGL2();
		
		// Select the viewport -- the display area -- to be the entire widget.
		gl.glViewport(0, 0, width, height);
		
		// Determine the width to height ratio of the widget.
		double ratio = (double) width / (double) height;
		
		// Select the Projection matrix.
		gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
		
		gl.glLoadIdentity();
		
		// Select the view volume to be x in the range of 0 to 1, y from 0 to 1 and z from -1 to 1.
		// We are careful to keep the aspect ratio and enlarging the width or the height.
		if (ratio < 1)
			gl.glOrtho(0, 1, 0, 1 / ratio, -1, 1);
		else
			gl.glOrtho(0, 1 * ratio, 0, 1, -1, 1);

		// Return to the Modelview matrix.
		gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
	}
	
	[...]
}

Link-uri Utile:

Spațiul de Coordonate[edit]

JOGL folosește mai multe spații de coordonate (coordinate spaces) pentru a transforma coordonatele date de utilizator la cele folosite pentru a afișa scena:

  • Object Coordinates -- coordonatele carteziene definite folosind funcția (metoda) glVertex*
  • Eye Coordinates -- este obtinută de ModelView matrix care contine transformările ale modelului cât și a vizualizării astfel poate plasa punctul de privire orientat pe axa negativă Z.
  • Clip Coordinates - sunt ibținute din Projection Matrix după transformarea Eye Coordinates. Coordonatele sunt are valorile de la -W la W pe toate cele 3 axe, obiectele înafară acestor coordonate nu se afișează
  • Normalized Device Coordinates -- situate între -1 și 1 si sunt obținute după transformarea Clip Coordinates cu ajutor 'Perspective division
  • Window Coordinates -- scalarea și translatarea coordonatele Normalized Device Coordinates față de viewport. Acestă operațiune ne dă coordonatle finale utilizate pentru a reda o șcenă. Această operație este realizată cu ajutorul funcțiilor (metodelor) glViewport și glDepthRange.

Astfel workflow-ul normal pentru transformarea coordonatelor este: Object CoordinatesEye CoordinatesClip CoordinatesNormalized Device CoordinatesWindow Coordinates.

Un sistem special de coordonate este reprezentat de World Coordinates care este rezultatul transformărilor Object Coordinates folosind rotations, translations și scalings stocate în ModelView matrix. Practic World Coordinates este diferit pentru fiecare aplicatie. Este creată după rotirea, scalarea și translatarea Object Coordinates în zona de afișare a applicației.

În secțiunile anterioare am discutate despre proiecții ortostatice. Acestea sunt create folosind funcțiile (metodele) callback init și reshape:

	[...]
	
	gl.glOrtho(0, 1, 0, 1, -1, 1);

	[...]

Acum vrem să setăm ca o unitate de măsură din proiecție să fie reprezentață de un pixel. Pentru aceasta trebuie să modificăm funcția (metoda) glOrtho:

	[...]
	
	gl.glOrtho(0, windowWidth, 0, windowHeight, -1, 1);

	[...]

Acesta ne dă un viewport având ca dimensiune toată suprafața ferestre de randare (canvas) JOGL. Este important de menționat faptul că viewport-ului poate fi de orice dimensiune. Dacă definim view colum-ul ca fiind gl.glOrtho(0, 1, 0, 1, -1, 1) observăm că nodul definit de glVertex2f(2.0f, 2.0f) nu va fi afișat. Dacă folosim gl.glOrtho(0, 800, 0, 600, -1, 1); același nod va apare în partea din stânga jos a ferestrei.

JOGL nu are o unitate standard de măsură pentru plasarea obiectelor. Astfel putem folosii orice unitate potrivită pentru o aplicație. De exemplu o unitate astronomică pentru a crea un simulator spațial sau nanometrii pentru a crea un simulator de structuri atomice.

Important: Când definim plaja de valori pentru Z de la -1 la 1 trebuie să folosim funcția (metoda) glVertex2*. În cazul glVertex3* a treia coordonată trebuie să fie 0.

Link-uri Utile:

Vertices vs. Points vs. Pixels[edit]

  • Vertices sau noduri sunt cele mai simple primitive folosite în JOGL
  • Nodurile pot fii văzute ca puncte reprezentate ca și vectori definiți cu ajutorul float
  • Un nod (sau vertex) NU este un pixel
  • Un nod este declarat folosind funcția (metoda) glVertex*

Nodurile se pot grupa astfel încât să formeze forme geometrice precum linii, triunghiuri, poligoane, etc.

Nodurile grupate astfel trebuie să fie în cadrul unui bloc glBegin și glEnd : To group together vertices one must bound them inside a glBegin and glEnd block:

public class MainFrame
{
	[...]

	public void display(GLAutoDrawable canvas) {
		GL2 gl = canvas.getGL().getGL2();

		[...]
		
		gl.glBegin(GL2.SHAPE_TYPE);
			[...]
		gl.glEnd();
		
		[...]
	}

	[...]
}

Liste de puncte (points, lines, line strip, line loop)[edit]

Nodurile pot fi interpretate de către JOGL în felul următor:

  • points -- specificat de GL.GL_POINTS și le consideră un set de puncte
  • lines -- specificat de GL.GL_LINES punctele sunt considerate ca și segmente de drepte
  • line strip -- specificat de GL.GL_LINE_STRIP consideră punctele ca o serie de drepte interconectate
  • line loop -- specificat de GL.GL_LINE_LOOP la fel ca și cazul precedent dar adaugă o dreaptă între prima și ultima dreaptă
public class MainFrame
{
	[...]

	public void display(GLAutoDrawable canvas) {
		GL2 gl = canvas.getGL().getGL2();

		[...]

		gl.glBegin(GL2.GL_LINES);
			gl.glVertex2f(0.2f, 0.2f);
			gl.glVertex2f(0.4f, 0.2f);
			gl.glVertex2f(0.2f, 0.4f);
			gl.glVertex2f(0.4f, 0.4f);
		gl.glEnd();

		[...]
	}

	[...]
}

Link-uri Utile:

Schimbarea proprietăților pentru puncte (dimensiune, grosime)[edit]

Punctele și liniile au proprietătile:

  • dimensiune (puncte) -- modificat utilizând funcția (metoda) glPointSize:
public class MainFrame
{
	[...]

	public void display(GLAutoDrawable canvas) {
		GL2 gl = canvas.getGL().getGL2();

		[...]

		// Set the size of the point
		gl.glPointSize(0.5f);

		gl.glBegin(GL2.GL_POINTS);
			gl.glVertex2f(0.2f, 0.2f);
			gl.glVertex2f(0.4f, 0.2f);
			gl.glVertex2f(0.2f, 0.4f);
			gl.glVertex2f(0.4f, 0.4f);
		gl.glEnd();

		[...]
	}

	[...]
}
  • lățime (linii) -- modificat folosind funcția (metoda) glLineWidth:
public class MainFrame
{
	[...]

	public void display(GLAutoDrawable canvas) {
		GL2 gl = canvas.getGL().getGL2();

		[...]

		// Set the width of the lines
		gl.glLineWidth(0.5f);

		gl.glBegin(GL2.GL_LINES);
			gl.glVertex2f(0.2f, 0.2f);
			gl.glVertex2f(0.4f, 0.2f);
			gl.glVertex2f(0.2f, 0.4f);
			gl.glVertex2f(0.4f, 0.4f);
		gl.glEnd();

		[...]
	}

	[...]
}
  • stipple (lininii) -- modificat folosind funcția (metoda) glLineStipple:
public class MainFrame
{
	[...]

	public void display(GLAutoDrawable canvas) {
		GL2 gl = canvas.getGL().getGL2();

		[...]

		gl.glLineStipple(1, 0x3F07);
		gl.glEnable(GL2.GL_LINE_STIPPLE);

		gl.glBegin(GL2.GL_LINES);
			gl.glVertex2f(0.2f, 0.2f);
			gl.glVertex2f(0.4f, 0.2f);
			gl.glVertex2f(0.2f, 0.4f);
			gl.glVertex2f(0.4f, 0.4f);
		gl.glEnd();

		gl.glDisable(GL2.GL_LINE_STIPPLE);

		[...]
	}

	[...]
}

Culori[edit]

JOGL -- ca și majoritatea produselor software -- folosește culori RGB definite pe 24 de biti, în unele situații RGBA.

De fiecare dată o șcenă este (re)desenată acesta este acoperită cu o culoare definită prin funcția (metoda) glClearColor -- culoarea implicită este culoarea neagra definită RGB = (0,0,0). Acest lucru implică manipularea color buffer -ului (acesta contine culorile pixelilor a ferestrei curente). Acest buffer va fi detaliat în laboratoarele următoare.

Fiecare obiect este desenată cu o altă culoare defeinită folosind functia (metoda) glColor*.

public class MainFrame
{
	[...]

	public void display(GLAutoDrawable canvas) {
		GL2 gl = canvas.getGL().getGL2();

		// Each time the scene is redrawn we clear the color buffers which is perceived by the user as clearing the scene.

		// Set the color buffer to be filled with the color black when cleared.
		// It can be defined in the init function (method) also.
		gl.glClearColor(0.0f, 0.0f, 0.0f);

		// Clear the color buffer.
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);

		[...]

		gl.glBegin(GL2.GL_POINTS);
			// Set the vertex color to Red.
			gl.glColor3f(1.0f, 0.0f, 0.0f);
			gl.glVertex2f(0.2f, 0.2f);
			// Set the vertex color to Green.
			gl.glColor3f(0.0f, 1.0f, 0.0f);
			gl.glVertex2f(0.4f, 0.2f);
			// Set the vertex color to Blue.
			gl.glColor3f(0.0f, 0.0f, 1.0f);
			gl.glVertex2f(0.2f, 0.4f);
			// Set the vertex color to White.
			gl.glColor3f(1.0f, 1.0f, 1.0f);
			gl.glVertex2f(0.4f, 0.4f);
		gl.glEnd();

		[...]
	}

	[...]
}

Link-uri Utile:

API[edit]

References[edit]

Exerciții[edit]

  • Creați o aplicatie minimală JOGL folosind Eclipse care instanțiază o simplă fereastră de randare.
  • Desenați câte un pătrat folosind GL_LINES, GL_LINE_STRIP and GL_LINE_LOOP. Fiecare nod (vertex) să aibă o culoare diferită
  • Desenați un cerc folosind GL_LINE_LOOP
  • Desenați o casă utilizând GL_LINES. Adăugați mai multe culori. Opțional adăugați un soare care se mișcă de la dreapta la stânga.
  • Opțional -- Desenați fractalul de la site-ul acesta. Puteți vedea și alți fractali la această pagină.
    • Metoda de desenare trebuie să fie recursivă!