Please find below a number of hints, tips, and tricks to fix issues that you might
encounter when working on the assignments.
-
In the last couple of years, some 2IV60 students experienced problems with the OpenGL assignment. Most of these were caused by graphics cards/drivers, which showed strange behavior for some of the OpenGL functions. To avoid such problems in the future, we have made a list of forbidden OpenGL functions and flags, see below. The framework automatically checks for these and gives a notification if used.
Forbidden functions for 2IV60:
- GL_MAP1_VERTEX_, GL_MAP1_INDEX, GL_MAP1_COLOR_4, GL_MAP1_NORMAL, GL_MAP1_TEXTURE_COORD_,
- glEvalCoord1f, glEvalCoord2f, glEvalCoord1d, glEvalCoord2f,
- glMap1f, glMap2f, glMap1d, glMap2d,
- GL_MAP2_VERTEX_, GL_MAP2_INDEX, GL_MAP2_COLOR_4, GL_MAP2_NORMAL, GL_MAP2_TEXTURE_COORD_,
- GL_AUTO_NORMAL,
- GLUquadric,
- GL_TEXTURE_GEN_S, GL_TEXTURE_GEN_T,
- glCallList, glGenLists, glNewList, glEndList, glDeleteLists,
- GL_POLYGON_SMOOTH,GL_LINE_SMOOTH, GL_POINT_SMOOTH,
- glLightModelfv
Note that these functions are not necessary to complete the assignment. They are either for optimizations (which is not the goal of the course), or they can be replaced by a piece of your own code to define the shape, normals, and texture coordinates of the objects (which you will have to do anyway in the second part of the assignment).
-
Write shorter formulas in java by importing static variables and methods of
Math
class.
So, instead of writing
double h = Math.cos(Math.PI/3) * sin(2*Math.PI/3);
you can write:
import static java.lang.Math.*;
...
double h = cos(PI/3) * sin(2*PI/3);
-
Use the supplied
Vector
class for vector computations, for instance:
Vector u = new Vector(1,2,4);
Vector v = new Vector(5,7,-10);
double dot = u.dot(v);
Vector sum = u.add(v);
-
The Vector class has immutable objects; that is, after creation a Vector's coordinates
can not be changed. As a result, the following piece of code does not
change the coordinates of vector
a
,
Vector a = new Vector(1,1,1);
Vector b = new Vector(1,2,3);
System.out.println("a="+a);
a.subtract(b); // vector a is NOT changed
System.out.println("a="+a);
but this code does:
a = a.subtract(b); // vector a now refers to a different Vector object
-
When two integer values are divided, integer division is used, and the result
might not be what you expect. For instance after
int width = 500; int height = 300; double ratio;
ratio = height / width;
ratio has a value of 0. This can be fixed by using a type cast to float or double,
to make sure that ratio gets a value of 0.6:
int width = 500; int height = 300; double ratio;
ratio = (double) height / (double) width;
-
For a generic FAQ on OpenGL, see
https://www.opengl.org/archives/resources/faq/technical
-
To find out more about how to use OpenGL lighting, color, and
materials, check out the webpage
http://sjbaker.org/steve/omniv/opengl_lighting.html .
-
If colors are specified with glcolor3f(r, g, b), the floating point
parameters r, g, and b are expected to be in the range of 0 to 1.
When glcolor3ub(r, g, b) is used, the integer parameters r, g, and b are expected
to be in the range of 0 to 255. For instance:
int r = 255; int g = 128; int b = 128; // pink, specified in integers
gl.glcolor3ub(r, g, b); // set color using unsigned bytes, or
gl.glcolor3f(r/255.0f, g/255.0f, b/255.0f); // set color using floats
-
If you see white triangles rendered that you did not explicitly draw you may
want to
disable polygon smoothing. This artifact is probably due to a driver issue and
does not a apply to everyone.
In RobotRace.java, in the public void initialize() function disable the followin
g two lines:
gl.glEnable(GL_POLYGON_SMOOTH);
gl.glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
- Carefully study the assignment(s) before you start implementing. Make sure that you fully understand what is asked and check the suggestions and hints given.
- When using an OpenGL routine you are not familiar with, carefully study the description and the meaning of the parameters, and make sure you understand these before you use the routine.
-
For Windows 7 and up: Do not place your Netbeans project in a folder that is
non-writable for executables, such as Desktop or Program Files. Netbeans will
compile you program and
report everything is correct, however, no jar file will be created.
-
If you experience serious rendering issues (very low frame rate) upon drawing
just
a few items, try updating (or installing) the driver of your video card to the
newest version. Drivers are usually
available on the manufacturers website, for example,
NVIDIA
drivers.
-
In most cases, functions and methods expect that radians are used for angles, however,
OpenGL expects degrees. If in doubt, check the specification of the function used.
-
Assign proper values to the near and far parameters for the clipping planes when specifying a perspective projection. Far should be greater than near, and near should always be greater than zero. Simply give them such values that everything you want to be in view is visible. What is the size of your scene? Do you really want to see things that are at 1cm before your camera?
-
OpenGL will take care of normalization of the normals if you use
gl.glEnable(GL_NORMALIZE);
Especially if you use gl.glScale() to resize your objects, this is highly
recommended.
-
Some of the standard OpenGL calls differ slightly for JOGL, a Java OpenGL
binding.
Especially for OpenGL calls that have array parameters, you might find
small variations like the following:
//Standard OpenGL, C
float[] light_position; ...
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
is replaced in Jogl by either
//Jogl
float[] lightposition = { 0f, 10f, 1f, 0f};
gl.glLightfv(GL_LIGHT0, GL_POSITION, light_position, 0);
or
//Jogl
float[] lightposition = { 0f, 10f, 1f, 0f};
gl.glLightfv(GL_LIGHT0, GL_POSITION, FloatBuffer.wrap(light_position));
-
1D texturing turns out to give problems. You can use the code below
to properly initialize 1D-textures:
/**
* Creates a new 1D - texture.
* @param gl
* @param colors
* @return the texture ID for the generated texture.
*/
public int create1DTexture(GL2 gl, Color[] colors){
gl.glDisable(GL_TEXTURE_2D);
gl.glEnable(GL_TEXTURE_1D);
int[] texid = new int[]{-1};
gl.glGenTextures(1, texid, 0);
ByteBuffer bb = ByteBuffer.allocateDirect(colors.length * 4).order(ByteOrder.nativeOrder());
for (Color color : colors) {
int pixel = color.getRGB();
bb.put((byte) ((pixel >> 16) & 0xFF)); // Red component
bb.put((byte) ((pixel >> 8) & 0xFF)); // Green component
bb.put((byte) (pixel & 0xFF)); // Blue component
bb.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component
}
bb.flip();
gl.glBindTexture(GL_TEXTURE_1D, texid[0]);
gl.glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, colors.length, 0, GL_RGBA, GL_UNSIGNED_BYTE, bb);
gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl.glBindTexture(GL_TEXTURE_1D, 0);
return texid[0];
}