Computer graphics -- 2008-2009 -- info.uvt.ro/Laboratory 5

From Wikiversity
Jump to navigation Jump to search

Quick links: front; laboratories agenda, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, JOGL template.


2D GRAPHICS BASICS (PART 4)[edit]

Placing text in your scene[edit]

In (J)OGL one can place text at certain coordinates (2D or 3D). This is easily achieved by using the GLUT API. The method (function) intended for displaying text is glutBitmapString.

Important: it should never be placed inside a glBegin/glEnd block.

Before using it we need however to specify the raster position (used to position pixel and bitmap write operations) by using the glRasterPos method (function). The object coordinates presented by glRasterPos are treated just like those given with glVertex methods (functions).

// Import the GLUT class so that we can use it.
import com.jogamp.opengl.util.gl2.GLUT;

public class MainFrame [...] {

	// GLUT object used for displaying text.
	private GLUT glut;

	public void init(GLAutoDrawable canvas)
	{
		[...]

		// Create a new GLU object.
		glut = new GLUT();

		[...]
	}

	public void display(GLAutoDrawable canvas)
	{
		[...]

		// Specify the raster position.
		gl.glRasterPos2d(0.5, 0.5);
		// Render the text in the scene.
		glut.glutBitmapString(GLUT.BITMAP_HELVETICA_10, "Hello World");

		[...]
	}
}

2D Application Example[edit]

Simple Star Chart[edit]

In what follows we will put together what we have seen so far and create a simple 2D application which displays a Star Chart. A Star Chart is basically a projection (using for example the Polar Projection) of constellations, stars and other stellar objects on a screen (paper).

To do this we need an API for reading and computing the coordinates of our objects (constellations, stars, names) from some data files. A simple API which does the previous can be found here.

The next code fragment shows you how you it could be used:

// Import the PolarProjectionMap class so that we can use it.
import astro.PolarProjectionMap;

public class MainFrame [...] {

	// Holds a reference to the PolarProjectionMap object.
	private PolarProjectionMap ppm = null;
	// Used to identify the display list.
	private int ppm_list;

	public void init(GLAutoDrawable canvas)
	{
		[...]

		// Initialize the object.
		this.ppm = new PolarProjectionMap(21.53, 45.17);
		// Set the separator for the line fields.
		this.ppm.setFileSep(",");
		// Read the file and compute the coordinates.
		this.ppm.initializeConstellationLines("data/conlines.dat");
		// Initialize here the rest of the elements from the remaining files using the corresponding methods.

		// Create the display list.
		this.ppm_list = gl.glGenLists(1);
		gl.glNewList(this.ppm_list, GL.GL_COMPILE);
			this.makePPM(gl);
		gl.glEndList();
		[...]
	}

	public void display(GLAutoDrawable canvas)
	{
		[...]

		gl.glCallList(this.ppm_list);

		[...]
	}

	// We use this method for creating the display list.
	private void makePPM(GL2 gl) {
		final ArrayList<PolarProjectionMap.ConstellationLine> clLines = this.ppm.getConLines();
		// Add here the rest of the ArrayLists.
		
		gl.glColor3f(0.0f, 1.0f, 0.0f);

		gl.glBegin(GL2.GL_LINES);
		for (PolarProjectionMap.ConstellationLine cl : clLines) {
			if (cl.isVisible()) {
				gl.glVertex2d(cl.getPosX1(), cl.getPosY1());
				gl.glVertex2d(cl.getPosX2(), cl.getPosY2());
			}
		}
		gl.glEnd();
		
		// Add here the rest of the code for rendering constellation boundaries (use GL_LINES), 
		// names (use glutBitmapString), stars (use GL_POINTS) and cardinal points (use glutBitmapString).
	}
}

Links:

PUBLISHING YOUR JOGL APPLICATION[edit]

Usually you will want to make your JOGL application available to everyone. The simplest way to achieve this is to publish your application on a website either as an applet or as a Java Web Start application. For JOGL this is probably the way any developer does. Next we will address the second issue as it allows you to download and run signed application directly on your computer without requiring an active browser.

Java Web Start[edit]

Java Web Start (or better known as javaws) allows user to start java applications directly from the Internet by using a browser as an intermediary. A specific requirement is for applications to be signed by trusted authorities. In contrast to applets, javaws eliminates some of the security restrictions of the former and thus lets applications perform operations such as file manipulation.

In order to deploy a javaws you need to do the following:

  • create a jar archive using either ant or jar as tools. Be sure to place all your files (java classes, images, text files, etc.) inside it. Also be sure to maintain the relative file paths used in the application for accessing them. Be sure you give proper access rights to any file (image or text placed in the jar) your application will use (chmod +r).
  • sign the jar using a digital certificate. In order to do this you must first generate one by using the keytool command followed by the jarsigner command. Don't forget to remember the password that you have provided as it will be necessary later. Also store in a safe place your certificate file. The following code fragment exemplifies how these commands can be used:
% keytool -genkey -keystore yourKeyStore -alias yourAlias
% jarsigner -keystore yourKeyStore -storepass yoursecret yourJarFile.jar yourAlias
  • create a JNLP (Java Network Launching Protocol) file. It specifies how to launch Java Web Start applications and consists of a set of rules defining how exactly to implement the launching mechanism. The following code fragment shows an example for jnlp file called starchart.jnlp handling a jar named starchart.jar:

IMPORTANT The build from 24 April 2012 does not work. It gives an exception stating it cannot find the GLEventListener class. Please use an older version of the JOGL, e.g., http://jogamp.org/deployment/archive/rc/v2.0-rc5/jogl-all-awt.jnlp. The next code fragment advices you on how to proceed if you get this error:

<?xml version="1.0" encoding="UTF-8"?>
  <!-- Use ip address or domain name and not localhost or 127.0.0.1 in the codebase as you will have problems when trying to access it from another machine-->
  <jnlp spec="1.0+" codebase="http://192.168.1.64:8080/starchart/" href="starchart.jnlp">

  <information>
    <title>Starchart v1.0</title>
    <vendor>Marc Frincu</vendor>
    <homepage href="http://www.info.uvt.ro/~mfrincu/" />
    <description>Simple starchart allowing users to see the night at various moments in time and to zoom in and out for greater or smaller detail</description>
  </information>

  <offline-allowed/>

  <security>
    <!--<j2ee-application-client-permissions/>-->
    <!-- In this case simply allow all. Should be changed however depending on application -->
    <all-permissions/>
  </security>

  <resources>
    <!-- The name of your jar -->
    <jar href="starchart.jar"/>
    <!-- The JRE version to use -->
    <j2se href="http://java.sun.com/products/autodl/j2se" onclick="javascript:mytracker(this.href);" version="1.5+"/>
    <!-- Additional jars. In our case we require the libraries and jars for JOGL -->
    <extension name="jogl-all-awt" href="http://jogamp.org/deployment/jogamp-current/jogl-all-awt.jnlp" />
    <!-- If you get a GLEventListener class not found exception comment the previous line and uncomment the next one. There seems to be a problem with the build from 24 April 2012 (the latest at the time this was written -->
    <!-- <extension name="jogl-all-awt" href="http://jogamp.org/deployment/archive/rc/v2.0-rc5/jogl-all-awt.jnlp" /> -->
    <!-- Other properties -->
    <property name="sun.java2d.noddraw" value="true"/>
  </resources>

  <!-- Specify the main class -->
  <application-desc main-class="PolarProjectionMap"/>
</jnlp>

NOTE: we can notice that the JOGL jars are grabbed at runtime from the site. In this way we need not bother moving them also to the web server

  • Move your jar, jnlp and other dependent jars to the web server. In our case we will use an Apache Tomcat Server but any other server can be used. The files need to be moved to the $CATALINA_HOME/webapps/yourApp/ directory so that both the jar and the jnlp file should be located on the same level. For any additional libraries create a lib/ directory and place them inside. In our example we could move the starchart.jar and starchart.jnlp to $CATALINA_HOME/webapps/starchart/

NOTE: You do not need to restart your web server each time you modify the jar. IMPORTANT: When reading files be sure to use an InputStreamReader as follows, or the application will not work:

	import java.net.URL;
	import java.io.InputStreamReader;
	import java.io.LineNumberReader;


	[...]

	URL location = Thread.currentThread().getContextClassLoader().getResource(filename);
	InputStreamReader isr = new InputStreamReader(location.openStream());

	LineNumberReader input = new LineNumberReader(isr);

	[...]

Links:

API[edit]

Exercises[edit]

  • Implement a simple Starchart by using the API and data files provided at the following link www.info.uvt.ro/~mfrincu/starchart_api.zip. The API provides methods for reading the data files and computing the coordinates of the objects which will be placed in the scene. It also offers methods for retrieving those coordinates
    • Copy the data, images and src directories inside the PPM (Polar Projection Map) folder inside your Java Project directory
      • The data folder contains the following files: beyer.dat for stars, cbounds.dat for constellation boundary lines, cnames.dat for constellation names, conlines.dat for constellation names, messier.dat for the Messier catalogue. Each of these files will be read with the corresponding initializeConstellationLines(filename), initializeConstellationBoundaries(filename), initializeConstellationNames(filename), initializeConstellationStars(filename), initializeMessierObjects(filename) methods found in the provided API
      • There are several getCon*() and one getMessierObjects() methods which return an ArrayList of objects for each type of existing element read from the previous files. Each object has methods for retrieving the coordinates and other optional values such as name
      • The textures inside images need to be read using the TextureHandler class. It is best to put them inside a Hashtable. The images are named m1 through m110 to make the reading and storing operations easier
    • Use display lists when rendering the info regarding constellations, stars and Messier objects
      • For the cardinal points there are several methods called getNorthP(), ... which retrieve an object that can be later queried for its coordinates
      • Use GL_LINES for constellation boundaries and lines, GL_POINTS for stars and glutBitmapString() for star and constellation names
    • Use different colors for constellation lines, boundaries, stars and constellation/star names
    • Use GL_QUAD to display the Messier objects and to apply the image texture on them. The correct image could be retrieved by getting the TextureHandler reference from the Hashtable based on the object name
    • If some objects fall outside the view-volume resize it so that everything fits perfectly
  • Publish the application using JavaWS.

IMPORTANT: remember to modify the initialize* methods by using:

	[...]
	URL location = Thread.currentThread().getContextClassLoader().getResource(filename);
	InputStreamReader isr = new InputStreamReader(location.openStream());
	LineNumberReader input = new LineNumberReader(isr);
	[...]

instead of:

	[...]
	BufferedReader input = new BufferedReader(new FileReader(filename));
	[...]

when reading the files.

IMPORTANT: place the images and data directories inside the bin directory for the application to work with JavaWS