#include "rts_glVolumeViewer.h" #include "PerformanceData.h" PerformanceData PD; rts_glVolumeViewer::rts_glVolumeViewer() { m_optimize=false; m_min_threshold = 0; m_max_threshold = 255; m_volume_texture = 0; m_p = point3D(0.0, 0.0, 0.0); m_texture_size = vector3D(2,2,1); m_voxel_size = vector3D(1.0, 1.0, 1.0); m_dimensions = vector3D(m_texture_size.x * m_voxel_size.x, m_texture_size.y * m_voxel_size.y, m_texture_size.z * m_voxel_size.z); m_dimensions.normalize(); //calculate the radii m_inner_radius = 0.5; m_outer_radius = (vector3D(1.0, 1.0, 1.0).length())*0.5; //create the plane display list SetNumPlanes(256); //visualization parameters m_alpha_scale = 1.0; } rts_glVolumeViewer::rts_glVolumeViewer(rtsVolume volume_data, point3D position = point3D(0.0, 0.0, 0.0), vector3D voxel_size = vector3D(1.0, 1.0, 1.0)) { m_optimize=false; m_volume_texture = 0; m_p = position; m_min_threshold = 0; m_max_threshold = 255; m_texture_size = vector3D(volume_data.get_dimx(), volume_data.get_dimy(), volume_data.get_dimz()); m_voxel_size = vector3D(1.0, 1.0, 1.0); m_dimensions = vector3D(m_texture_size.x * m_voxel_size.x, m_texture_size.y * m_voxel_size.y, m_texture_size.z * m_voxel_size.z); m_dimensions.normalize(); //store the volume PD.StartTimer(COPY_DATA); m_source = volume_data; PD.EndTimer(COPY_DATA); //calculate the radii //m_inner_radius = max(max(m_dimensions.x, m_dimensions.y), m_dimensions.z) * 0.5; //m_outer_radius = (m_dimensions.length())*0.5; m_inner_radius = 0.5; m_outer_radius = vector3D(1.0, 1.0, 1.0).length()*0.5; SetNumPlanes(256); CHECK_OPENGL_ERROR //enable 3d texture mapping glEnable(GL_TEXTURE_3D); CHECK_OPENGL_ERROR //3D Texture mapping glGenTextures(1, &m_volume_texture); CHECK_OPENGL_ERROR glBindTexture(GL_TEXTURE_3D, m_volume_texture); CHECK_OPENGL_ERROR glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP); CHECK_OPENGL_ERROR //load the texture data m_load_texture(); CHECK_OPENGL_ERROR // our texture colors will replace the untextured colors glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); glShadeModel(GL_FLAT); CHECK_OPENGL_ERROR glDisable(GL_TEXTURE_3D); //visualization parameters m_alpha_scale = 1.0; } //~rts_glVolumeViewer() //{ //} void rts_glVolumeViewer::RenderBoundingBox() { //create the transformation for the volume glMatrixMode(GL_MODELVIEW); glPushMatrix(); glScalef(m_dimensions.x, m_dimensions.y, m_dimensions.z); glTranslatef(m_p.x, m_p.y, m_p.z); glutWireCube(1.0); glPopMatrix(); } void rts_glVolumeViewer::m_draw_plane(point3D p, vector3D n, vector3D up) { //calculate the u, v vectors representing the plane vector3D v = up.cross(n); v.normalize(); vector3D u = n.cross(v); u.normalize(); //compute the points that make up the plane point3D p0 = p - v*m_outer_radius - u*m_outer_radius; point3D p1 = p - v*m_outer_radius + u*m_outer_radius; point3D p2 = p + v*m_outer_radius + u*m_outer_radius; point3D p3 = p + v*m_outer_radius - u*m_outer_radius; //compute texture coordinates point3D t0 = point3D(0.5, 0.5, 0.5) + (p0 - m_p); point3D t1 = point3D(0.5, 0.5, 0.5) + (p1 - m_p); point3D t2 = point3D(0.5, 0.5, 0.5) + (p2 - m_p); point3D t3 = point3D(0.5, 0.5, 0.5) + (p3 - m_p); //enable texture mapping //glEnable(GL_TEXTURE_3D); glBindTexture(GL_TEXTURE_3D, m_volume_texture); //enable blending glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1.0, 1.0, 1.0, 1.0); glBegin(GL_QUADS); glTexCoord3f(t0.x, t0.y, t0.z); glVertex3f(p0.x, p0.y, p0.z); glTexCoord3f(t1.x, t1.y, t1.z); glVertex3f(p1.x, p1.y, p1.z); glTexCoord3f(t2.x, t2.y, t2.z); glVertex3f(p2.x, p2.y, p2.z); glTexCoord3f(t3.x, t3.y, t3.z); glVertex3f(p3.x, p3.y, p3.z); glEnd(); glDisable(GL_TEXTURE_3D); glDisable(GL_BLEND); } void rts_glVolumeViewer::RenderCameraSlice(point3D eye_point, vector3D camera_up, float slice_number) { /*Renders a slice of the volume at the specified value (0 = closest to the camera while 1 = furthest from the camera). The slice is oriented towards the camera position*/ /*//get the vector from the volume to the eye point vector3D to_camera = eye_point - m_p; //normalize in order to compute the plane normal to_camera.normalize(); //draw the camera-oriented plane m_draw_plane(m_p, to_camera, camera_up);*/ glMatrixMode(GL_MODELVIEW); glPushMatrix(); //calculate the new basis functions vector3D to_camera = (eye_point - m_p); to_camera.normalize(); vector3D side = camera_up.cross(to_camera); side.normalize(); camera_up = to_camera.cross(side); camera_up.normalize(); //create the rotation matrix matrix4x4 mat_rotate(side, camera_up, to_camera); float gl_rotate[16]; mat_rotate.gl_get_matrix(gl_rotate); //perform the geometric transformations glScalef(m_dimensions.x, m_dimensions.y, m_dimensions.z); glTranslatef(m_p.x, m_p.y, m_p.z); glMultMatrixf(gl_rotate); //perform the texture transformations glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glScalef(m_source.get_dimx()/m_texture_size.x, m_source.get_dimy()/m_texture_size.y, m_source.get_dimz()/m_texture_size.z); glTranslatef(0.5, 0.5, 0.5); glMultMatrixf(gl_rotate); //enable texture mapping glEnable(GL_TEXTURE_3D); glBindTexture(GL_TEXTURE_3D, m_volume_texture); //enable blending //glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //draw the planes glColor4f(1.0, 1.0, 1.0, 1.0); //PD.StartTimer(RENDER_PLANES); //glCallList(m_dl_planes); glBegin(GL_QUADS); glTexCoord3f(-m_outer_radius, -m_outer_radius, slice_number); glVertex3f(-m_outer_radius, -m_outer_radius, slice_number); glTexCoord3f(-m_outer_radius, m_outer_radius, slice_number); glVertex3f(-m_outer_radius, m_outer_radius, slice_number); glTexCoord3f(m_outer_radius, m_outer_radius, slice_number); glVertex3f(m_outer_radius, m_outer_radius, slice_number); glTexCoord3f(m_outer_radius, -m_outer_radius, slice_number); glVertex3f(m_outer_radius, -m_outer_radius, slice_number); glEnd(); //glFinish(); //PD.EndTimer(RENDER_PLANES); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_TEXTURE); glPopMatrix(); glDisable(GL_TEXTURE_3D); glDisable(GL_BLEND); } void rts_glVolumeViewer::RenderVolume(point3D eye_point, vector3D camera_up) { if(m_volume_texture == 0) return; glMatrixMode(GL_MODELVIEW); glPushMatrix(); //calculate the new basis functions vector3D to_camera = (eye_point - m_p); to_camera.normalize(); vector3D side = camera_up.cross(to_camera); side.normalize(); camera_up = to_camera.cross(side); camera_up.normalize(); //create the rotation matrix matrix4x4 mat_rotate(side, camera_up, to_camera); float gl_rotate[16]; mat_rotate.gl_get_matrix(gl_rotate); //perform the geometric transformations glScalef(m_dimensions.x, m_dimensions.y, m_dimensions.z); glTranslatef(m_p.x, m_p.y, m_p.z); glMultMatrixf(gl_rotate); //perform the texture transformations glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glScalef(m_source.get_dimx()/m_texture_size.x, m_source.get_dimy()/m_texture_size.y, m_source.get_dimz()/m_texture_size.z); glTranslatef(0.5, 0.5, 0.5); glMultMatrixf(gl_rotate); //enable texture mapping glEnable(GL_TEXTURE_3D); glBindTexture(GL_TEXTURE_3D, m_volume_texture); //enable blending glDisable(GL_DEPTH_TEST); //glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //draw the planes glColor4f(1.0, 1.0, 1.0, m_alpha_scale); PD.StartTimer(RENDER_PLANES); glCallList(m_dl_planes); glFinish(); PD.EndTimer(RENDER_PLANES); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_TEXTURE); glPopMatrix(); glDisable(GL_TEXTURE_3D); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); } void rts_glVolumeViewer::SetNumPlanes(unsigned int planes) { //set the number of planes m_num_planes = planes; //create the display list m_dl_planes = glGenLists(1); glNewList(m_dl_planes, GL_COMPILE); //the display planes run from (-m_outer_radius, m_outer_radius) in each dimension float z_step = 2.0*m_outer_radius/(planes + 1.0); glBegin(GL_QUADS); for(int z=0; z 0) texture_volume.blacken(m_min_threshold); if(m_max_threshold < 255) texture_volume.whiten(m_max_threshold); //if we are optimizing the texture, make the dimensions a power-of-two if(m_optimize) { PD.StartTimer(RESIZE_DATA); //find the maximum dimension unsigned int max_dimension = max(max(m_source.get_dimx(), m_source.get_dimy()), m_source.get_dimz()); unsigned int new_dimension = 2; //calculate the new dimension while(new_dimension < max_dimension) new_dimension *= 2; //resize the texture volume texture_volume.resize_canvas(new_dimension, new_dimension, new_dimension); PD.EndTimer(RESIZE_DATA); } //apply the new image to the texture glBindTexture(GL_TEXTURE_3D, m_volume_texture); unsigned int dimx = texture_volume.get_dimx(); unsigned int dimy = texture_volume.get_dimy(); unsigned int dimz = texture_volume.get_dimz(); m_texture_size = vector3D((double)dimx, (double)dimy, (double)dimz); unsigned char* bits = texture_volume.get_bits(); glTexImage3D(GL_TEXTURE_3D, 0, GL_ALPHA8, dimx, dimy, dimz, 0, GL_ALPHA, GL_UNSIGNED_BYTE, bits); PD.EndTimer(LOAD_TEXTURE); }