2D/3D Graphics Java and OpenGL context Android

Introduction:

Android est un système d'exploitation open source utilisant le noyau Linux, pour smartphones, tablettes tactiles, PDA et terminaux mobiles conçu par Android, une startup rachetée par Google, et annoncé officiellement le 5 novembre 2007. D'autres types d'appareils possédant ce système d'exploitation existent, par exemple des téléviseurs, des radio-réveils ou des autoradios et même des voitures.[1]

Le système d'exploitation Android possède  plusieurs fonctionnalistes comme stockage, connectivité, navigateur, support Java, média, multitâche, Multi-touch, 2D graphique (avec l'orientation du matériel, mise à l'échelle, conversion de format de pixels) et d'accélération graphique 3D, etc... Ce plate-forme est adaptable au VGA, 2D bibliothèque graphique, 3D bibliothèque graphique basé sur les spécifications OpenGL 2.0 ES et toutes les traditionnelles Smartphones layouts.[2]

Android prend en charge les graphismes hauts performances 2D et 3D avec l'Open Graphics Library (OpenGL), en particulier, l'API OpenGL ES. OpenGL est une API multi-plateforme graphique qui spécifie une interface logicielle standard pour le matériel de traitement graphique 3D. OpenGL ES est une saveur de la spécification OpenGL destiné pour les systèmes embarqués. Les OpenGL ES 1.0 et 1.1 des spécifications API ont été pris en charge depuis Android 1.0. À commencer par Android 2.2 (niveau API 8), le cadre prend en charge l'API OpenGL ES 2.0 des spécifications.[3]

OpenGL

OpenGL (Open Graphics Library) est une spécification qui définit une API multiplate-forme pour la conception d'applications générant des images 3D et 2D. L'interface regroupe environ 250 fonctions différentes qui peuvent être utilisées pour afficher des scènes tridimensionnelles complexes à partir de simples primitives géométriques. OpenGL est la plus largement adoptée API graphique 2D et 3D dans le secteur. La dernière version d’OpenGL est 4.3 qui a apporté beaucoup d’amélioration sur le performance de GPU, augmentation de la mémoire de sécurité, la capacité de faire un debug, une extension multi-application qui garantit qu'une application qui provoque une réinitialisation GPU n'affectera pas les autres applications en cours d'exécution, etc.[4]

OpenGL ES

Plusieurs versions de la spécification OpenGL ES existent maintenant. OpenGL ES 1.0 est dressé contre l'OpenGL 1.3, OpenGL ES 1.1 est défini par rapport à la spécification OpenGL 1.5 et OpenGL ES 2.0 est définie par rapport à la spécification OpenGL 2.0. Cela signifie que, par exemple, une application écrite pour OpenGL ES 1.0 devrait être facilement portable vers l'ordinateur de bureau OpenGL 1.3, comme OpenGL ES est une version allégée de l'API, l'inverse peut ou peut ne pas être vrai, en fonction de la caractéristiques particulières utilisées.[5]

2D using Java openGL:

Le graphique 2D est la production assistée par ordinateur d'images numériques, la plupart par de ces modèles sont par exemple les modèles géométriques du texte et des images numériques. Ils sont principalement utilisés dans les applications qui ont été développées à l'origine lors de l'impression traditionnelle et les technologies de dessin, comme la typographie, la cartographie, le dessin technique, la publicité, etc.[6]

OpenGL a été conçu avant tout comme une bibliothèque graphique 3D, mais il peut être utilisé encore pour le dessin 2D                                 

La mise en place d'une projection en 2D peut être faite par une matrice en 2D.[7]

Par exemple:

          

     const XSize = 640, YSize = 480;

        glMatrixMode (GL_PROJECTION);

        glLoadIdentity ();

        glOrtho (0, XSize, YSize, 0, 0, 1);

        glMatrixMode (GL_MODELVIEW)

;[7]

Ceci met en place la fenêtre OpenGL afin que (0,0) correspond au coin supérieur gauche, et (640,480) correspondant au coin en bas à droite. Si l'écran n'est pas de 640*480 alors openGL va étirer l'image pour l'adapter à la taille nécessaire.

D'une autre part, il n'y a pas de profondeur graphique (qui est utilisé pour déterminer quels objets sont en face ou derrière l'autre dans l'espace 3D, basé sur leur coordonnées Z pixel) pour cela il faut désactiver le tampon de profondeur.[7]

           

   glDisable(GL_DEPTH_TEST)

Les principes de dessin en 2D:

D’abord il faut effacer l’écran par

          

    glClear(GL_COLOR_BUFFER_BIT)

Ensuite il faut tirer les primitives graphiques (GL_QUADS, GL_TRIANGLES, GL_LINES etc.), à la norme glBegin () .. glEnd ().C’est possible d’utiliser toutes les transformations standards OpenGL comme (glTranslate, glScale, glRotate etc.)

Quand la rendre de la scène est fini,  l'affichage se fait avec

         

  SwapBuffers ()

Pour dessiner un point il faut

         

      glBegin(GL_POINTS)

        glVertex2f(x1, y1)

        glEnd()

Pour dessiner une ligne

           

glBegin(GL_LINES)

        glVertex2f(x1, y1): glVertex2f(x2, y2)

        glEnd()

Pour dessiner un carré ou un rectangle

Rempli:

           

glBegin(GL_QUADS)

        glVertex2f(x1, y1): glVertex2f(x2, y1): glVertex2f(x2, y2): glVertex2f(x1, y2)

        glEnd()

Vide:[7]

          

  glBegin(GL_LINE_LOOP)

        glVertex2f(x1, y1): glVertex2f(x2, y1): glVertex2f(x2, y2): glVertex2f(x1, y2)

        glEnd()

Pour dessiner un cercle

OpenGL n'a pas de primitives de dessin des courbes et des cercles.

Cependant c’est possible approximer un cercle à l'aide d'un ventilateur triangle comme ceci:[7]

             

glBegin(GL_TRIANGLE_FAN)

       glVertex2f(x1, y1)

       for angle# = 0 to 360 step 5

       glVertex2f(x1 + sind(angle#) * radius#, y1 + cosd(angle#) * radius#)

    next

 glEnd()

Ou pour un cercle vide:

           

glBegin(GL_LINE_LOOP)

      for angle# = 0 to 360 step 5

      glVertex2f(x1 + sind(angle#) * radius#, y1 + cosd(angle#) * radius#)

    next

glEnd()

Pour dessiner dans différentes couleurs[7]

Il suffit d'utiliser:

 

glColor3f (red, green, blue)

Pour définir la couleur d'arrière-plan

 glClearColor(red, green, blue, 0)[7]

En plus il y a des méthodes nécessaires à utiliser dans le développement et le dessin de 2D graphiques.

Une mise en œuvre de SurfaceView qui utilise la surface dédiée pour afficher le rendu OpenGL.

Un GLSurfaceView offre les fonctionnalités suivantes:[3]

-Gère une surface, qui est une pièce spéciale de la mémoire qui peuvent être combinées dans le système de vue Android.

-Gère un affichage EGL, qui permet de rendre OpenGL dans une surface.

-Accepte un objet fourni par l'utilisateur de rendu qui fait le rendu réel.

-Renders sur un thread dédié à découpler les performances de rendu du thread d'interface utilisateur.

-Prise en charge à la fois rendu à la demande et en continu.

-Enveloppe éventuellement, des traces, et / ou d'erreurs vérifie les appels de rendu OpenGL.[3]

GLSurfaceView.Renderer : Une interface générique de rendu(Renderer). Qui est chargé de faire des appels OpenGL pour rendre un cadre. Les clients de  GLSurfaceView généralement créé leurs propres classes qui implémentent cette interface, puis appele setRenderer (GLSurfaceView.Renderer) pour enregistrer le rendu avec la GLSurfaceView.

GLSurfaceView.Renderer est une interface générique, qui a trois fonctions abstraites qu’elles doit être mettre en œuvre. Les trois fonctions sont les suivantes:[8] 

1. onSurfaceCreated : Cette méthode est appelée lorsque la surface est créée ou recréée. Ici, les couleurs par défaut d’OpenGL et les paramètres de rendu vont être mettre en place.[8]

public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

  gl10.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); // Set the background color to black ( rgba ).

  gl10.glClearColor(0.0f, 0.0f, 0.0f, 1);

  // Enable Flat Shading.

  gl10.glShadeModel(GL10.GL_FLAT);

  // we don't need to worry about depth testing!

  gl10.glDisable(GL10.GL_DEPTH_TEST);

  // Set OpenGL to optimise for 2D Textures

  gl10.glEnable(GL10.GL_TEXTURE_2D);

  // Disable 3D specific features.

   // but you'll have to figure that out for yourself.

  gl10.glDisable(GL10.GL_DITHER);

  gl10.glDisable(GL10.GL_LIGHTING);

  gl10.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,    GL10.GL_MODULATE); // Initial clear of the screen.

  gl10.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

 }[8]

2. onDrawFrame : Cette méthode est appelée par le thread d'OpenGL pour dessiner le cadre courant. Cette méthode sera appelée en permanence.

   public void onDrawFrame(GL10 gl10) {

   // just clear the screen and depth buffer.

       gl10.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

   }[8]

3. onSurfaceChanged : Cette méthode est appelée lorsque la surface change de taille. Il faut utiliser cette méthode pour coder pour soutenir les différentes tailles d'écran de l'appareil. Pour l'instant, cet exemple va juste faire en sorte que le ratio de fenêtre et de la perspective est correct.

public void onSurfaceChanged(GL10 gl10, int i, int i1) {

   gl10.glViewport(0, 0, i, i1);

 /*

  * Set our projection matrix. This doesn't have to be done each time we

  * draw, but usually a new projection needs to be set when the viewport

  * is resized.

  */

  float ratio = (float) i / i1;

  gl10.glMatrixMode(GL10.GL_PROJECTION);

  gl10.glLoadIdentity();

  gl10.glFrustumf(-ratio, ratio, -1, 1, 1, 10);

  }[8]

3D using Java openGL:

La synthèse d'image 3D (pour trois dimensions : x,y,z, les trois axes qui constituent le repère orthonormé de la géométrie dans l'espace) est un ensemble de techniques qui permet la représentation d'objets en perspective sur un moniteur d'ordinateur. Elle est actuellement très utilisée en art numérique dans l'industrie du film, dans beaucoup de jeux vidéo.[9]

Le dessin 3D sur Android est géré par le GPU (Graphic Unité de traitement) de l'appareil. Le moyen le plus direct pour programmer des graphismes 3D sur Android est par moyens d'OpenGL ES.[10]

Les configurations matérielles requises pour 3D dans la transformation pour Android :

1. En principe, toute GPU prenant en charge OpenGL ES 1.1

2. GPU tels que l’Adreno 200 ou SVG PowerVR 540/530 sont recommandés.

3. Ancien GPU trouve sur des appareils comme le G1 pourrait fonctionner, mais la performance est limitée.

4. Comme une obligation générale de traitement, Android 2.1. Mais, certaines fonctionnalités d'OpenGL manquaient dans 2.1, alors, froyo (2.2) est nécessaire pour tirer pleinement parti du matériel.[11]

N.B. En traitement pour Android il n'est pas nécessaire d'utiliser OpenGL ES directement (même s'il est possible). L'API de dessin dans le traitement utilise OpenGL en interne lors de sélectionnant l'A3D (Android 3D) rendu (renderer). Le moteur de rendu (the renderer) de traitement est le module qui exécute toutes les commandes de dessin.[11]

Pour dessiner un formes géometrique 3D simple par exemple un 3D cube il faut créer 3 classes "Main.java, cube.java et CubeRenderer.java". d'abord, il faut écrire une nouvelle activité dans la méthode onCreate, alors créer deux objets fondamentaux pour utiliser l'API OpenGL, une GLSurfaceView et GLSurfaceView.Renderer.[12]

GLSurfaceView est utilisé pour dessiner et manipuler des objets à l'aide des appels API OpenGL.

GLSurfaceView.Renderer est une interface qui définit les méthodes nécessaires à l'établissement d'une GLSurfaceView OpenGL.[12]

 

 

Main.java

 public class Main extends Activity {

   /** Called when the activity is first created. */

   @Override

   public void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);     

       GLSurfaceView view = new GLSurfaceView(this);

       view.setRenderer(new CubeRenderer());

       setContentView(view);

   }

 }[12]

 

Deuxièmement, il faut créer Cube.java qui utilise deux objets FloatBuffer pour stocker les informations de vertex et de couleurs. Un ByteBuffer pour stocker les indices visage.

Cube.java

 class Cube {           

   private FloatBuffer mVertexBuffer;

   private FloatBuffer mColorBuffer;

   private ByteBuffer  mIndexBuffer;   

   private float vertices[] = {

                               -1.0f, -1.0f, -1.0f,

                               1.0f, -1.0f, -1.0f,

                               1.0f,  1.0f, -1.0f,

                               -1.0f, 1.0f, -1.0f,

                               -1.0f, -1.0f,  1.0f,

                               1.0f, -1.0f,  1.0f,

                               1.0f,  1.0f,  1.0f,

                               -1.0f,  1.0f,  1.0f

                               };

   private float colors[] = {

                              0.0f,  1.0f,  0.0f,  1.0f,

                              0.0f,  1.0f,  0.0f,  1.0f,

                              1.0f,  0.5f,  0.0f,  1.0f,

                              1.0f,  0.5f,  0.0f,  1.0f,

                              1.0f,  0.0f,  0.0f,  1.0f,

                              1.0f,  0.0f,  0.0f,  1.0f,

                              0.0f,  0.0f,  1.0f,  1.0f,

                              1.0f,  0.0f,  1.0f,  1.0f

                           };

      private byte indices[] = {

                             0, 4, 5, 0, 5, 1,

                             1, 5, 6, 1, 6, 2,

                             2, 6, 7, 2, 7, 3,

                             3, 7, 4, 3, 4, 0,

                             4, 7, 6, 4, 6, 5,

                             3, 0, 1, 3, 1, 2            }          

   public Cube() {

           ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);

           byteBuf.order(ByteOrder.nativeOrder());

           mVertexBuffer = byteBuf.asFloatBuffer();

           mVertexBuffer.put(vertices);

           mVertexBuffer.position(0);

               

           byteBuf = ByteBuffer.allocateDirect(colors.length * 4);

           byteBuf.order(ByteOrder.nativeOrder());

           mColorBuffer = byteBuf.asFloatBuffer();

           mColorBuffer.put(colors);

           mColorBuffer.position(0);           

           mIndexBuffer = ByteBuffer.allocateDirect(indices.length);

           mIndexBuffer.put(indices);

           mIndexBuffer.position(0);

   }

   public void draw(GL10 gl) {           

           gl.glFrontFace(GL10.GL_CW);        

           gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);

           gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);

           gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

           gl.glEnableClientState(GL10.GL_COLOR_ARRAY);            

           gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE,

                           mIndexBuffer);              

           gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

           gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

   }

 } [12]

Troisièmement, création de CubeRenderer.java. Il existe trois méthodes ici: onSurfaceCreated(), onDrawFrame() et onSurfaceChanged()

CubeRenderer.java

 class CubeRenderer implements Renderer {

   private Cube mCube = new Cube();

   private float mCubeRotation;

   public void onSurfaceCreated(GL10 gl, EGLConfig config) {

       gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);          

       gl.glClearDepthf(1.0f);

       gl.glEnable(GL10.GL_DEPTH_TEST);

       gl.glDepthFunc(GL10.GL_LEQUAL);

       gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,

                 GL10.GL_NICEST);       

   }  

   public void onDrawFrame(GL10 gl) {

       gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);      

       gl.glLoadIdentity();       

       gl.glTranslatef(0.0f, 0.0f, -10.0f);

       gl.glRotatef(mCubeRotation, 1.0f, 1.0f, 1.0f);         

       mCube.draw(gl);

       gl.glLoadIdentity();                                  

       mCubeRotation -= 0.15f;

   }

   public void onSurfaceChanged(GL10 gl, int width, int height) {

       gl.glViewport(0, 0, width, height);

       gl.glMatrixMode(GL10.GL_PROJECTION);

       gl.glLoadIdentity();

       GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);

       gl.glViewport(0, 0, width, height);

       gl.glMatrixMode(GL10.GL_MODELVIEW);

       gl.glLoadIdentity();

   }

 } [12]

 

 

 

 

 

Notes et références

 

  1- http://source.android.com/

  2- http://en.wikipedia.org/wiki/List_of_features_in_Android

  3- http://developer.android.com/guide/topics/graphics/opengl.html

  4- http://fr.wikipedia.org/wiki/OpenGL

  5- http://en.wikipedia.org/wiki/OpenGL_ES

  6- http://en.wikipedia.org/wiki/2D_computer_graphics

  7- http://basic4gl.wikispaces.com/2D+Drawing+in+OpenGL

  8- http://apecoder.net/2010/11/12/using-2d-opengl-on-android-part-1/

  9- http://fr.wikipedia.org/wiki/Infographie_tridimensionnelle

 10- http://www.khronos.org/opengles/

 11- http://users.design.ucla.edu/~acolubri/files/Fast3DGraphics.pdf

 12- http://blogs.mervpolis.com/roller/netoyaOzora/entry/android_3d_cube_using_opengl

Comments