Login  Register

Re: Text without AWT?

Posted by Xerxes Rånby on Mar 01, 2017; 11:20am
URL: https://forum.jogamp.org/Text-without-AWT-tp4037684p4037707.html

I have implemented a single class that demo the Graph API for text rendering without using AWT.

you can checkout this code using git and test it:
git clone https://github.com/xranby/jogamp-forum-examples
cd jogamp-forum-examples/xranby
sh fetch-jogamp-build-and-run.sh


https://twitter.com/xranby/status/836946773637738497

package com.gudinna;

import com.jogamp.graph.curve.Region;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;

import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.curve.opengl.TextRegionUtil;
import com.jogamp.graph.geom.SVertex;

import com.jogamp.newt.opengl.GLWindow;

import com.jogamp.opengl.*;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.PMVMatrix;

import java.io.IOException;

/**
 * <pre>
 *   __ __|_  ___________________________________________________________________________  ___|__ __
 *  //    /\                                           _                                  /\    \\
 * //____/  \__     __ _____ _____ _____ _____ _____  | |     __ _____ _____ __        __/  \____\\
 *  \    \  / /  __|  |     |   __|  _  |     |  _  | | |  __|  |     |   __|  |      /\ \  /    /
 *   \____\/_/  |  |  |  |  |  |  |     | | | |   __| | | |  |  |  |  |  |  |  |__   "  \_\/____/
 *  /\    \     |_____|_____|_____|__|__|_|_|_|__|    | | |_____|_____|_____|_____|  _  /    /\
 * /  \____\                       http://jogamp.org  |_|                              /____/  \
 * \  /   "' _________________________________________________________________________ `"   \  /
 *  \/____.                                                                             .____\/
 * </pre>
 *
 * <p>
 * JogAmp JOGL OpenGL ES 2 graph text demo to expose and learn how to use the graph API to draw text.
 *
 * Inside the main JOGL source tree we have the "Graph" API that is what we consider
 * the *best* way to render text using nurbs on all GPU's.
 * Graph is using a patent free shaders implementation.
 * Graph is suitable for both desktop and mobile GPU processors.
 *
 * NOTE: This demo is using jogamp.graph.font.fonts.ubuntu is found inside jogl-fonts-p0.jar
 * you may need to add this jar to your classpath
 * http://jogamp.org/deployment/jogamp-current/jar/atomic/jogl-fonts-p0.jar
 *
 * In a nutshell the JogAmp Graph API enable you to define nurbs shapes
 * Outline → OutlineShapes → GLRegion
 * and then render the shapes using a Renderer
 * RegionRenderer
 * TextRegionUtil (same as RegionRender with Helper methods for texts and fonts.)
 *
 * To load a Font you need to implement your own FontSet
 * The JogAmp JOGL source tree contains two FontSet's
 * One for loading Ubuntu true type fonts bundled with JogAmp
 * One for loading "Java" true type fonts bundled with the JRE
 * http://jogamp.org/git/?p=jogl.git;a=blob;f=src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java;hb=HEAD
 * http://jogamp.org/git/?p=jogl.git;a=blob;f=src/jogl/classes/jogamp/graph/font/JavaFontLoader.java;hb=HEAD
 * The FontFactory class can be used to load a default JogAmp FontSet Font.
 *
 * The graph API is using the math by Rami Santina introduced in 2011
 * https://jogamp.org/doc/gpunurbs2011/p70-santina.pdf
 * https://jogamp.org/doc/gpunurbs2011/graphicon2011-slides.pdf
 *
 * The best documentation for the graph API is found in the JOGL junit tests
 * http://jogamp.org/git/?p=jogl.git;a=tree;f=src/test/com/jogamp/opengl/test/junit/graph;hb=HEAD
 *
 * and javadoc for Outline and OutlineShape .. and all classes i mentioned above..
 * https://www.jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/graph/geom/Outline.html
 * https://www.jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/graph/curve/OutlineShape.html
 * </p>
 *
 * @author Xerxes Rånby (xranby)
 */

public class JogAmpGraphAPITextDemo {

    static Animator animator;

    public static void main(String[] args) {

        // Enable JOGL debugging of GLSL shader compilation and GL calls
        //System.setProperty( "jogl.debug.GLSLCode", "");
        //System.setProperty( "jogl.debug.DebugGL", "");

        GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2));
        caps.setAlphaBits(4);
        GLWindow glWindow = GLWindow.create(caps);
        glWindow.setSize(800,400);
        glWindow.setTitle("JogAmp JOGL Graph API text demo");
        glWindow.setVisible(true);

        glWindow.addGLEventListener(new GraphText() /* GLEventListener */);

        animator = new Animator();
        animator.add(glWindow);
        animator.start();
    }

    private static class GraphText implements GLEventListener{

        TextRegionUtil textRegionUtil;
        RenderState renderState;
        RegionRenderer regionRenderer;

        Font font;
        static int fontSet = FontFactory.UBUNTU;
        static int fontFamily = 0; // default
        static int fontStyleBits = 0; // default

        volatile float weight = 1.0f;
        volatile double lastTime = com.jogamp.common.os.Platform.currentTimeMicros();

        final float fontSize = 10.0f;

        final float zNear = 0.1f, zFar = 7000f;

        /* 2nd pass texture size antialias SampleCount
           4 is usually enough */
        private final int[] sampleCount = new int[] { 4 };

        /* variables used to update the PMVMatrix before rendering */
        private float xTranslate = -40f;
        private float yTranslate =  0f;
        private float zTranslate = -100f;
        private float angleRotate = 0f;

        private final int renderModes = Region.VARWEIGHT_RENDERING_BIT;

        double fpsHuman;

        @Override
        public void init(GLAutoDrawable drawable) {

            final GL2ES2 gl = drawable.getGL().getGL2ES2();

            /* SwapInterval 1 makes the demo run at 60 fps
            use SwapInterval 0 here to get ... hundreds ... sometimes thousands of fps!
            SwapInterval 0 can cause stuttering due to thermal throttling of your GPU */
            gl.setSwapInterval(1);

            gl.glEnable(GL.GL_DEPTH_TEST);
            gl.glEnable(GL.GL_BLEND);
            gl.glClearColor(1.0f, 0.0f, 1.0f, 1.0f);

            /* load a ttf font */
            try {
                /* JogAmp FontFactory will load a true type font
                 *
                 * fontSet == 0 loads
                 * jogamp.graph.font.fonts.ubuntu found inside jogl-fonts-p0.jar
                 * http://jogamp.org/deployment/jogamp-current/jar/atomic/jogl-fonts-p0.jar
                 *
                 * fontSet == 1 tries loads LucidaBrightRegular from the JRE.
                 */

                font = FontFactory.get(fontSet).get(fontFamily, fontStyleBits);
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(1);
            }


            /* initialize OpenGL specific classes that know how to render the graph API shapes */
            renderState = RenderState.createRenderState(SVertex.factory());
            // define a RED colour to render our shape with
            renderState.setColorStatic(1.0f, 0.0f, 0.0f, 1.0f);
            renderState.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);

            regionRenderer = RegionRenderer.create(renderState, /* GLCallback */ RegionRenderer.defaultBlendEnable, /* GLCallback */ RegionRenderer.defaultBlendDisable);

            textRegionUtil = new TextRegionUtil(renderModes);

            regionRenderer.init(gl, renderModes);
            regionRenderer.enable(gl, false);
        }

        @Override
        public void dispose(GLAutoDrawable drawable) {
            final GL2ES2 gl = drawable.getGL().getGL2ES2();
            //stop the animator thread when user close the window
            animator.stop();
            // it is important to free memory allocated no the GPU!
            // this memory cant be garbage collected by the JVM
            renderState.destroy(gl);
        }

        @Override
        public void display(GLAutoDrawable drawable) {
            final GL2ES2 gl = drawable.getGL().getGL2ES2();

            // use JogAmp high resolution timer for smooth animations!
            double time = com.jogamp.common.os.Platform.currentTimeMicros();
            double fps = Math.floor(1000000f/(time-lastTime));
            lastTime = time;

            // fps updates too fast for humans to read... sample an fps at some frames.
            if(time%100==0) {
                fpsHuman = fps;
            }

            float sinusAnimationRotate = (float) (Math.sin(time/1000000f));

            String text = "JogAmp GRAPH API Text demo\nFPS: "+fps+"\nFPS human readable: "+fpsHuman;

            // clear screen
            gl.glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
            gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

            float offsetX = -30;
            float offsetY = 30;

            // When rendering text we need to account for newlines inside the text.
            final int newLineCount = TextRegionUtil.getCharCount(text, '\n');

            final float lineHeight = font.getLineHeight(fontSize);
            offsetX += font.getAdvanceWidth('X', fontSize);
            offsetY -= lineHeight * newLineCount;

            // the RegionRenderer PMVMatrix define where we want to render our shape
            final PMVMatrix Pmv = regionRenderer.getMatrix();
            Pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
            Pmv.glLoadIdentity();
            Pmv.glTranslatef(xTranslate+offsetX, yTranslate+offsetY, zTranslate);
            Pmv.glRotatef(angleRotate+ 10f * sinusAnimationRotate, 0, 0, 1);

            if( weight != regionRenderer.getRenderState().getWeight() ) {
                regionRenderer.getRenderState().setWeight(weight);
            }

            // Draw the  shape using RegionRenderer and TextRegionUtil
            regionRenderer.enable(gl, true);
            textRegionUtil.drawString3D(gl, regionRenderer, font, fontSize, text, null, sampleCount);
            regionRenderer.enable(gl, false);
        }

        @Override
        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
            final PMVMatrix Pmv = regionRenderer.getMatrix();
            regionRenderer.reshapePerspective(45.0f, width, height, zNear, zFar);
            Pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
            Pmv.glLoadIdentity();
        }
    }
}