CS 553 -- Winter Quarter 2009

Project #3: Point Clouds, Colors, and Range Sliders

80 Points

Due: January 20



Image from Joe Graphics's Combined projects 2, 3, 4, and 5


This page was last updated: January 5, 2009


The Scenario

You have run a temperature simulation of a 3D room that has 4 heat sources. You are given the temperature data from the simulation at each node in a 3D grid. You will be creating several visualizations (in Projects 2, 3, 4, and 5) to understand the distribution of temperatures within the 3D room.

Requirements:

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

  2. The information on the temperature distribution is the same as in Project #2.

  3. Display the temperature data as a point cloud.

  4. Use four GLUI range sliders to allow the user to cull the data by displaying a subset in X, Y, Z, and Temperature.

  5. Use a fifth GLUI range slider to allow the user to reduce the data by checking its distance from the center of the cube (0.,0.,0.).

  6. Use a sixth range slider to control the display based on the absolute gradient at each point. The gradient at each point is a 3-component vector: (dt/dx,dt/dy,dt/dz). The absolute gradient is: sqrt( SQR(dtdx) + SQR(dtdy) + SQR(dtdz) ).
    This will show where the temperature is changing quickly and where it is changing slowly.

    The x gradient at a point is obtained by taking the difference from the point before to the point after:

    Nodes[i][j][k].dtdx = ( Nodes[i+1][j][k].t - Nodes[i-1][j][k].t ) / ( Nodes[i+1][j][k].x - Nodes[i-1][j][k].x );

    The y and z gradients are similar. Be sure to take into account when i, j, or k are either 0 or at their maximum value.

The radius and the gradient are known as derived data. That is, they are not part of the dataset as it was given, but have been computed from that dataset.

Setting up the Data in your Program

If you are comfortable with structures, a 3D array of structures is a good way to store and access the data for this project:

struct node
{
        float x, y, z;          // location
        float t;                // temperature
	float rgb[3];		// the assigned color
        float rad;              // radius
        float grad;             // total gradient
};

struct node  Nodes[NX][NY][NZ];

If you are not comfortable with C structures, a 3D array for X, a 3D array for Y, etc. will work too.

InitGraphics() is a good place to set all these values. Fill the (x,y,z) components of each structure in the 3D array, use those (x,y,z) to compute a temperature, use the temperature to compute a color, and also use those (x,y,z) to compute the radius and the gradient.

Using the GLUI Range Sliders

We have added range sliders to the GLUI library. Here is how to use them.

For each variable, define a text-display format, a 2-element array to hold the low and high end of the range, a pointer to the created slider, and a pointer to the created text-display:


// in the global variables:
#define TEMP	0
const float 		TEMPMIN = {   0. };
const float 		TEMPMAX = { 100. };
const char *		TEMPFORMAT = { "Temperature: %5.2f - %5.2f" };
float			TempLowHigh[2];
GLUI_HSlider *		TempSlider;
GLUI_StaticText *	TempLabel;
. . .



// in the function prototypes:
void	Buttons( int );
void	Sliders( int );
. . .


// in InitGlui():
	char str[128];
	. . .
	TempSlider = Glui->add_slider( true, GLUI_HSLIDER_FLOAT, TempLowHigh,
		TEMP, (GLUI_Update_CB) Sliders );
	TempSlider->set_float_limits( TEMPMIN, TEMPMAX );
	TempSlider->set_w( 200 );		// good slider width
	sprintf( str, TEMPFORMAT, TempLowHigh[0], TempLowHigh[1] );
	TempLabel = Glui->add_statictext( str );
	. . .

The arguments to Glui->add_slider() are, in order:
range_slidertrue means this is a 2-edged range slider
typevalues are floats
array2-element float array to store values in
idunique id to be passed into the callback routine
callbackcallback routine

The arguments to TempSlider->set_float_limits() are the minimum and maximum values on that slider.

The argument to TempSlider->set_w() is the width, in pixels, of that slider in the GLUI window.

The argument to Glui->add_statictext() is the string to display.

The Button Callback Routine

The buttons callback routine needs to be modified do re-do all the text strings if the Reset button is selected:


void
Buttons( int id )
{
        char str[256];

        switch( id )
        {
                case RESET:
                        Reset();
                        sprintf( str, TEMPFORMAT, TempLowHigh[0], TempLowHigh[1] );
                        TempLabel->set_text( str );
			. . .

The Slider Callback Routine

All range sliders can use the same callback routine:

void
Sliders( int id )
{
        char str[32];

        switch( id )
        {
                case TEMP:
                        sprintf( str, TEMPFORMAT, TempLowHigh[0], TempLowHigh[1] );
                        TempLabel->set_text( str );
                        break;

		. . .
	}

        glutSetWindow( GraphicsWindow );
        glutPostRedisplay();
}

In Subroutine Display():

Note that you can't use display lists as easily as you did in Project #2. (Why?) Therefore, it is easiest if you redraw all the points in Display(). However, you can at least save some compute time by pre-computing each point's (x,y,z) location, its color, its radius, and its gradient.

glPointSize( ?? );
glBegin( GL_POINTS );
for( int i = 0; i < NX; i++ )
{
  for( int j = 0; j < NY; j++ )
  {
    for( int k = 0; k < NZ; k++ )
    {
	if( Nodes[i][j][k].x < XLowHigh[0]  ||  Nodes[i][j][k].x > XLowHigh[1] )
		continue;

	?????

	// check the radius too:

	?????

	// check the gradient too:

	?????

	glColor3f( ??? );
	glVertex3f( ??? );
    }
  }
}
glEnd();

Suggestions:

Feel free to use whatever color scale you find most insightful. One way of doing the color variation is to march from blue through green to red around the top of the HSV color cone. Feel free to use the HsvRgb() routine. One way to map scalar values to this range is by setting saturation to 1.0, setting value to 1.0, and setting hue to:

or,

so that the whole calling sequence could look like:

float hsv[3], rgb[3];
. . .
hsv[0] = 240. - . . .
hsv[1] = 1.;
hsv[2] = 1.;
HsvRgb( hsv, rgb );
glColor3f( rgb[0], rgb[1], rgb[2] );
or, more conveniently,
glColor3fv( rgb );

Grading:

Item Points
Correct colored points display 20
X, Y, and Z range sliders works 20
Temperature range slider works 20
Radius range slider works 10
Gradient range slider works 10
Potential Total 80