This page was last updated: January 5, 2009
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.
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.
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.
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_slider | true means this is a 2-edged range slider |
| type | values are floats |
| array | 2-element float array to store values in |
| id | unique id to be passed into the callback routine |
| callback | callback 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 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 );
. . .
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();
}
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();
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:
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 );
| 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 |