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

📄 render.cc

📁 MatlabVisualization Package
💻 CC
字号:
#include "render.h"#include <iostream>#include <fstream>#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <math.h>#include "mpi.h"const int IMAGE_TAG = 1;const int AXES_INDENT = 50;const int TICK_LENGTH = 10;const int NUM_BOX_SIZE = 16;const int NUM_DISTANCE = NUM_BOX_SIZE / 2;#define _RECTANGLE_Render::Render(int w, int h, int rank, double *data, int start_row, 	       int start_column, int nrows, int ncols, 	       DistLayout *data_layout, bool render_spy) {  r = rank;  data_buffer = data;  image_buffer = NULL;  send_buffer = NULL;  depth_buffer = NULL;  send_depth = NULL;  valid_procs = NULL;  is_spy = render_spy;  nonzero = 0;  num_blocks = data_layout->blocks;  blocks_data = data_layout->block_data;  MPI_Comm_size(MPI_COMM_WORLD, &num_procs);  if (rank != DISPLAY_NODE) {    if (!num_blocks || 	((blocks_data[0] == blocks_data[2]) &&	 (blocks_data[1] == blocks_data[3]))) {      // there is no data on this node      valid = 0;    }    else {      valid = 1;    }    MPI_Send(&valid, 1, MPI_INT, 0, IMAGE_TAG, MPI_COMM_WORLD);    if (!valid) {      if (!is_spy) {	double minval = HUGE;	double maxval = MINISCULE;	MPI_Allreduce(&minval, &minZ, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);	MPI_Allreduce(&maxval, &maxZ, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);	if (is_spy) 	  MPI_Allreduce(&nonzero, &num_nonzeros, 1, MPI_INT, 			MPI_SUM, MPI_COMM_WORLD);      }      return;    }  }  else {    valid = 1;    MPI_Status status;    valid_procs = new int[num_procs];        for (int proc = 1; proc < num_procs; proc++) {      MPI_Recv(&valid, 1, MPI_INT, proc, IMAGE_TAG,	       MPI_COMM_WORLD, &status);      valid_procs[proc] = valid;    }  }  width = w; height = h;  nr = nrows; nc = ncols;   sr = start_row; sc = start_column;  lCols = data_layout->lCols;//Total number of rows or columns on this node.  lRows = data_layout->lRows;   if (!is_spy) {    // find out minimum and maximum value in the matrix    double minval, maxval;    minval = maxval = data_buffer[0];    for (int i = 0; i < lRows; i++)      for (int j = 0; j < lCols; j++) {	double val = data_buffer[i * lCols + j];	if (val < minval)	  minval = val;	if (val > maxval)	  maxval = val;      }        MPI_Allreduce(&minval, &minZ, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);    MPI_Allreduce(&maxval, &maxZ, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);  }  axes_length = min (width, height) / 2;  reshape();  initTexture();}Render::~Render() {  if (image_buffer)    free(image_buffer);  if (send_buffer)    free(send_buffer);  if (depth_buffer)    free(depth_buffer);   if (send_depth)    free(send_depth);    if (valid_procs)    delete []valid_procs;  /* destroy the context */  OSMesaDestroyContext(ctx); }void Render::collect_images() {#ifdef _RECTANGLE_  int x, y, image_rows, image_cols, buf_size;  unsigned char *recv_image_buf;  GLfloat *recv_depth_buf;  MPI_Status status;  for (int proc = 1; proc < num_procs; proc++) {    if (valid_procs[proc]) {      MPI_Recv(image_info, 4, MPI_INT, proc, IMAGE_TAG, MPI_COMM_WORLD, 	       &status);         x = image_info[0];      y = image_info[1];      image_rows = image_info[2];      image_cols = image_info[3];      buf_size = image_rows * image_cols;          recv_image_buf = (unsigned char*) malloc(sizeof(unsigned char) * 					       buf_size);      MPI_Recv(recv_image_buf, buf_size, MPI_BYTE, proc, IMAGE_TAG,	       MPI_COMM_WORLD, &status);      if (!is_spy) {	recv_depth_buf = (GLfloat*) malloc(sizeof(GLfloat) * 					   buf_size);	MPI_Recv(recv_depth_buf, buf_size, MPI_FLOAT, proc, IMAGE_TAG,		 MPI_COMM_WORLD, &status);      }      int k = 0;          for (int i = y; i < image_rows + y; i++)	for (int j = x; j < image_cols + x; j++) {	  int index = i * width + j;	  if (!is_spy) {	    if (depth_buffer[index] > recv_depth_buf[k]) {	      send_buffer[index] = recv_image_buf[k];	      depth_buffer[index] = recv_depth_buf[k];	    }	  }	  else if (recv_image_buf[k] != WHITE) {	    send_buffer[index] = recv_image_buf[k];	  }	  k++;	}          free(recv_image_buf);      if (!is_spy) {	free(recv_depth_buf);      }    }  }#elseint buf_size = width * height;  MPI_Status status;  int k = 0;  GLubyte *buf = (GLubyte*) image_buffer;  for (int i = 0; i < buf_size * 4; i += 4)    send_buffer[k++] = buf[i];  unsigned char** images = new unsigned char*[num_procs];  GLfloat** depths = new GLfloat*[num_procs];  MPI_Request* requests = new MPI_Request[2 * num_procs];  MPI_Status* statuses = new MPI_Status[2 * num_procs];  int num_recvs = 0;  for (int proc = 1; proc < num_procs; proc++) {    if (valid_procs[proc]) {      images[proc] = new unsigned char[buf_size];      MPI_Irecv(images[proc], buf_size, MPI_BYTE, proc, IMAGE_TAG, 		MPI_COMM_WORLD, &requests[num_recvs++]);      if (!is_spy) {	depths[proc] = new GLfloat[buf_size];	MPI_Irecv(depths[proc], buf_size, MPI_FLOAT, proc, IMAGE_TAG,		  MPI_COMM_WORLD, &requests[num_recvs++]);      }    }  }  MPI_Waitall(num_recvs, requests, statuses);  unsigned char *image;  GLfloat* depth;  for (int proc = 1; proc < num_procs; proc++) {    if (valid_procs[proc]) {      image = images[proc];      depth = depths[proc];      if (!is_spy) {	for (int i = 0; i < buf_size; i++)	  if (depth_buffer[i] > depth[i]) {	    send_buffer[i] = image[i];	    depth_buffer[i] = depth[i];	  }      }      else {	for (int i = 0; i < buf_size; i++) {	  if (image[i] != WHITE) {	    send_buffer[i] = image[i];	  }	}      }       delete []image;      if (!is_spy)	delete []depth;    }  }  delete []images;  delete []requests;  delete []statuses;  delete []depths;#endif  int buf_index, image_index, color_index;  for (int j = 0; j < width; j++)     for (int i = 0; i < height; i++) {      buf_index = i * width + j;      color_index = (int) ((unsigned char*) send_buffer)[buf_index];      image_index = 3 * (j * height + (height - i));      final_image[image_index + 0] = colormap[color_index][0];      final_image[image_index + 1] = colormap[color_index][1];      final_image[image_index + 2] = colormap[color_index][2];    }#ifdef _DEBUG_RENDER_  char *filename = new char[20];  sprintf(filename, "image.rgb");    ofstream image_file(filename);  assert(image_file.good());   for (int i = 0; i < width * height * 3; i++) {    image_file << final_image[i] << " ";  }    image_file << endl;  image_file.close();#endif}float* Render::draw() {  if (!valid)    return final_image;  else if (2 * AXES_INDENT > width ||	   2 * AXES_INDENT > height) {    cout << "Please make the size of the drawing area larger !!!\n";    return final_image;  }  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );    if (r == DISPLAY_NODE) {    coordinatesGL();    coordinates();  }   dataGL();  for (int i = 0; i < num_blocks; i++)    if (draw_help(i))      break;   glFinish();   if (!is_spy) {    depth_buffer = (GLfloat*) malloc(sizeof(GLfloat) * width * height);    glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, 		 GL_FLOAT, depth_buffer);  }  done_drawing();  rectangle();  if (r == DISPLAY_NODE)    collect_images();  else    send();  return final_image;}void Render::done_drawing() {}void Render::axes(double x1, double y1, double z1, 		  double x2, double y2, double z2) {  line(x1, y1, z1, x2, y2, z2);  ticks(x1, y1, z1, x2, y2, z2);  }void Render::line(double x1, double y1, double z1, 		  double x2, double y2, double z2) {  glBegin(GL_LINES);  glVertex3d(x1, y1, z1);  glVertex3d(x2, y2, z2);  glEnd();  }void Render::ticks(double x1, double y1, double z1,		   double x2, double y2, double z2) {  if (x1 == x2) {    ticks_help(x1, y1, y2, sr, nr + 1, true);  }  else {    ticks_help(y1, x1, x2, sc, nc + 1, false);  }}void Render::ticks_help(double constant, double var1, double var2,			int first_tick, int last_tick, bool x_axis) {  int line_length = (int) (var2 - var1);    int tick_distance = min(MIN_TICK_DISTANCE, line_length);  // Find out how many ticks we can have  int num_ticks = line_length / tick_distance;    int gap = (line_length % tick_distance) *     (last_tick - first_tick) / line_length;    double stride = (double) (last_tick - first_tick - gap) / (double) num_ticks;  int up_down = -1;  if (!x_axis) {    if (constant < height / 2) {      up_down = 1;    }  }  else if (constant < width / 2) {    up_down = 1;  }  for (double i = first_tick; i <= (int) last_tick; i += stride) {    double offset = var1 + ((i - first_tick) / stride) * tick_distance;    if (!x_axis) {      line(offset, constant, 0, offset, constant + TICK_LENGTH * up_down, 0);        if (up_down == -1) {	// awful hack to get around texture problem	glColor3f(1, 0, 0);	num((int) i, offset - NUM_BOX_SIZE / 2, constant + 2, 0);	glColor3ub(BLACK, 0, 0);      }    }    else {      line(constant, offset, 0, constant + TICK_LENGTH * up_down, offset, 0);        if (up_down == 1) {	glColor3f(1, 0, 0);	num((int) i, constant - NUM_BOX_SIZE, offset - NUM_BOX_SIZE / 2, 0);	glColor3ub(BLACK, 0, 0);      }    }  }}void Render::num(int num, double x, double y, double z) {    int temp = num;  num = abs(num);  for (int i = 0; i < 10; i++) {    double temp_num = (double) num / 10;    single_num(num - ((int) temp_num * 10), x, y, z);    x -= NUM_DISTANCE;    if (temp_num < 1.) {      if (temp < 0) {	single_num(10, x, y, z);      }      break;    }    if (is_spy && x < 0)      break;    num = (int) temp_num;  }  }void Render::single_num(int num, double x, double y, double z) {       glEnable(GL_TEXTURE_2D);    glBindTexture(GL_TEXTURE_2D, tex_ids[num]);    glBegin(GL_QUADS);    if (is_spy) {      glTexCoord3i(0, 0, 0); glVertex3d(x, y, z);      glTexCoord3i(0, 1, 0); glVertex3d(x, y + NUM_BOX_SIZE, z);      glTexCoord3i(1, 1, 0); glVertex3d(x + NUM_BOX_SIZE, y + NUM_BOX_SIZE, z);      glTexCoord3i(1, 0, 0); glVertex3d(x + NUM_BOX_SIZE, y, z);    }    else {      glTexCoord3d(0.4, 0, 0); glVertex3d(x, y, z);      glTexCoord3d(0.4, 1, 0); glVertex3d(x, y, z - NUM_BOX_SIZE);      glTexCoord3d(1, 1, 0); glVertex3d(x + 0.6 * NUM_BOX_SIZE, y, 					z - NUM_BOX_SIZE);      glTexCoord3d(1, 0, 0); glVertex3d(x + 0.6 * NUM_BOX_SIZE, y, z);    }    glEnd();    glDisable(GL_TEXTURE_2D);}void Render::initTexture() {  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);  glGenTextures(11, tex_ids);  for (int i = 0; i < 11; i++) {    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);        glBindTexture(GL_TEXTURE_2D, tex_ids[i]);        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);    if (!is_spy) {      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, 		   GL_UNSIGNED_BYTE, textures[i]);    }    else {      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, 		   GL_UNSIGNED_BYTE, textures_spy[i]);    }  }}void Render::reshape() {  /* Allocate the image buffer */  if (image_buffer)    free(image_buffer);  image_buffer = malloc(width * height * 4 * sizeof(GLubyte));  if (!image_buffer) {    cout << "Alloc image buffer failed!\n" << endl;    exit(1);  }  send_buffer = (unsigned char*) malloc(width * height * 					sizeof(unsigned char));  if (!send_buffer) {    cout << "Alloc send buffer failed!\n" << endl;    exit(1);  }  send_depth = (GLfloat*) malloc(width * height *				       sizeof(GLfloat));  if (!send_depth) {    cout << "Alloc depth buffer failed!\n" << endl;    exit(1);  }  ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );    if (!ctx) {    cout << "OSMesaCreateContext failed!" << endl;    exit(1);  }      /* Bind the buffer to the context and make it current */  if (!OSMesaMakeCurrent(ctx, image_buffer, GL_UNSIGNED_BYTE, width, height)) {    cout << "OSMesaMakeCurrent failed!" << endl;    exit(1);  }  if (r == DISPLAY_NODE)    final_image = new float[width * height * 3];  }void Render::rectangle() {#ifdef _RECTANGLE_   int lx, ly, rx, ry;  rx = ry = 0;  lx = width;  ly = height;    int image_buffer_width = width * 4;  GLubyte *buf = (GLubyte*) image_buffer;  for (int i = 0; i < height; i++)    for (int j = 0; j < image_buffer_width; j += 4) {      if ((int) buf[i * image_buffer_width + j]) {	int j_index = j / 4;	if (lx > j_index)	  lx = j_index;	if (ly > i)	  ly = i;	if (j_index > rx)	  rx = j_index;	if (i > ry)	  ry = i;      }    }  int rect_rows = max(ry - ly + 1, 0);  int rect_cols = max(rx - lx + 1, 0);  image_info[0] = lx;  image_info[1] = ly;  image_info[2] = rect_rows;  image_info[3] = rect_cols;  int k = 0;  if (r != DISPLAY_NODE) {    for (int i = ly; i < rect_rows + ly; i++)      for (int j = lx; j < rect_cols + lx; j++) {	send_buffer[k] = buf[i * image_buffer_width + j * 4];	if (!is_spy) {	  send_depth[k] = depth_buffer[i * width + j];	}	k++;      }  }  else {    for (int i = 0; i < width * height * 4; i += 4)      send_buffer[k++] = buf[i];  }#endif}void Render::send() {#ifdef _RECTANGLE_  int buf_size = image_info[2] * image_info[3];  MPI_Send(image_info, 4, MPI_INT, 0, IMAGE_TAG, MPI_COMM_WORLD);  MPI_Send(send_buffer, buf_size, MPI_BYTE, 0, IMAGE_TAG, MPI_COMM_WORLD);  if (!is_spy) {    MPI_Send(send_depth, buf_size, MPI_FLOAT, 0, IMAGE_TAG, MPI_COMM_WORLD);  } #else  int buf_size = width * height;  int k = 0;  GLubyte *buf = (GLubyte*) image_buffer;  for (int i = 0; i < width * height * 4; i += 4) {    send_buffer[k] = buf[i];    if (!is_spy) {      send_depth[k] = depth_buffer[k];    }    k++;  }    MPI_Request requests[2];  MPI_Status statuses[2];  int count = 0;  MPI_Isend(send_buffer, buf_size, MPI_BYTE, 0, IMAGE_TAG, MPI_COMM_WORLD,	    &requests[count++]);  if (!is_spy) {    MPI_Isend(send_depth, buf_size, MPI_FLOAT, 0, IMAGE_TAG, MPI_COMM_WORLD,	      &requests[count++]);  }   MPI_Waitall(count, requests, statuses);#endif}

⌨️ 快捷键说明

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