Skip to content

Commit

Permalink
Add text management in a similar fashion than GLUT.glutBitmapString()
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-pernollet committed Oct 14, 2020
1 parent 84f1e0a commit fbcbd72
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 11 deletions.
127 changes: 119 additions & 8 deletions src/main/java/jgl/GL.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,19 @@
package jgl;

import java.applet.Applet;
import java.awt.Color;
// import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.MemoryImageSource;
import java.util.ArrayList;
import java.util.List;

import jgl.context.gl_context;
import jgl.context.gl_list;
Expand Down Expand Up @@ -624,9 +631,10 @@ public class GL {
protected gl_list List;
protected Component JavaComponent;
protected Image JavaImage;
// protected MemoryImageSource JavaImageSource;
protected int StartX = 0;
protected int StartY = 0;
protected List<TextToDraw> textsToDraw = new ArrayList<>();


public Image getRenderedImage() {
return JavaImage;
Expand Down Expand Up @@ -1714,17 +1722,119 @@ public String glGetString(int name) {

/** Creates a new {@link MemoryImageSource} based on the current color buffer.
*
* This image can later be applied to a {@link Component} using {@link #glXSwapBuffers(Graphics, ImageObserver)}*/
* This image can later be applied to a {@link Component} using {@link #glXSwapBuffers(Graphics, ImageObserver)}
*/
public void glFlush() {
if (Context.RenderMode != GL_RENDER) {
return;
}
// JavaImage = JavaApplet.createImage(new MemoryImageSource
JavaImage = JavaComponent.createImage(new MemoryImageSource(Context.Viewport.Width, Context.Viewport.Height,
Context.ColorBuffer.Buffer, 0, Context.Viewport.Width));
// System.out.println ("create Java Image");
// JavaImageSource.newPixels();

// ------------------------------------------
// Create an image producer based on
// colorbuffer into which GL draws
ImageProducer producer = new MemoryImageSource(
Context.Viewport.Width,
Context.Viewport.Height,
Context.ColorBuffer.Buffer,
0,
Context.Viewport.Width);

// Generates an image from the toolkit to use this producer
Image colorBuffer = JavaComponent.createImage(producer);

// ------------------------------------------
// Write GL content in a temporary image
// and then to the image returned to Canvas

if(HANDLE_TEXT) {
JavaImage = new BufferedImage(colorBuffer.getWidth(null), colorBuffer.getHeight(null), BufferedImage.TYPE_INT_ARGB);

Graphics2D g2d = (Graphics2D) JavaImage.getGraphics();

// Color buffer
g2d.drawImage(colorBuffer, 0, 0, null);

// Text
drawText(g2d);
}

// ------------------------------------------
// Write GL content to the image returned
// to Canvas

else {
JavaImage = colorBuffer;
}
}

private static boolean HANDLE_TEXT = true;

/**
* Renders appended text to given {@link Graphics2D} context.
* @param g2d
*/
protected void drawText(Graphics2D g2d) {
synchronized (textsToDraw) {
for(TextToDraw text: textsToDraw) {
g2d.setFont(text.font);
if(text.r>=0) {
g2d.setColor(new Color(text.r, text.g, text.b));
}
else {
g2d.setColor(Color.BLACK);
}
g2d.drawString(text.string, text.x, text.y);
}
textsToDraw.clear(); // empty text buffer
}
}

/**
* To be called by {@link GLUT#glutBitmapString(Font, String, float, float)} to append
* text to a list of text to render at {@link GL#glFlush()} step.
*/
protected void appendText(Font font, String string, int x, int y) {
synchronized (textsToDraw) {
textsToDraw.add(new TextToDraw(font, string, x, y));
}
}

/**
* To be called by {@link GLUT#glutBitmapString(Font, String, float, float)} to append
* text to a list of text to render at {@link GL#glFlush()} step.
*/
protected void appendText(Font font, String string, int x, int y, float r, float g, float b) {
synchronized (textsToDraw) {
textsToDraw.add(new TextToDraw(font, string, x, y, r, g, b));
}
}

class TextToDraw{
Font font;
String string;
int x;
int y;
float r;
float g;
float b;

public TextToDraw(Font font, String string, int x, int y) {
this(font, string, x, y, -1, -1, -1);
}

public TextToDraw(Font font, String string, int x, int y, float r, float g, float b) {
super();
this.font = font;
this.string = string;
this.x = x;
this.y = y;
this.r = r;
this.g = g;
this.b = b;
}
}



/**
* Depth Buffer
Expand Down Expand Up @@ -6089,8 +6199,9 @@ public boolean glXMakeCurrent(Component o, int x, int y) {
// public void glXSwapBuffers (Graphics g, Applet o) {
public void glXSwapBuffers(Graphics g, ImageObserver o) {
// if (JavaImage != null) g.drawImage (JavaImage, StartX, StartY, o);

g.drawImage(JavaImage, StartX, StartY, o);

// if (Context.RenderMode != GL_RENDER) { return; }
// int i, j, k = 0;
// for (i = StartY; i < Context.Viewport.Height; i++) {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/jgl/GLCanvas.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void update(Graphics g) {
public void paint(Graphics g) {
myGL.glXSwapBuffers(g, this);

firePostPaintEvents(g);
//firePostPaintEvents(g);
}

// ************ RETRIEVE RENDERING CONTEXT ************ //
Expand All @@ -77,7 +77,7 @@ public GLUT getGLUT() {

// ************ LISTEN PAINT METHOD CALLS ************ //

public interface PaintListener{
/*public interface PaintListener{
public void postPaint(Graphics g);
}
Expand All @@ -99,7 +99,7 @@ public void firePostPaintEvents(Graphics g) {
for(PaintListener listener: listeners) {
listener.postPaint(g);
}
}
}*/

// ************ MANUAL REPAINT ************ //

Expand Down
92 changes: 92 additions & 0 deletions src/main/java/jgl/GLUT.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ComponentEvent;
import java.awt.event.InputEvent;
Expand All @@ -34,6 +35,7 @@
import java.util.TimerTask;
import java.util.Vector;


import jgl.glaux.teapot;
import jgl.glu.GLUquadricObj;
import jgl.glut.glut_menu;
Expand Down Expand Up @@ -121,6 +123,96 @@ public class GLUT implements Runnable {
private glut_menu currentMenu = null;
private int JavaMenuButton = -1;
private int keyModifiers = 0;

/**
* Print string at the specified 2d position.
*
* This method is not following exactly the GLUT interface.
* Printing text in OpenGL usually requires such code :
*
* <pre><code>
* gl.glColor3f(r, g, b);
* gl.glRasterPos3f(x, y, z);
* glut.glutBitmapString(font, string);
* </code></pre>
*
* In our case, one need to first perform model-to-screen projection to get
* x,y coordinates, and then call glutBitmapString.
*
* @see {@link #glutBitmapString(Font, String, float, float, float, float, float, float) to avoid doing the model-to-screen projection.
*/
public void glutBitmapString(Font font, String string, float x, float y) {
JavaGL.appendText(font, string, (int)x, (int)y);
}

/**
* Print string at the specified 3d position.
*
* This method is not following exactly the GLUT interface.
* Printing text in OpenGL usually requires such code :
*
* <pre><code>
* gl.glColor3f(r, g, b);
* gl.glRasterPos3f(x, y, z);
* glut.glutBitmapString(int font, string);
* </code></pre>
*
* Here we provide a convenient function that does all in one pass
* <pre><code>
* glut.glutBitmapString(java.awt.Font, java.lang.String, x, y, z, r, g, b);
* </code></pre>
*
* Behind the scene it makes the model-to-screen conversion and then
* provide all data to {@link GL#appendText(Font, String, int, int, float, float, float)}
* that will handle the text rendering in {@link GL#glFlush()}
*/
public void glutBitmapString(Font font, String string, float x, float y, float z, float r, float g, float b) {
double[] win = modelToScreen(x, y, z);

double winX = win[0];
double winY = JavaGL.Context.Viewport.Height - win[1];


JavaGL.appendText(font, string, (int)winX, (int)winY, r, g, b);
}

protected double[] modelToScreen(float x, float y, float z) {
int viewport[] = getViewPortAsInt();

double winx[] = new double[1];
double winy[] = new double[1];
double winz[] = new double[1];

if (!JavaGLU.gluProject(x, y, z, getModelViewAsDouble(), getProjectionAsDouble(), viewport, winx, winy, winz))
System.err.println("GLUT.modelToScreen : Could not retrieve model coordinates in screen for " + x + ", "+ y+ ", "+ z);

double[] win = new double[3];
win[0] = winx[0];
win[1] = winy[0];
win[2] = winz[0];

return win;
}

protected int[] getViewPortAsInt() {
int viewport[] = new int[4];
JavaGL.glGetIntegerv(GL.GL_VIEWPORT, viewport);
return viewport;
}

protected double[] getModelViewAsDouble() {
double modelview[] = new double[16];
JavaGL.glGetDoublev(GL.GL_MODELVIEW_MATRIX, modelview);
return modelview;
}

protected double[] getProjectionAsDouble() {
double projection[] = new double[16];
JavaGL.glGetDoublev(GL.GL_PROJECTION_MATRIX, projection);
return projection;
}
//</pre>


/** Private Member Functions */
/*
Expand Down

0 comments on commit fbcbd72

Please sign in to comment.