CS 553 -- Winter Quarter 2009

Project #9: Terrain Mapping Project

120 Points

Due: February 25


This page was last updated: February 9, 2009


Scenario:

A severe economic weather cloud is threatening Oregon. Your mission is to visualize it so you can try to figure out where it came from, where it is going, and who should be most concerned about it.

You will be given a height field and an image, representing the terrain and satellite image of the state of Oregon (in low resolution to keep it simple). The graphical representation of the transparent cloud, and its motion, is up to you. Write a program to view this scenario.

Requirements:

  1. Put this project number and your name in the title bar.

  2. Get the height field from a file called or.hgt. It has 105 rows, with 201 points per row. Ignore the exact formatting -- just read them freeform. (See below.)

  3. Get the texture map from a file called or.bmp. Use the BmpToTexture routine to read it. (See below.)

  4. Draw the triangles of the terrain in shades of white. Compute s and t texture coordinates at each vertex. Do OpenGL lighting or pseudo-lighting for each triangle. (See below)

  5. Using texture mapping, display the texture on top of the terrain.

  6. Using the GLUI interface, allow the user to switch between (1) no texturing, (2) GL_REPLACE texturing, and (3) GL_MODULATE texturing.

  7. Using the GLUI interface, allow the user to select between (1) GL_NEAREST or (2) GL_LINEAR as the minification and magnification filters.

  8. The cloud can be drawn any way you want, but it must use OpenGL blending to make it look transparent.

  9. The cloud can move any periodic way you want it to move. Make the period 10 seconds.

  10. Hitting the 'p' key should pause or resume the animation.

  11. Using the GLUI interface, allow the user to exaggerate the height of the terrain. I.e., scale it in the vertical direction, starting at 1.0 and going to whatever maximum value you think is good.

  12. Using the GLUI interface, allow the user to turn the cloud off and on.

  13. Using the GLUI interface, allow the user to toggle between orthographic and perspective projections.

Reading the Texture:

The texture image is in ".bmp" format. Read the texture image file into your program by:


unsigned char *BmpToTexture( char *filename, int *widthp, int *heightp );

unsigned char *Texture;
int Width, Height;

Texture = BmpToTexture( "or.bmp", &Width, &Height );

Test to be sure Texture is not equal to NULL, and that Width and Height each come back as 256. Then,


glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

glTexImage2D( GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, Texture );

Click here to get a copy of BmpToTexture(). You can either treat this as a separate file, or easier, just copy it into your proj09.cpp program.

Computing s and t Coordinates from Longitude and Latitude

The dimensions of the data are:

// Longitude is west-to-east (x)
// Latitude is south-to-north (-z)

#define NUMLNGS		201
#define NUMLATS		105

The ranges of the data are (all units are kilometers):

const float LNGMIN = { -289.6f   };
const float LNGMAX = {  289.6f   };
const float LATMIN = { -197.5f   };
const float LATMAX = {  211.2f   };
const float HGTMIN = {    0.0f   };
const float HGTMAX = {    2.891f };

The texture image consists of 256x256 texels, but only the bottom 256x184 (0-255, 0-183) actually have the Oregon image. The upper 256x72 are there to pad it out to a power of 2. So, to compute s and t from a longitude and latitude:

	s = ( lng - LNGMIN ) / ( LNGMAX - LNGMIN );	/* 0. -> 1.    */
	t = ( lat - LATMIN ) / ( LATMAX - LATMIN );	/* 0. -> 1.    */
	t = t * ( 183. / 255. );			/* 0. -> 0.718 */

Reading the Terrain:

	struct LngLatHgt
	{
		float lng, lat, hgt;
	};

	struct LngLatHgt Points[NUMLATS][NUMLNGS];
	float lng, lat, hgt;
	float dlat, dlng;
	int x, z;

	dlng = ???
	dlat = ???

	for( z = 0, lat = LATMAX; z < NUMLATS; z++, lat -= dlat )
	{
		for( x = 0, lng = LNGMIN; x < NUMLNGS; x++, lng += dlng )
		{
			Points[z][x].lng = lng;
			Points[z][x].lat = lat;
			fscanf( fp, "%f", &Points[z][x].hgt );
		}
	}

Drawing the Terrain:

You can draw the terrain with GL_TRIANGLES or GL_TRIANGLE_STRIPs. (Anything with quadrilaterals is not recommended because of non-planarity.) However you do it, just be sure to:

  1. Use GL_FLAT shading
  2. Be sure each triangle is drawn in some shade of white/gray/black depending on the pseudo-lighting calculation (see below).
  3. Be sure each vertex has s and t texture coordinates attached to it.

Note that:

Computing Pseudo-Lighting for a Triangle:

OpenGL has a real lighting feature where the pipeline hardware will compute a lighting intensity at each vertex for you. You can use it if you want (it's fun to put the light source on the cloud, so it appears to be a moving glow), or you can simulate it.

If we assume that the light is coming from straight overhead, then any triangle that has a perfectly vertical (+Z) surface normal will be brighter than any triangle that doesn't. So, to do lighting this way, take the cross product of two edge vectors and use the Z component of the unitized normal vector as the intensity:

	x01 = x1 - x0;
	y01 = y1 - y0;
	z01 = HGTFACTOR*( z1 - z0 );

	x02 = x2 - x0;
	y02 = y2 - y0;
	z02 = HGTFACTOR*( z2 - z0 );

	Cross( x01, y01, z01,  x02, y02, z02,  &nx, &ny, &nz );

	inten = fabs(nz) / sqrt( nx*nx  +  ny*ny  +  nz*nz );
	glColor3f( inten, inten, inten );

The HGTFACTOR is there to make the difference in intensities more obvious. You can hardcode this value, or make it a slider or spinner so you can adjust it.

Don't remember how to do a cross product? Look at the "Determinant Formula" here.

+5 Points Extra Credit

Open up another graphics window and graph:

  1. The X coordinate of the center of the cloud versus Time
  2. The Y coordinate of the center of the cloud versus Time
Have a dot moving on the 2 graphs to show the coordinates of the cloud right now.
You do not need to put any sort of labels or tic marks on the axes.

+5 Points Extra Credit

Open up another graphics window and display a 3D view of the scene while riding on the cloud. Pick a reasonable eye position and lookat position. Try not to make the grader motion sick!

Grading:

Item Points
Display the terrain correctly 20
Correct lighting 10
Correct GL_REPLACE 20
Correct GL_MODULATE 20
Toggle Nearest/Linear filtering correctly10
Draw the cloud15
Make the cloud transparent10
Animate the cloud15
Graph Extra Credit5
Cloud-riding Extra Credit5
Potential Total 130