JavaFX et JOGL fonctionnent ensemble [JavaFX and JOGL work together]

JOGL with JavaFX (OpenJFX 14) [JOGL avec JavaFX (OpenJFX 14)]
Français English
Sommaire :

Summary:

Introduction

Introduction

Le support de JavaFX dans JOGL était demandé depuis très longtemps 1. Je remercie chaleureusement Sven Göthel pour son énorme travail sur JogAMP 2 (JOGL, JOCL, JOAL, GlueGen, …) depuis plus d’un décennie, il a implémenté un canevas JavaFX basé sur NEWT (l’API de fenêtrage propre à JOGL) appelé NewtCanvasJFX 3. Cette tâche était loin d’être triviale comme JavaFX n’est pas conçu pour interagir avec des APIs de rendu de bas niveau, Sven a dû appeler des méthodes non publiques et non exportées 4. The support of JavaFX within JOGL was in demand for a very long time 1. I warmly thank Sven Göthel for his enormous work on JogAMP 2 (JOGL, JOCL, JOAL, GlueGen, …) since more than a decade, he implemented a JavaFX canvas based on NEWT (JOGL’s own windowing API) called NewtCanvasJFX 3. This task was far from being trivial as JavaFX isn’t designed to interact with some low-level rendering APIs, Sven had to call some non public and non exported methods 4.
Il est possible d’utiliser javafx.embed.swing.SwingNode pour embarquer du contenu Swing depuis JavaFX 8 afin d’utiliser JOGL avec JavaFX par l’intermédiaire de Swing via le panneau Swing de JOGL appelé GLJPanel mais NewtCanvasJFX 3 offre de meilleures performances. It has been possible to use javafx.embed.swing.SwingNode to embed some Swing content since JavaFX 8 in order to use JOGL with JavaFX through the intermediary of Swing by way of JOGL’s Swing panel named GLJPanel but NewtCanvasJFX 3 offers better performance.
Je vais vous aider à préparer votre environnement de développement pour pouvoir lancer mon exemple rudimentaire. I’m going to help you to prepare your development environment to be able to run my rudimentary example.

Installation

Installation

Java

Java

Vous avez besoin du kit de développement Java (JDK), soit OpenJDK (via AdoptOpenJDK 5 ou Oracle 6) soit Oracle Java (sur le site officiel d’Oracle 7) quel que soit votre système d’exploitation. Apple Java n’est pas compatible avec JavaFX et déprécié depuis OS X 10.6 8. You need the Java development kit (JDK), either OpenJDK (via AdoptOpenJDK 5 or Oracle 6) or Oracle Java (on the official Oracle website 7) whatever your operating system is. Apple Java isn’t compatible with JavaFX and deprecated since OS X 10.6 8.
Ajoutez une variable d’environnement pointant vers le répertoire d’installation du JDK en entrant Add an environment variable pointing to the installation directory of the JDK by entering
export JAVA_HOME=path/to/jdk-14
sous GNU Linux ou Mac ou bien under GNU Linux or Mac or
set JAVA_HOME=path\to\jdk-14
sous Microsoft Windows. under Microsoft Windows.
Ce tutoriel nécessite au moins Java 9 mais je l’ai mis au point avec Java 14. This tutorial requires at least Java 9 but I developed it with Java 14.

JogAMP

JogAMP

Vous avez besoin du fat JAR de JogAMP 9 appelé jogamp-fat.jar qui comprend JOGL 2.4.0. You need JogAMP’s fat JAR 9 named jogamp-fat.jar that contains JOGL 2.4.0.

JavaFX

JavaFX

Téléchargez l’environnement d’exécution de JavaFX 10 et décompressez-le dans le répertoire de votre choix. Download the JavaFX runtime 10 and unzip it in the directory of your choice.
Ajoutez une variable d’environnement pointant vers le répertoire « lib » de l’environnement d’exécution de JavaFX en entrant Add an environment variable pointing to the « lib » directory of the JavaFX runtime by entering
export PATH_TO_FX=chemin/vers/javafx-sdk-14/lib
sous GNU Linux ou Mac ou bien under GNU Linux or Mac or
set PATH_TO_FX=path\to\javafx-sdk-14\lib
sous Microsoft Windows. under Microsoft Windows.

Compilation et exécution

Compilation and execution

Interface en ligne de commande

Command line interface

L’arborescence de fichiers du projet est la suivante : The project file tree structure is as follows:
  • joglojfx
    • jogamp-fat.jar
    • src
      • main
        • java
          • org
            • jogamp
              • joglojfx
                • App.java
    • target
      • classes
        • org
          • jogamp
            • joglojfx
              • App.class
Le répertoire contenant le code source s’appelle « src/main/java ». Le paquetage de la classe principale s’appelle « org.jogamp.joglojfx ». La classe principale s’appelle App. Le répertoire contenant les fichiers .class s’appellent « target/classes ». Le fat JAR de JogAMP jogamp-fat.jar est à la racine du projet. Entrez The directory containing the source code is named « src/main/java ». The package of the main class is named « org.jogamp.joglojfx ». The main class is named App. The directory containing containing the .class files is named « target/classes ». JogAMP’s fat JAR jogamp-fat.jar is at the root of the project. Enter
$JAVA_HOME/bin/javac --module-path $PATH_TO_FX --add-modules javafx.controls src/main/java/org/jogamp/joglojfx/App.java -d target/classes -cp jogamp-fat.jar
sous GNU Linux ou Mac ou bien under GNU Linux or Mac or
%JAVA_HOME%\bin\javac --module-path %PATH_TO_FX% --add-modules javafx.controls src/main/java/org/jogamp/joglojfx/App.java -d target/classes -cp jogamp-fat.jar
sous Microsoft Windows pour compiler l’exemple que je vais vous montrer. Entrez under Microsoft Windows to compile the example that I’m going to show you. Enter
$JAVA_HOME/bin/java --module-path $PATH_TO_FX --add-modules javafx.controls --add-opens javafx.graphics/com.sun.javafx.tk=ALL-UNNAMED --add-opens javafx.graphics/javafx.stage=ALL-UNNAMED --add-opens javafx.graphics/com.sun.javafx.tk.quantum=ALL-UNNAMED --add-opens javafx.graphics/com.sun.glass.ui=ALL-UNNAMED -cp target/classes:jogamp-fat.jar org.jogamp.joglojfx.App
sous GNU Linux ou Mac ou bien under GNU Linux or Mac or
%JAVA_HOME%\bin\java --module-path %PATH_TO_FX% --add-modules javafx.controls --add-opens javafx.graphics/com.sun.javafx.tk=ALL-UNNAMED --add-opens javafx.graphics/javafx.stage=ALL-UNNAMED --add-opens javafx.graphics/com.sun.javafx.tk.quantum=ALL-UNNAMED --add-opens javafx.graphics/com.sun.glass.ui=ALL-UNNAMED -cp target/classes;jogamp-fat.jar org.jogamp.joglojfx.App
sous Microsoft Windows pour lancer l’exemple que je vais vous montrer. under Microsoft Windows to run the example that I’m going to show you.
N.B : Vous devez remplacer « ALL-UNNAMED » par « jogamp.fat » dans un projet modulaire. N.B: You must remplace « ALL-UNNAMED » by « jogamp.fat » in a modular project.

Maven

Maven

Il n’est pas encore possible d’utiliser Maven pour compiler et lancer mon exemple comme JOGL 2.4.0 n’est pas encore sur Maven Central mais je mettrai à jour cette partie dès que ce sera fait. Using Maven to compile and run my example isn’t possible yet because JOGL 2.4.0 isn’t on Maven Central yet but I’ll update this section as soon as it will be done.

Exemple

Example

Cet exemple se veut rudimentaire, c’est surtout pour montrer le principe de base. This example is meant to be rudimentary, it’s mostly to show the basic principle.
package org.jogamp.joglojfx;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GL2ES1;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.fixedfunc.GLLightingFunc;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
import com.jogamp.newt.javafx.NewtCanvasJFX;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;

public class App extends Application {

    private Animator animator;

    @Override
    public void start(Stage stage) {
        Platform.setImplicitExit(true);
        final Group g = new Group();
        Scene scene = new Scene(g, 800, 600);
        stage.setScene(scene);
        stage.show();
        com.jogamp.newt.Display jfxNewtDisplay = NewtFactory.createDisplay(null, false);
        final Screen screen = NewtFactory.createScreen(jfxNewtDisplay, 0);
        final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxFixedFunc(true));
        final GLWindow glWindow1 = GLWindow.create(screen, caps);
        glWindow1.addGLEventListener(new GLEventListener() {
               private float rotateT = 0.0f;
        
               public void init(final GLAutoDrawable drawable) {
                   GL2 gl = drawable.getGL().getGL2();
		           gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
		           gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		           gl.glClearDepth(1.0f);
		           gl.glEnable(GL.GL_DEPTH_TEST);
		           gl.glDepthFunc(GL.GL_LEQUAL);
		           gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
               }
               public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
                   GL2 gl = drawable.getGL().getGL2();
		           final float aspect = (float) width / (float) height;
		           gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
		           gl.glLoadIdentity();
		           final float fh = 0.5f;
		           final float fw = fh * aspect;
		           gl.glFrustumf(-fw, fw, -fh, fh, 1.0f, 1000.0f);
		           gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
		           gl.glLoadIdentity();
               }
               public void display(final GLAutoDrawable drawable) {
                   final GL2 gl = drawable.getGL().getGL2();
		           gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		           gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
		           gl.glLoadIdentity();
		           gl.glTranslatef(0.0f, 0.0f, -5.0f);
		           gl.glRotatef(rotateT, 1.0f, 0.0f, 0.0f);
		           gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
		           gl.glRotatef(rotateT, 0.0f, 0.0f, 1.0f);
		           gl.glBegin(GL2.GL_QUADS);       
		           gl.glColor3f(0.0f, 1.0f, 1.0f);
		           gl.glVertex3f(-1.0f, 1.0f, 0.0f);
		           gl.glVertex3f( 1.0f, 1.0f, 0.0f);
		           gl.glVertex3f( 1.0f,-1.0f, 0.0f);
		           gl.glVertex3f(-1.0f,-1.0f, 0.0f);
		           gl.glEnd();                  
		           rotateT += 0.2f; 
               }
               public void dispose(final GLAutoDrawable drawable) {
               }
            });
        final NewtCanvasJFX glCanvas = new NewtCanvasJFX(glWindow1);
        glCanvas.setWidth(800);
        glCanvas.setHeight(600);
        g.getChildren().add(glCanvas);
        animator = new Animator(glWindow1);
        animator.start();
    }
    
    @Override
    public void stop() throws Exception {
        if (animator != null) {
            animator.stop();
        }
    }

    public static void main(String[] args) {
        launch();
    }
}
Cet exemple est basé sur le test unitaire écrit par Sven 11. This example is based on the unit test written by Sven 11.

Conclusion

Conclusion

Mon exemple est très simple, il n’a pas pour but de montrer toutes les possibilités offertes par NewtCanvasJFX 3. Vous pouvez l’ajouter à un conteneur JavaFX aussi bien avant ou après avoir rendu le composant de plus haut niveau visible. Selon moi, il serait intéressant d’afficher des composants JavaFX sur le canevas NewtCanvasJFX, par exemple pour bénéficier d’un moteur 3D basé sur JOGL tout en utilisant JavaFX comme bibliothèque de composants graphiques 2D. My example is very simple, it doesn’t aim to demonstrate all possibilities offered by NewtCanvasJFX 3. You can add it into a JavaFX container either before or after driving the top level component visible. According to me, it would be interesting to display some JavaFX components over the NewtCanvasJFX canvas, for example to benefit from a JOGL based 3D engine while using JavaFX as a library of 2D graphic components.

Références

References

[1]Rapport de bogue de JOGL « JavaFX 2+ et JOGL devrait fonctionner ensemble »
[2]Page d’accueil de JogAMP
[3]Documentation de l’API Java de NewtCanvasJFX
[4]JFXAccessor
[5]AdoptOpenJDK
[6]OpenJDK
[7]Oracle JavaSE
[8]Dépréciation d’Apple Java
[9]Le fat JAR de JogAMP comprenant JOGL 2.4.0
[10]L’environnement d’exécution de JavaFX
[1]Bug report of JOGL « JavaFX 2+ and JOGL should work together »
[2]Homepage of JogAMP
[3]Java API documentation of NewtCanvasJFX
[4]JFXAccessor
[5]AdoptOpenJDK
[6]OpenJDK
[7]Oracle JavaSE
[8]Apple Java deprecation
[9]JogAMP’s fat JAR containing JOGL 2.4.0
[10]The JavaFX runtime
[11]Le test unitaire de NewtCanvasJFX écrit par Sven Göthel [11]The unit test of NewtCanvasJFX written by Sven Göthel
Licence Creative Commons
Les photos de cet article sont mises à disposition selon les termes de la Licence Creative Commons Attribution – Pas d’Utilisation Commerciale – Pas de Modification 3.0 non transposé
Creative Commons License
The photos of this article are licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License
Licence Creative Commons
Cet article est mis à disposition selon les termes de la Licence Creative Commons Attribution – Pas d'Utilisation Commerciale – Partage à l'Identique 3.0 non transposé
Creative Commons License
This article is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
Auteur : Julien Gouesse Author: Julien Gouesse

A propos gouessej

Ingénieur en informatique, militant politique d'extrême-gauche, développeur de logiciels libres multi-plateformes. Engineer in computer science, far left-wing political activist, developer of free open source cross-platform softwares.
Cet article, publié dans Jeux vidéo, est tagué , , . Ajoutez ce permalien à vos favoris.