📄 hemicube.cpp
字号:
/*+-------------------------------------------------------------------
Ben Landon
CSCI E-235
Final Project
HemiCube.cpp - Contains the implementation of the HemiCube class,
including methods for performing the renderings from each of the
five faces of the hemicube. This class also manages the buffers
that hold the flat and diffuse renderings.
Typically there is only one HemiCube object per program, although
there is nothing that would prevent more of them.
*/
#include <stdio.h>
#include <math.h>
#include "HemiCube.hpp"
#include "Texture.hpp"
#include "gl_common.h"
#include "pgm_util.hpp"
#include "Map_of.hpp"
// Enumeration describing to refer to a particular
// side of the hemicube.
enum HemiCubeSide
{
Center,
Left,
Bottom,
Right,
Top
};
/*+-------------------------------------------------------------------
The HemiCube is 2.0 units on a side.
The hemicube is responsible for managing the sets of renderings
(depth, item, color, cosine texture).
m_center_pixel_width and m_center_pixel_height are the dimensions of
the center face of the hemicube. The sides of the hemicube are
m_side_pixel_width by m_side_pixel_height.
*/
HemiCube::HemiCube (void)
:
m_center_pixel_width(32),
m_center_pixel_height(32),
m_side_pixel_width(32),
m_side_pixel_height(16),
m_components_per_pixel(3),
m_center_rc_buffer(NULL),
m_left_rc_buffer(NULL),
m_bottom_rc_buffer(NULL),
m_right_rc_buffer(NULL),
m_top_rc_buffer(NULL),
m_center_cosine_texture(NULL),
m_bottom_cosine_texture(NULL)
{
// OpenGL must be enabled for this constructor to
// work properly since this creates textures.
this->load_cosine_image();
size_t center_depth_buffer_size =
m_center_pixel_width * m_center_pixel_height;
m_center_depth_buffer =
new float[center_depth_buffer_size];
size_t side_depth_buffer_size = m_side_pixel_width * m_side_pixel_height;
m_left_depth_buffer =
new float[side_depth_buffer_size];
m_bottom_depth_buffer =
new float[side_depth_buffer_size];
m_right_depth_buffer =
new float[side_depth_buffer_size];
m_top_depth_buffer =
new float[side_depth_buffer_size];
size_t center_rgb_buffer_size =
m_components_per_pixel * m_center_pixel_width * m_center_pixel_height;
m_center_item_buffer =
new unsigned char [center_rgb_buffer_size];
size_t side_rgb_buffer_size =
m_components_per_pixel * m_side_pixel_width * m_side_pixel_height;
m_left_item_buffer = new unsigned char [side_rgb_buffer_size];
m_bottom_item_buffer = new unsigned char [side_rgb_buffer_size];
m_right_item_buffer = new unsigned char [side_rgb_buffer_size];
m_top_item_buffer = new unsigned char [side_rgb_buffer_size];
this->clear_item_buffers();
m_center_rc_buffer = new float[center_rgb_buffer_size];
m_left_rc_buffer = new float [side_rgb_buffer_size];
m_bottom_rc_buffer = new float [side_rgb_buffer_size];
m_right_rc_buffer = new float [side_rgb_buffer_size];
m_top_rc_buffer = new float [side_rgb_buffer_size];
this->clear_rc_buffers();
}
/*+-------------------------------------------------------------------
HemiCube destructor
Delete all of the dynamically allocated buffers. Also delete
any textures created by the HemiCube object.
*/
HemiCube::~HemiCube ()
{
if (m_center_item_buffer)
{
delete [] m_center_item_buffer;
m_center_item_buffer = NULL;
}
if (m_left_item_buffer)
{
delete [] m_left_item_buffer;
m_left_item_buffer = NULL;
}
if (m_bottom_item_buffer)
{
delete [] m_bottom_item_buffer;
m_bottom_item_buffer = NULL;
}
if (m_right_item_buffer)
{
delete [] m_right_item_buffer;
m_right_item_buffer = NULL;
}
if (m_top_item_buffer)
{
delete [] m_top_item_buffer;
m_top_item_buffer = NULL;
}
if (m_center_depth_buffer)
{
delete [] m_center_depth_buffer;
m_center_depth_buffer = NULL;
}
if (m_left_depth_buffer)
{
delete [] m_left_depth_buffer;
m_left_depth_buffer = NULL;
}
if (m_bottom_depth_buffer)
{
delete [] m_bottom_depth_buffer;
m_bottom_depth_buffer = NULL;
}
if (m_right_depth_buffer)
{
delete [] m_right_depth_buffer;
m_right_depth_buffer = NULL;
}
if (m_top_depth_buffer)
{
delete [] m_top_depth_buffer;
m_top_depth_buffer = NULL;
}
if (m_center_rc_buffer)
{
delete [] m_center_rc_buffer;
m_center_rc_buffer = NULL;
}
if (m_left_rc_buffer)
{
delete [] m_left_rc_buffer;
m_left_rc_buffer = NULL;
}
if (m_bottom_rc_buffer)
{
delete [] m_bottom_rc_buffer;
m_bottom_rc_buffer = NULL;
}
if (m_right_rc_buffer)
{
delete [] m_right_rc_buffer;
m_right_rc_buffer = NULL;
}
if (m_top_rc_buffer)
{
delete [] m_top_rc_buffer;
m_top_rc_buffer = NULL;
}
if (m_pCenter_cos_map)
{
delete m_pCenter_cos_map;
m_pCenter_cos_map = NULL;
}
if (m_pLeft_cos_map)
{
delete m_pLeft_cos_map;
m_pLeft_cos_map = NULL;
}
if (m_pBottom_cos_map)
{
delete m_pBottom_cos_map;
m_pBottom_cos_map = NULL;
}
if (m_pRight_cos_map)
{
delete m_pRight_cos_map;
m_pRight_cos_map = NULL;
}
if (m_pTop_cos_map)
{
delete m_pTop_cos_map;
m_pTop_cos_map = NULL;
}
if (m_center_cosine_texture)
{
delete m_center_cosine_texture;
m_center_cosine_texture = NULL;
}
if (m_bottom_cosine_texture)
{
delete m_bottom_cosine_texture;
m_bottom_cosine_texture = NULL;
}
}
/*+-------------------------------------------------------------------
HemiCube::load_cosine_image
Get the cosine texture from a PGM file. This is done
once when the HemiCube is created.
If something goes wrong with loading cosine.pgm, this
method can throw a HemiCubeException.
*/
void HemiCube::load_cosine_image (void)
{
unsigned char* data = NULL;
unsigned int width, height, colorDepth;
if (!read_pgm_file("cosine.pgm", &width, &height, &colorDepth, &data))
throw HemiCubeException();
// Go through the cosine image and populate some maps.
// Read the cosine.pgm image into a Map_of<float>
unsigned int counter = 0;
Map_of<float> temp_gray_map(width, height);
for (int j = 0; j < (int)height; j++)
{
for (int i = 0; i < (int)width; i++)
{
temp_gray_map.set(float(data[counter++])/255.0f, i, j);
}
}
// Now that the data from the texture is in the map.
// the array of uchars can be deleted.
if (data)
{
delete [] data;
data = NULL;
}
// Now create the 5 textures.
for (unsigned int tex_index = 0; tex_index < 5; tex_index++)
{
unsigned int tex_width, tex_height, tex_x, tex_y;
Map_of<float>* pMap = NULL;
HemiCubeSide which_side = (HemiCubeSide)tex_index;
switch (which_side)
{
case Center:
tex_width = width / 2;
tex_height = height / 2;
tex_x = width / 4;
tex_y = height / 4;
m_pCenter_cos_map = new Map_of<float>(tex_width, tex_height);
pMap = m_pCenter_cos_map;
break;
case Left:
tex_width = width /4;
tex_height = height / 2;
tex_x = 0;
tex_y = height / 4;
m_pLeft_cos_map = new Map_of<float>(tex_width, tex_height);
pMap = m_pLeft_cos_map;
break;
case Bottom:
tex_width = width / 2;
tex_height = height / 4;
tex_x = width / 4;
tex_y = 0;
m_pBottom_cos_map = new Map_of<float>(tex_width, tex_height);
pMap = m_pBottom_cos_map;
break;
case Right:
tex_width = width /4;
tex_height = height / 2;
tex_x = 3 * (width / 4);
tex_y = (height / 4);
m_pRight_cos_map = new Map_of<float>(tex_width, tex_height);
pMap = m_pRight_cos_map;
break;
case Top:
tex_width = width /2;
tex_height = height / 4;
tex_x = width / 4;
tex_y = 3 * (height / 4);
m_pTop_cos_map = new Map_of<float>(tex_width, tex_height);
pMap = m_pTop_cos_map;
break;
}
if (!pMap)
throw HemiCubeException();
for (int i = 0; i < (int)tex_width; i++)
{
for (int j = 0; j < (int)tex_height; j++)
{
float gray_val = temp_gray_map.get(i + tex_x, j + tex_y);
pMap->set(gray_val, i, j);
}
}
}
// Create the center and bottom grayscale textures
assert(m_pCenter_cos_map != NULL);
assert(m_pBottom_cos_map != NULL);
m_center_cosine_texture = new GrayscaleTexture(*m_pCenter_cos_map);
m_bottom_cosine_texture = new GrayscaleTexture(*m_pBottom_cos_map);
}
/*+-------------------------------------------------------------------
HemiCube::debug_draw_rc_buffer
This is a method for debugging the HemiCube class. It just
draws the buffer holding the center diffuse scene at the
current raster position.
*/
void HemiCube::debug_draw_rc_buffer (void)
{
glDrawPixels(m_center_pixel_width,
m_center_pixel_height,
GL_RGB, GL_FLOAT,
m_center_rc_buffer);
}
/*+-------------------------------------------------------------------
HemiCube::debug_draw_item_buffer
This is also a debugging tool. It draws the item
buffer to the current raster position. The item buffer
is the buffer that contains a rendering of the scene,
with flat shading and no lighting. The item buffer is used
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -