⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hemicube.cpp

📁 The goal of this project is to explore the idea of point-based radiosity, which is a shooting radio
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  properties for the scene to be rendered.

  Parameters:

  scene - The Scene object to be rendered.

  camera_point - The position of the camera. This is the center
  of the HemiCube. 

  normal - The normal vector, which is perpendicular to the
  center face of the hemicube.  This is the same as the normal
  vector to the SceneTriangle where the HemiCube is currently
  situated. 
  
  up - The vector "up" vector for orienting the camera.
  
  light_color - The RGB color of the light to be placed
  at the center of the HemiCube.

  frustum_bottom - A floating point value describing the 
  frustum bottom to be passed to glFrustum. This is -1.0
  for the center face of the hemicube and 0.0 for the
  side faces, although we shouldn't depend on this.

  frustum_top - A floating point value that specifies the
  top of the frustum to be passed to glFrustum.  This
  is currently always 1.0, but we shouldn't depend on
  this either.

  Note: The left side of the frustum is always at -1.0f 
  and the right side of the frustum is always at 1.0f;

  modelview_matrix - Pointer to an array of 16 doubles.  This is used
  to store the current modelview matrix (current when the scene is
  rendered).  We need to get the modelview matrix because it
  is used later in the reconstruction phase as a parameter to
  gluUnProject.

  projection_matrix - Same as the modelview matrix parameter except
  that this is for the projection matrix.  Likewise, this is used
  later during reconstruction as a parameter for gluUnProject.

*/
void HemiCube::render_one_lighted_scene_buffer (const Scene& scene,
						const Point& camera_point,
						const Vector& normal,
						const Vector& up,
                                                const Color& light_color,
						float frustum_bottom,
						float frustum_top,
						GLdouble* modelview_matrix,
						GLdouble* projection_matrix) 
{
    assert(modelview_matrix != NULL);
    assert(projection_matrix != NULL);

    // This is a positional light, so the w component must 
    // be 1.0f.
    GLfloat light_origin[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // We need diffuse lighting, so enable lighting 
    // and light 0.
    glEnable(GL_LIGHTING);  
    glEnable(GL_LIGHT0);
    glShadeModel(GL_SMOOTH); 
    glDisable(GL_TEXTURE_2D); 

    // Set the camera to be a the camera_point 
    Point look_at = camera_point + normal;
        
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // Set the light position to be the origin, so that it
    // is at the lens of the camera. 
    glLightfv(GL_LIGHT0, GL_POSITION, light_origin);
    
    gluLookAt(camera_point.x(), camera_point.y(), camera_point.z(),
	      look_at.x(), look_at.y(), look_at.z(),
	      up.x(), up.y(), up.z());
    
    // Set the lighting parameters
    GLfloat light_color_vec[4];
    light_color.to_float_array(light_color_vec, 4);

    GLfloat no_light_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color_vec);
    glLightfv(GL_LIGHT0, GL_AMBIENT, no_light_color);
    glLightfv(GL_LIGHT0, GL_SPECULAR, no_light_color);

    // Do I need to adjust constant attenuation? 
    // 3.14159f

    // The quadratic attenuation is supposed to be pi,
    // but this value is too large, so nothing gets drawn. 
     // Maybe I have to 
    // take the size of the scene into account to properly
    // set this.  For now, just use pi/10 as the quadratic
    // attenuation coefficient.
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.3f);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0f);
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f);

    GLenum err = glGetError();

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0f, frustum_bottom, frustum_top, 1.0f, 100.0f);
    
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
    glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);

    scene.draw_diffuse_shaded();

    // Put the quadratic attenuation of light 0 back to zero,
    // which is the default state.  I'm sure that if i don't 
    // do this here, then I'll forget and it will look weird
    // later.
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f);
}


/*+-------------------------------------------------------------------
  HemiCube::clear_item_buffers

  Set all of the item buffers, both for RGB data and for 
  depth, to zero.

*/
void HemiCube::clear_item_buffers (void)
{
    memset(m_center_depth_buffer, 0, 
	   m_center_pixel_width * m_center_pixel_width * sizeof(float));

    size_t side_depth_buffer_size = 
	m_side_pixel_width * m_side_pixel_height * sizeof(float);

    memset(m_left_depth_buffer, 0, side_depth_buffer_size);
    memset(m_bottom_depth_buffer, 0, side_depth_buffer_size);
    memset(m_right_depth_buffer, 0, side_depth_buffer_size);
    memset(m_top_depth_buffer, 0, side_depth_buffer_size);

    size_t center_rgb_buffer_size = 
	m_components_per_pixel * m_center_pixel_width * m_center_pixel_height;

    memset(m_center_item_buffer, 0, center_rgb_buffer_size);
	
    size_t side_rgb_buffer_size = 
	m_components_per_pixel * m_side_pixel_width * m_side_pixel_height;
    
    memset(m_left_item_buffer, 0, side_rgb_buffer_size);
    memset(m_bottom_item_buffer, 0, side_rgb_buffer_size);
    memset(m_right_item_buffer, 0, side_rgb_buffer_size);
    memset(m_top_item_buffer, 0, side_rgb_buffer_size);
}


/*+-------------------------------------------------------------------
  HemiCube::clear_rc_buffers

  Set the contents of the RC buffers to zero.

*/
void HemiCube::clear_rc_buffers (void)
{
    size_t center_rgb_buffer_size = 
	m_components_per_pixel * m_center_pixel_width * m_center_pixel_height * sizeof(float);

    size_t side_rgb_buffer_size = 
	m_components_per_pixel * m_side_pixel_width * m_side_pixel_height * sizeof(float);

    memset(m_center_rc_buffer, 0, center_rgb_buffer_size);
    memset(m_left_rc_buffer, 0, side_rgb_buffer_size);
    memset(m_bottom_rc_buffer, 0, side_rgb_buffer_size);
    memset(m_right_rc_buffer, 0, side_rgb_buffer_size);
    memset(m_top_rc_buffer, 0, side_rgb_buffer_size);
}


/*+-------------------------------------------------------------------
  HemiCube::reconstruct 
  
  This method takes the item buffer, the depth buffer, and the 
  RC buffer, and computes points in 3D from them using gluUnProject.
  These points and their corresponding colors are then stored
  with the triangle that they correspond to.
  
  These splats are later rendered onto the scenes textures
  in software or using glBegin(GL_POINTS), etc.

*/
void HemiCube::reconstruct (Scene& scene)
{
    for (int side_index = 0; side_index < 5; side_index++)
    {
	HemiCubeSide which_side = (HemiCubeSide)side_index;
	
	float* which_depth_buffer = NULL;
	float* which_rc_buffer = NULL;
	unsigned char* which_item_buffer = NULL;
	GLdouble* which_projection_matrix = NULL;
	GLdouble* which_modelview_matrix = NULL;
	int pixel_width  = -1;
	int pixel_height = -1; 
	float area = 2.0f;

	// Set various parameters to reconstruct
	// each side.  The code to do each side
	// is very very similar, so it makes sense to 
	// set up the parameters for the rendering 
	// in the following switch statement, and 
	// then invoke the reconstruction method
	// on one side.
	switch(which_side)
	{

	case Center:
	    which_depth_buffer = m_center_depth_buffer;
	    which_rc_buffer = m_center_rc_buffer;
	    which_item_buffer = m_center_item_buffer;
	    which_projection_matrix = m_center_projection;
	    which_modelview_matrix = m_center_modelview;
	    pixel_width = m_center_pixel_width;
	    pixel_height = m_center_pixel_height;
	    area = 4.0f;
	    break;
	    
	case Left:
	    which_depth_buffer = m_left_depth_buffer;
	    which_rc_buffer = m_left_rc_buffer;
	    which_item_buffer = m_left_item_buffer;
	    which_projection_matrix = m_left_projection;
	    which_modelview_matrix = m_left_modelview;
	    pixel_width = m_side_pixel_width;
	    pixel_height = m_side_pixel_height;
	    break;

	case Bottom:
	    which_depth_buffer = m_bottom_depth_buffer;
	    which_rc_buffer = m_bottom_rc_buffer;
	    which_item_buffer = m_bottom_item_buffer;
	    which_projection_matrix = m_bottom_projection;
	    which_modelview_matrix = m_bottom_modelview;
	    pixel_width = m_side_pixel_width;
	    pixel_height = m_side_pixel_height;
	    break;

	case Right:
	    which_depth_buffer = m_right_depth_buffer;
	    which_rc_buffer = m_right_rc_buffer;
	    which_item_buffer = m_right_item_buffer;
	    which_projection_matrix = m_right_projection;
	    which_modelview_matrix = m_right_modelview;
	    pixel_width = m_side_pixel_width;
	    pixel_height = m_side_pixel_height;
	    break;

	case Top:
	    which_depth_buffer = m_top_depth_buffer;
	    which_rc_buffer = m_top_rc_buffer;
	    which_item_buffer = m_top_item_buffer;
	    which_projection_matrix = m_top_projection;
	    which_modelview_matrix = m_top_modelview;
	    pixel_width = m_side_pixel_width;
	    pixel_height = m_side_pixel_height;
	    break;
	}

	// Assert that the needed paramters to 
	// reconstruct one side have all been set.
	// This isn't completely sufficient to 
	// ensure that everything has been set up
	// properly, but it's better than nothing.
	assert(which_depth_buffer != NULL);
	assert(which_rc_buffer != NULL);
	assert(which_item_buffer != NULL);
	assert(which_projection_matrix != NULL);
	assert(which_modelview_matrix != NULL);

	assert(pixel_width != -1);
	assert(pixel_height != -1);

	this->reconstruct_one_side(scene, 
				   which_rc_buffer, 
				   which_depth_buffer, 
				   which_item_buffer,
				   pixel_width, 
				   pixel_height, 
				   area, 
				   which_modelview_matrix, 
				   which_projection_matrix);
	
    }
}


/*+-------------------------------------------------------------------
  HemiCube::reconstruct_one_side

  For one side of the HemiCube go through the item buffer,
  the depth buffer, and the RC buffer (RC = diffuse rendering * cosine)
  and figure out which reprojected points belong to which scene
  elements. 
  
*/
void HemiCube::reconstruct_one_side (Scene& scene, 
				     float* rc_buffer,
				     float* depth_buffer,
				     unsigned char* item_buffer,
				     int pixel_width, 
				     int pixel_height,
				     float area, 
				     GLdouble* modelview_matrix,
				     GLdouble* projection_matrix)
{
    SceneTriangle* tri  = NULL;
    
    GLint viewport[] = { 0, 0, pixel_width, pixel_height};

    // Go through the center item buffer
    for (int pixel_y = 0; pixel_y < pixel_height; pixel_y++)
    {
	for (int pixel_x = 0; pixel_x < pixel_width; pixel_x++)
	{
	    // Get the element from the item buffer and 
	    // get an id for it. 
	    // Use (r, g, b) to get a SceneTriangle out. 
	    unsigned int depth_offset = 
		(pixel_y * pixel_width + pixel_x);
	    
	    unsigned int item_offset = 3 * depth_offset;
	    
	    unsigned char item_r = item_buffer[item_offset];
	    unsigned char item_g = item_buffer[item_offset + 1];
	    
	    unsigned char item_b = item_buffer[item_offset + 2];
	    
	    float depth = depth_buffer[depth_offset];
	    
	    unsigned int rc_offset = item_offset;
	    
	    float rc_red = rc_buffer[rc_offset];
	    float rc_green = rc_buffer[rc_offset + 1];
	    float rc_blue = rc_buffer[rc_offset + 2];
	    
	    GLdouble objx, objy, objz;
	    
	    unsigned int tri_id = 
		SceneTriangle::item_rgb_to_id(item_r, item_g, item_b);
	    
	    if ((tri == NULL) || 
		(tri->id() != tri_id))
	    {
		tri = scene.item_rgb_to_triangle(item_r, item_g, item_b);
	    }

	    if (item_r != 0 && item_g != 0 && item_b != 0)
	    {
		assert(tri != NULL);
	    }
	    if (tri && (depth < 1.0f) && (depth > 0.0f))
	    {

		gluUnProject(pixel_x + 0.5, pixel_y + 0.5, 
			     depth,
			     modelview_matrix,
			     projection_matrix,
			     viewport, 
			     &objx, &objy, &objz);

		// At this point we have a point and a SceneTriangle
		// onto which this should be drawn. Next comes 
		// reconstruction.  We can take advantage of coherence
		// since adjacent pixels are likely to map to the same
		// SceneTriangle.

		Splat splat;
	        
		// Multiplying by 1 / (res)^2 is the correct thing
		// to do.
                                
		float res_factor = area / float(pixel_width * pixel_height);
		float factor = 100.0f * res_factor;
		splat.color = Color(factor * rc_red, 
				    factor * rc_green, 
				    factor * rc_blue);
		splat.point = Point((float)objx, (float)objy,(float)objz);

		tri->add_splat(splat);

	    }

	}
    }

    // For this side of the hemicube, all of the splats have
    // been accumulated into the scene.  Maybe now is the 
    // time to do the reconstruction.
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -