Assign3
Assign3
Goal:
In this assignment, you will be asked to implement two visualization techniques for 2D steady
(time-dependent) vector fields. The first technique is the direct visualization with colors and
arrows, the second one is a texture-based method, line integral convolution. You will be given a
set of vector field data for this assignment. All of them are planar data and defined in a planar region
[0,1]x[0,1].
Task:
1.2 Visualize the vector field magnitude, vector angle (0~2pi), x component, and y component,
respectively using color plots. (20 points)
1.3 Visualize the vector field using arrow plots (30 points)
To create an arrow plot, draw an arrow at each vertex of the mesh.
Use the following routine to draw an arrow head with the given direction if you do not have one. You
should be able to draw the other part of the arrow, right? It is just a line segment pointing from the
vertex location (x, y) to the direction according to the vector value defined at it. Note that you need to
scale the arrows uniformly through the whole field in order to get reasonable visualization.
glPopMatrix();
}
Here, IMG_RES is the resolution of the output image. For instance, if the output image is 512x512, then
IMG_RES = 512;
void gen_noise_tex ()
{
for (int x = 0; x < img_res; x++)
for (int y = 0; y < img_res; y++)
{
noise_tex[x][y][0] =
noise_tex[x][y][1] =
noise_tex[x][y][2] = (unsigned char) 255*(rand() % 32768) / 32768.0;
}
}
float rgb[3];
rgb[0] = (vx - min_vx) / (max_vx - min_vx); // red channel
rgb[1] = (vy - min_vy) / (max_vy - min_vy); // green channel
rgb[2] = 0;
You can create a routine as follows and call it right after you load the data and set up the initialization.
Remember the LIC image need to compute only once and will be saved as a texture for later rendering.
glDrawBuffer(GL_BACK);
int i, j;
// first search the max_vx, min_vx, max_vy, min_vy through the entire field
...
// render the mesh
for (i=0; i<this_poly->ntris; i++) {
Triangle *temp_t=this_poly->tlist[i];
float rgb[3];
rgb[2] = 0.5;
glBegin(GL_TRIANGLES);
for (j=0; j<3; j++)
{
Vertex *v = temp_t->verts[j];
//determine the color for this vertex based on its vector value
...
glVertex2f (v->x, v->y);
}
glEnd();
}
As you have encode the vector field into an image with the same resolution of the output in the
previous step. The streamline tracing and the search of the pixels that it passes can be combined. Here is
the basic idea of how these two can be combined.
Given a current pixel (i, j) with i, j its integer indexes corresponding to its row and column, respectively,
we can extract the vector value from the vec_img as follows:
vx = min_vx + (max_vx - min_vx) * vec_img[i][j][0]/255.0;
vy = min_vy + (max_vy - min_vy) * vec_img[i][j][1]/255.0;
Then the color of the current pixel can be computed as the weighted sum of the color values of those
pixels extracted in the streamline tracing. In this assignment, a simple average of those colors is
sufficient.
void Display()
{
glViewport(0, 0, (GLsizei) 512, (GLsizei) 512);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_FLAT);
glBegin(GL_QUAD_STRIP);
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
glEnd();
glDisable(GL_TEXTURE_2D);
// Add you arrow plot here and use a checkbox to enable its visualization
glutSwapBuffers();
glFlush();
You can also add a checkbox to your interface to toggle on and off this rendering mode.
Grades:
Tasks Total Points
1 50
2 100
3
Here are the results for the five data sets you should expect to see.
bnoise
bruno3
cnoise
dipole
vnoise