Commit 1b4d9e25 authored by Sander Mathijs van Veen's avatar Sander Mathijs van Veen

Merge branch 'master' of ssh://vo20.nl/git/uva

parents aa4fd943 ec5c92d4
......@@ -217,8 +217,9 @@ intersect_node(bvh_node *node, intersection_point *ip,
}
else
{
// Leaf node, find shortest triangle and check if it is closer than the
// current closest intersection
// Leaf node, find the shortest triangle in the leaf and check if it is
// closer to the origin than the current closest intersection. If so,
// make it the new closest intersection.
triangle *triangles = leaf_node_triangles(node);
intersection_point ip2;
......@@ -253,13 +254,6 @@ find_first_intersected_bvh_triangle(intersection_point* ip,
ip->t = C_INFINITY;
// If the root has no intersection, none of the BVH nodes does
//
// Note that this step if mkes the program less efficient when the root's
// bounding box has a relatively large surface in the camera screen (has
// lot of ray intersections). This is because every ray intersecting a
// triangle is now tested one time more and every non-intersection ray is
// tested one time less. So, when raytracing large objects, omitting this
// step would be advisable.
if( !bbox_intersect(&t0, &t1, bvh_root->bbox, ray_origin,
ray_direction, 0.0, C_INFINITY) )
{
......
/* Computer Graphics, Assignment, Ray-tracing 2
*
* Student name ....
* Student email ...
* Collegekaart ....
* Date ............
* Comments ........
*
*
* (always fill in these fields before submitting!!)
* Student name .... Sander van Veen & Taddeus Kroes
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Collegekaart .... 6167969 & 6054129
* Date ............ 07.11.2010
*/
#include <sys/time.h>
......@@ -160,7 +156,7 @@ ray_trace(void)
vec3 forward_vector, right_vector, up_vector;
int i, j, k, l;
vec3 right_step, down_step;
float image_plane_width, image_plane_height, diff[2] = {0.25, 0.75};
float image_plane_width, image_plane_height, pixel_diff[2] = {0.25, 0.75};
vec3 image_plane_topleft, image_plane_point;
vec3 ray_direction;
vec3 color;
......@@ -203,26 +199,34 @@ ray_trace(void)
{
for (i = 0; i < framebuffer_width; i++)
{
if( do_antialiasing)
if( do_antialiasing )
{
color.x = color.y = color.z = 0;
// Anti-aliasing is on, shoot 4 rays through each point and use the average
color.x = color.y = color.z = 0.0;
for( k = 0; k < 2; k++ )
{
for( l = 0; l < 2; l++ )
{
// Compute corresponding point on image plane
image_plane_point = v3_add(image_plane_topleft, v3_multiply(right_step, i+diff[k]));
image_plane_point = v3_add(image_plane_point, v3_multiply(down_step, j+diff[l]));
// Compute corresponding point corner on image plane
image_plane_point = v3_add(
image_plane_topleft,
v3_multiply(right_step, i+pixel_diff[k])
);
image_plane_point = v3_add(
image_plane_point,
v3_multiply(down_step, j+pixel_diff[l])
);
// Compute direction for shooting the ray
ray_direction = v3_subtract(image_plane_point, scene_camera_position);
// Determine ray color
// Add ray color for this corner to the current color
color = v3_add(color, ray_color(0, scene_camera_position, ray_direction));
}
}
// Divide by 4 to get the average of all corners, this is the point color
color = v3_multiply(color, 0.25);
}
else
......
CC=gcc
WARNING_FLAGS=-Wall -Wextra -Werror-implicit-function-declaration -Wshadow -Wstrict-prototypes -pedantic-errors
CFLAGS=-g -O2 -std=c99 $(WARNING_FLAGS)
LDFLAGS=-g -lGL -lglut -lGLU
.c.o:
$(CC) -c $(CFLAGS) $<
all: main
main: main.o volume.o
$(CC) $(LDFLAGS) -o main main.o volume.o
clean:
rm -f *.o
rm -f main
volume.o : volume.h
main.o : volume.h main.c
volume.o : volume.h volume.c
We did the following measurements with out program.
+----------------+-----+-----------------------+---------------------+-------------+
| dataset | iso | framerate unoptimized | framerate optimized | improvement |
| | | (points/cubes) | (points/cubes) | ratio |
+----------------+-----+-----------------------+---------------------+-------------+
| frog.small.vtk | 78 | 80 / 19 | 670 / 235 | 8.4 / 12.4 |
+----------------+-----+-----------------------+---------------------+-------------+
| knee.vtk | 60 | 58 / 2 | 362 / 29 | 6.2 / 14.5 |
+----------------+-----+-----------------------+---------------------+-------------+
| mummy.128.vtk | 50 | 40 / 5 | 515 / 86 | 12.9 / 17.2 |
+----------------+-----+-----------------------+---------------------+-------------+
We can see that the improvement in performance is very large, especially for
the cubes. This makes sense, because when not using arrays, all of the cubes
have to be translated and transformed whereas the points only have to be
calculated. Still, the optimization certainly also pays off for the points.
/* Computer Graphics, Assignment, Volume rendering with cubes/points
*
* Filename ........ main.c
* Description ..... Creates OpenGL window and draws the scene.
* Date ............ 29.10.2008
* Created by ...... Paul Melis
*
* Student name .... Sander van Veen & Taddeus Kroes
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Collegekaart .... 6167969 & 6054129
* Date ............ 07.11.2010
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include "volume.h"
#include "v3math.h"
int display_mode=0; /* 0 = points, 1 = cubes */
int use_arrays=0;
unsigned char isovalue=128;
unsigned char epsilon=0;
int window;
int mouse_mode=0;
int mx, my;
float camDistance=100.0;
float camRotZ=45.0, camAzimuth=20.0;
float saved_camRotZ, saved_camAzimuth, saved_camDistance;
int regenerate_arrays=1;
int entered_number=0;
int display_fps_counter=0;
int backface_culling=0;
#define MAX_VERTICES_IN_ARRAY 5000000
int num_vertices_in_array=0;
float vertices[3*MAX_VERTICES_IN_ARRAY];
float normals[3*MAX_VERTICES_IN_ARRAY];
void SetupCamera(void);
void DrawVolumeAxes(void);
void DrawVolumeUsingCurrentDisplayMode(void);
/* Some definitions and global variables for use in the filled-in functions */
#define TIMER_FRAMERATE 30
#define POINT_SIZE 1.0
int timer = TIMER_FRAMERATE + 1;
struct timeval start, end;
float x_center = 0.0, y_center = 0.0, z_center = 0.0;
float normal_x_size = 0.0, normal_y_size = 0.0;
/* Draw the selected iso-value (range) using GL_POINTS */
void DrawVolumeAsPoints(void)
{
int x, y, z;
char value;
/* Initialize global help variables */
if( x_center == 0.0 || y_center == 0.0 || z_center == 0.0 )
{
x_center = .5 * sizex;
y_center = .5 * sizey;
z_center = .5 * sizez;
}
/* Go through all voxels and compare them to the volume dataset. If the
* the value is in the specified range, draw a point at that location. */
glBegin(GL_POINTS);
for( x = 0; x < nx; x++ )
for( y = 0; y < ny; y++ )
for( z = 0; z < nz; z++ )
if( (value = volume[voxel2idx(x, y, z)]) >= isovalue - epsilon
&& value <= isovalue + epsilon )
glVertex3f(x + x_center, y + y_center, z + z_center);
glEnd();
}
/* Draw the selected iso-value (range) using glutSolidCube()'s */
void DrawVolumeAsCubes(void)
{
int x, y, z;
char value;
/* Initialize global help variables */
if( x_center == 0.0 || y_center == 0.0 || z_center == 0.0 )
{
x_center = .5 * sizex;
y_center = .5 * sizey;
z_center = .5 * sizez;
}
/* Go through all voxels and compare them to the volume dataset. If the
* the value is in the specified range, draw a cube at that location. */
for( x = 0; x < nx; x++ )
{
for( y = 0; y < ny; y++ )
{
for( z = 0; z < nz; z++ )
{
if( (value = volume[voxel2idx(x, y, z)]) >= isovalue - epsilon
&& value <= isovalue + epsilon )
{
glPushMatrix();
glTranslatef(x + x_center, y + y_center, z + z_center);
glScalef(sizex, sizey, sizez);
glutSolidCube(1.0);
glPopMatrix();
}
}
}
}
}
/* Fill the vertex array based on the current iso-value range,
so the array can be drawn as GL_POINTS, with one point per voxel
to be shown.
Be sure to set num_vertices_in_array.
*/
/* Add an (x,y,z)-value to the vertices array */
void
addVertex(int *index, float x, float y, float z)
{
vertices[(*index)++] = x;
vertices[(*index)++] = y;
vertices[(*index)++] = z;
num_vertices_in_array++;
}
/* Add an (x,y,z)-value to the normals array */
void
addNormal(int index, float x, float y, float z)
{
normals[index++] = x;
normals[index++] = y;
normals[index] = z;
}
/* Draw the corners of a quad in the X-dimension (all points have the
* same x-coordinate). Add the corner normals to the normals array. */
void
addQuadX(int *index, float x, float y, float z,
float w, float h, float normal_x)
{
addNormal(*index, normal_x, 0, 0);
addVertex(index, x, y, z);
addNormal(*index, normal_x, 0, 0);
addVertex(index, x, y + w, z);
addNormal(*index, normal_x, 0, 0);
addVertex(index, x, y + w, z + h);
addNormal(*index, normal_x, 0, 0);
addVertex(index, x, y, z + h);
}
/* Draw the corners of a quad in the Y-dimension (all points have the
* same y-coordinate). Add the corner normals to the normals array. */
void
addQuadY(int *index, float x, float y, float z,
float w, float h, float normal_y)
{
addNormal(*index, 0, normal_y, 0);
addVertex(index, x, y, z);
addNormal(*index, 0, normal_y, 0);
addVertex(index, x + w, y, z);
addNormal(*index, 0, normal_y, 0);
addVertex(index, x + w, y, z + h);
addNormal(*index, 0, normal_y, 0);
addVertex(index, x, y, z + h);
}
/* Draw the corners of a quad in the Z-dimension (all points have the
* same z-coordinate). Add the corner normals to the normals array. */
void
addQuadZ(int *index, float x, float y, float z,
float w, float h, float normal_z)
{
addNormal(*index, 0, 0, normal_z);
addVertex(index, x, y, z);
addNormal(*index, 0, 0, normal_z);
addVertex(index, x, y + h, z);
addNormal(*index, 0, 0, normal_z);
addVertex(index, x + w, y + h, z);
addNormal(*index, 0, 0, normal_z);
addVertex(index, x + w, y, z);
}
void FillArrayWithPoints(void)
{
int x, y, z, index;
char value;
/* Initialize global help variables */
if( x_center == 0.0 || y_center == 0.0 || z_center == 0.0 )
{
x_center = .5 * sizex;
y_center = .5 * sizey;
z_center = .5 * sizez;
}
/* Clear array counters */
num_vertices_in_array = index = 0;
/* Go through all voxels and compare them to the volume dataset. If the
* the value is in the specified range, add a point at that location. */
for( x = 0; x < nx; x++ )
{
for( y = 0; y < ny; y++ )
{
for( z = 0; z < nz; z++ )
{
if( (value = volume[voxel2idx(x, y, z)]) >= isovalue - epsilon
&& value <= isovalue + epsilon )
{
addVertex(&index, x + x_center, y + y_center, z + z_center);
/* Check if the next point will fit in the vertices array */
if( num_vertices_in_array == MAX_VERTICES_IN_ARRAY )
{
puts("vertex array full, stopped filling");
return;
}
}
}
}
}
}
/* Fill the vertex and normal arrays based on the current iso-value range,
so the arrays can be drawn as GL_QUADS, with one cube per voxel
to be shown (and six quads per cube).
Be sure to set num_vertices_in_array.
*/
void FillArrayWithCubes(void)
{
int x, y, z, index;
char value;
/* Initialize global help variables */
if( normal_x_size == 0.0 || normal_y_size == 0.0 )
{
// Set normal sizes relative to the
normal_x_size = sizez / sizex;
normal_y_size = sizez / sizey;
}
/* Clear array counters */
num_vertices_in_array = index = 0;
/* Go through all voxels and compare them to the volume dataset. If the
* the value is in the specified range, add a cube at that location. */
for( x = 0; x < nx; x++ )
{
for( y = 0; y < ny; y++ )
{
for( z = 0; z < nz; z++ )
{
if( (value = volume[voxel2idx(x, y, z)]) >= isovalue - epsilon
&& value <= isovalue + epsilon )
{
/* Check if the cube will fit in the vertices array */
if( num_vertices_in_array + 24 > MAX_VERTICES_IN_ARRAY )
{
puts("vertex array full, stopped filling");
return;
}
/* Back planes of the cube */
addQuadX(&index, x, y, z, sizey, sizez, -normal_x_size);
addQuadY(&index, x, y, z, sizex, sizez, -normal_y_size);
addQuadZ(&index, x, y, z, sizex, sizey, -1.0);
/* Front planes of the cube */
addQuadX(&index, x + sizex, y, z, sizey, sizez, normal_x_size);
addQuadY(&index, x, y + sizey, z, sizex, sizez, normal_y_size);
addQuadZ(&index, x, y, z + sizez, sizex, sizey, 1.0);
}
}
}
}
}
/* Restart the framerate timer (also used at keypress-events) */
void
reset_timer(void)
{
gettimeofday(&start, NULL);
timer = TIMER_FRAMERATE + 1;
}
void DrawScene(void)
{
/* clear the draw buffer */
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
/* set the model-view matrix */
SetupCamera();
/* draw an outline of where the volume resides */
DrawVolumeAxes();
/* draw the volume in the chosen mode */
DrawVolumeUsingCurrentDisplayMode();
glFinish();
/* Stop framerate timer */
if( display_fps_counter )
{
if( timer == TIMER_FRAMERATE )
{
gettimeofday(&end, NULL);
/* Print FPS (rounded to complete frames) */
printf("Framerate: %d \n", (int)(TIMER_FRAMERATE / (
end.tv_sec - start.tv_sec + (end.tv_usec - start.tv_usec) * 1e-6
) + .5));
fflush(stdout);
}
timer = (timer + 1) % (TIMER_FRAMERATE + 1);
}
/* Start framerate timer */
if( display_fps_counter && !timer )
gettimeofday(&start, NULL);
/* finally, swap the draw buffers to make the frame appear on screen */
glutSwapBuffers();
}
/* Draw a set of colored X, Y and Z axes that match the size (and location)
of the volume, so we can see where output should appear */
void
DrawVolumeAxes(void)
{
glPushAttrib(GL_LIGHTING_BIT);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3f(0, 0, 0);
glVertex3f(nx*sizex, 0, 0);
glColor3f(0, 1, 0);
glVertex3f(0, 0, 0);
glVertex3f(0, ny*sizey, 0);
glColor3f(0, 0, 1);
glVertex3f(0, 0, 0);
glVertex3f(0, 0, nz*sizez);
glEnd();
glPopAttrib();
}
void DrawVolumeUsingCurrentDisplayMode(void)
{
if (use_arrays)
{
if (regenerate_arrays == 1)
{
printf("Filling vertex/normal arrays... ");
fflush(stdout);
switch (display_mode)
{
case 0:
FillArrayWithPoints();
break;
case 1:
FillArrayWithCubes();
break;
}
printf("done, %d array vertices used (1 per point, 4 per quad)\n", num_vertices_in_array);
regenerate_arrays = 0;
}
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
if (display_mode > 0)
{
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
}
}
glColor3f(0.6, 0.0, 0.0);
if (display_mode == 0)
glDisable(GL_LIGHTING);
else
glEnable(GL_LIGHTING);
if (display_mode == 0)
{
/* points */
glPointSize(POINT_SIZE);
if (use_arrays)
glDrawArrays(GL_POINTS, 0, num_vertices_in_array);
else
if (display_mode == 0)
DrawVolumeAsPoints();
}
else if (display_mode == 1)
{
/* cubes */
if (use_arrays)
glDrawArrays(GL_QUADS, 0, num_vertices_in_array);
else
{
glEnable(GL_RESCALE_NORMAL);
DrawVolumeAsCubes();
glDisable(GL_RESCALE_NORMAL);
}
}
if (use_arrays)
{
glDisableClientState(GL_VERTEX_ARRAY);
if (display_mode > 0)
glDisableClientState(GL_NORMAL_ARRAY);
}
}
void SetupCamera(void)
{
GLfloat light_position[4];
glLoadIdentity();
// Verbose, but straightforward way, of positioning the camera and lightsource.
// Assume the camera's final position is (cx, cy, cz).
// Start with c being (camDistance, 0, 0)
// First rotate around Y, then around Z.
// Now we have c at the given distance from the origin, with specified rotation angles.
float cx, cy, cz;
float t;
float beta, gamma;
// degrees -> radians
beta = camAzimuth / 180.0 * 3.1415926535;
gamma = camRotZ / 180.0 * 3.1415926535;
cx = camDistance;
cy = cz = 0.0;
// Rotate around Y
t = cx;
cx = cx * cos(beta) - cz * sin(beta);
cz = t * sin(beta) + cz * cos(beta);
// Rotate around Z
t = cx;
cx = cx * cos(gamma) + cy * sin(gamma);
cy = -t * sin(gamma) + cy * cos(gamma);
gluLookAt (cx, cy, cz, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
// Finally, translate because the lookat point is at the center of the volume.
glTranslatef(-0.5*nx*sizex, -0.5*ny*sizey, -0.5*nz*sizez);
// Place the light source at the camera position (head light)
light_position[0] = cx + 0.5*nx*sizex;
light_position[1] = cy + 0.5*ny*sizey;
light_position[2] = cz + 0.5*nz*sizez;
light_position[3] = 1.0;
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
}
void InitOpenGL(void)
{
GLfloat light_ambient[] = { 0.4, 0.4, 0.4, 0.0 };
GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat mat_no_specular[] = { 0.0, 0.0, 0.0, 1.0 };
glClearColor(0.7, 0.7, 1, 1);
glEnable(GL_COLOR_MATERIAL);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_no_specular);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glShadeModel(GL_FLAT);
//glShadeModel(GL_SMOOTH);
}
void ReSizeScene(int Width, int Height)
{
if (Height==0)
Height=1;
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height, 0.1f, 10000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
}
void keyPressed(unsigned char key, int x, int y)
{
int redraw=0;
/* keep gcc happy, as we don't use these parameters */
(void)x;
(void)y;
switch (key)
{
case 'q':
exit(-1);
break;
case 'b':
backface_culling = 1 - backface_culling;
if (backface_culling)
{
glEnable(GL_CULL_FACE);
printf("Backface culling is now enabled\n");
}
else
{
glDisable(GL_CULL_FACE);
printf("Backface culling is now disabled\n");
}
glutPostRedisplay();
break;
case 'p':
/* switch to points mode */
display_mode = 0;
redraw = 1;
break;
case 'c':
/* switch to cubes mode */
display_mode = 1;
redraw = 1;
break;
case '[':
/* decrease isovalue */
{
int newvalue = isovalue-10;
if (newvalue < 0)
isovalue = 0;
else
isovalue = newvalue;
}
printf("Setting isovalue to %d\n", isovalue);
redraw = 1;
break;
case ']':
/* increase isovalue */
{
int newvalue = isovalue+10;
if (newvalue > 255)
isovalue = 255;
else
isovalue = newvalue;
}
printf("Setting isovalue to %d\n", isovalue);
redraw = 1;
break;
/* handle isovalue/epsilon entered by number */
case '0':
entered_number = entered_number*10;
break;
case '1':
entered_number = entered_number*10 + 1;
break;
case '2':
entered_number = entered_number*10 + 2;
break;
case '3':
entered_number = entered_number*10 + 3;
break;
case '4':
entered_number = entered_number*10 + 4;
break;
case '5':
entered_number = entered_number*10 + 5;
break;
case '6':
entered_number = entered_number*10 + 6;
break;
case '7':
entered_number = entered_number*10 + 7;
break;
case '8':
entered_number = entered_number*10 + 8;
break;
case '9':
entered_number = entered_number*10 + 9;
break;
case 'i':
/* update isovalue with number entered */
isovalue = entered_number % 256;
entered_number = 0;
printf("Setting isovalue to %d\n", isovalue);
redraw = 1;
break;
case '{':
/* decrease epsilon */
{
int newvalue = epsilon - 2;
if (newvalue < 0)
epsilon = 0;
else
epsilon = newvalue;
}
printf("Setting epsilon to %d\n", epsilon);
redraw = 1;
break;
case '}':
/* increase epsilon */
{
int newvalue = epsilon + 2;
if (newvalue > 255)
epsilon = 255;
else
epsilon = newvalue;
}
printf("Setting epsilon to %d\n", epsilon);
redraw = 1;
break;
case 'e':
/* update epsilon with number entered */
epsilon = entered_number % 256;
entered_number = 0;
printf("Setting epsilon to %d\n", epsilon);
redraw = 1;
break;
case 'f':
/* enable/display FPS counter display */
display_fps_counter = 1 - display_fps_counter;
break;
case 'a':
use_arrays = 1 - use_arrays;
if (use_arrays)
printf("Now using arrays\n");
else
printf("Stopped using arrays\n");
glutPostRedisplay();
break;
}
reset_timer();
if (redraw)
{
regenerate_arrays = 1;
glutPostRedisplay();
}
}
void specialKeyPressed(int key, int x, int y)
{
/* keep gcc happy, as we don't use these parameters */
(void)key;
(void)x;
(void)y;
}
static void
mouseFunc(int button, int state, int x, int y)
{
// guard against both left and right buttons being pressed at the same time,
// by only responding when a mouse button is pressed while another one
// hasn't been pressed yet
if (state == GLUT_DOWN && mouse_mode == 0)
{
if (button == GLUT_LEFT_BUTTON)
{
mouse_mode = GLUT_LEFT_BUTTON;
saved_camRotZ = camRotZ;
saved_camAzimuth = camAzimuth;
mx = x;
my = y;
}
else if (button == GLUT_RIGHT_BUTTON)
{
mouse_mode = GLUT_RIGHT_BUTTON;
saved_camDistance = camDistance;
my = y;
}
}
else if (state == GLUT_UP && button == mouse_mode)
{
// pressed button released
mouse_mode = 0;
}
}
static void
motionFunc(int x, int y)
{
int dx, dy;
if (mouse_mode == GLUT_LEFT_BUTTON)
{
dx = mx - x;
dy = my - y;
camRotZ = saved_camRotZ - dx * 0.25;
camAzimuth = saved_camAzimuth - dy * 0.25;
if (camAzimuth > 89.99)
camAzimuth = 89.99;
else if (camAzimuth < -89.99)
camAzimuth = -89.99;
}
else if (mouse_mode == GLUT_RIGHT_BUTTON)
{
dy = my - y;
camDistance = saved_camDistance - dy * sizex;
if (camDistance < 0.01)
camDistance = 0.01;
}
}
static void
initialize_volume(const char *fname, unsigned char iso)
{
read_volume(fname);
isovalue = iso;
if (epsilon > 0)
printf("Iso-value = %d (+/- %d)\n", isovalue, epsilon);
else
printf("Iso-value = %d\n", isovalue);
// Initial distance from camera position to center of volume
camDistance = 2.0 * nx * sizex;
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
if (argc != 3)
{
printf("usage: %s datafile isovalue\n", argv[0]);
exit(0);
}
initialize_volume(argv[1], atoi(argv[2]));
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(0, 0);
window = glutCreateWindow("OpenGL Framework");
glutDisplayFunc(&DrawScene);
glutIdleFunc(&DrawScene);
glutReshapeFunc(&ReSizeScene);
glutSpecialFunc(&specialKeyPressed);
glutKeyboardFunc(&keyPressed);
glutMouseFunc(&mouseFunc);
glutMotionFunc(&motionFunc);
InitOpenGL();
glutMainLoop();
return 1;
}
#ifndef V3MATH_H
#define V3MATH_H
#include <math.h>
typedef struct
{
float x, y, z;
}
vec3;
// Create a new 3-vector of floats
static inline vec3
v3_create(float x, float y, float z)
{
vec3 res;
res.x = x;
res.y = y;
res.z = z;
return res;
}
// Return -a
static inline vec3
v3_negate(vec3 a)
{
vec3 res;
res.x = - a.x;
res.y = - a.y;
res.z = - a.z;
return res;
}
// Return a + b
static inline vec3
v3_add(vec3 a,vec3 b)
{
vec3 res;
res.x = a.x+b.x;
res.y = a.y+b.y;
res.z = a.z+b.z;
return res;
}
// Return a - b
static inline vec3
v3_subtract(vec3 a, vec3 b)
{
vec3 res;
res.x = a.x-b.x;
res.y = a.y-b.y;
res.z = a.z-b.z;
return res;
}
// Return a / |a|
static inline vec3
v3_normalize(vec3 a)
{
vec3 res;
double l = sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
res = a;
res.x /= l;
res.y /= l;
res.z /= l;
return res;
}
// Return a ^ b
static inline vec3
v3_crossprod(vec3 a, vec3 b)
{
vec3 res;
res.x = a.y*b.z - a.z*b.y;
res.y = a.z*b.x - a.x*b.z;
res.z = a.x*b.y - a.y*b.x;
return res;
}
// Return a * b
static inline float
v3_dotprod(vec3 a, vec3 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
// Return a*s
static inline vec3
v3_multiply(vec3 a, float s)
{
vec3 res;
res.x = a.x*s;
res.y = a.y*s;
res.z = a.z*s;
return res;
}
// Return |a|
static inline float
v3_length(vec3 a)
{
return sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
}
// Return the i-th component of a, i.e. for i=0
// this returns a.x
static inline float
v3_component(vec3 a, int i)
{
if (i == 0)
return a.x;
else if (i == 1)
return a.y;
else
return a.z;
}
// Set the i-th component of a to v
static inline vec3
v3_set_component(vec3 a, int i, float v)
{
vec3 res = a;
if (i == 0)
res.x = v;
else if (i == 1)
res.y = v;
else
res.z = v;
return res;
}
#endif
/* Computer Graphics, Assignment, Volume rendering with cubes/points
*
* Description ..... Creates OpenGL window and draws the scene.
* Date ............ 29.10.2008
* Created by ...... Paul Melis
*
* Student name .... Sander van Veen & Taddeus Kroes
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Collegekaart .... 6167969 & 6054129
* Date ............ 07.11.2010
*/
#include <stdio.h>
#include <stdlib.h>
#include "volume.h"
/* The voxels of the volume dataset, stored as a one-dimensional array */
unsigned char *volume;
/* The dimensions of the volume dataset */
int nx, ny, nz;
/* The size of a voxel */
float sizex, sizey, sizez;
/* Utility function to convert the index of a voxel
into an index in the volume array above */
int
voxel2idx(int i, int j, int k)
{
return (k*ny + j)*nx + i;
}
/* Utility function to read a volume dataset from a VTK file.
This will store the data in the "volume" array and update the dimension
and size values. */
void
read_volume(const char *fname)
{
FILE *f;
char s[256];
unsigned int nvoxels;
printf("Reading %s\n", fname);
f = fopen(fname, "rb");
if (!f)
{
fprintf(stderr, "read_volume(): Could not open file '%s' for reading!\n", fname);
exit(-1);
}
// header line
fgets(s, 255, f);
// comment line
fgets(s, 255, f);
// BINARY
fgets(s, 255, f);
// DATASET STRUCTURED_POINTS
fgets(s, 255, f);
// DIMENSIONS %d %d %d
fscanf(f, "%s %d %d %d\n", s, &nx, &ny, &nz);
printf("%d x %d x %d voxels\n", nx, ny, nz);
// ASPECT_RATIO/SPACING %f %f %f
fscanf(f, "%s %f %f %f\n", s, &sizex, &sizey, &sizez);
printf("voxel sizes: %.3f, %.3f, %.3f\n", sizex, sizey, sizez);
// ORIGIN ...
fgets(s, 255, f);
// POINT_DATA ...
fgets(s, 255, f);
// SCALARS ...
fgets(s, 255, f);
// LOOKUP_TABLE ...
fgets(s, 255, f);
// allocate memory to hold the volume data and read it from file
nvoxels = nx * ny * nz;
volume = (unsigned char*)malloc(nvoxels);
if (fread(volume, 1, nvoxels, f) < nvoxels)
{
printf("WARNING: not all data could be read!\n");
}
fclose(f);
}
#ifndef VOLUME_H
#define VOLUME_H
/* The data points in the volume dataset, stored as a one-dimensional array */
extern unsigned char *volume;
/* The dimensions of the volume dataset in number of voxels in each
dimension*/
extern int nx, ny, nz;
/* The size of a voxel for each dimension */
extern float sizex, sizey, sizez;
/* Utility function to convert the index of a datapoint
into an index in the volume array above */
int voxel2idx(int i, int j, int k);
/* Utility function to read a volume dataset from a file.
This will store the data in the "volume" array and update the dimension
and size values. */
void read_volume(const char *fname);
#endif
......@@ -10,7 +10,6 @@
\usepackage{float}
\usepackage[dutch]{babel}
\usepackage{listings}
\lstset{
language=C,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment