📄 render.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 + -