void adrt_slave_work(tienet_buffer_t *work, tienet_buffer_t *result) { TIE_3 pos, foc; unsigned char rm, op; uint32_t ind, wlen; uint16_t wid; /* Length of work data */ wlen = work->ind; ind = 0; /* Get work type */ TCOPY(uint8_t, work->data, ind, &op, 0); ind += 1; /* Workspace ID */ TCOPY(uint16_t, work->data, ind, &wid, 0); ind += 2; /* This will get improved later with caching */ TIENET_BUFFER_SIZE((*result), 3); /* Copy op and wid, 3 bytes */ memcpy(result->data, &work->data[0], 3); result->ind = ind; switch (op) { case ADRT_WORK_INIT: { render_camera_init (&adrt_workspace_list[wid].camera, adrt_slave_threads); if ( slave_load (&adrt_workspace_list[wid].tie, (void *)work->data, wlen-ind) != 0 ) bu_exit (1, "Failed to load geometry. Going into a flaming tailspin\n"); tie_prep (&adrt_workspace_list[wid].tie); render_camera_prep (&adrt_workspace_list[wid].camera); printf ("ready.\n"); result->ind = 0; /* Mark the workspace as active so it can be cleaned up when the time comes. */ adrt_workspace_list[wid].active = 1; } break; case ADRT_WORK_STATUS: { #ifdef HAVE_GETLOADAVG double loadavg = -1.0; getloadavg (&loadavg, 1); printf ("load average: %f\n", loadavg); #endif } break; case ADRT_WORK_SELECT: { uint8_t c; char string[255]; uint32_t n, i, num; ind = 1; /* ind is too far in for some reason, force it back to 1? */ /* reset */ TCOPY(uint8_t, work->data, ind, &c, 0); ind += 1; if (c) for (i = 0; i < slave_load_mesh_num; i++) slave_load_mesh_list[i].flags = 0; /* number of strings to match */ TCOPY(uint32_t, work->data, ind, &num, 0); ind += 4; for (i = 0; i < num; i++) { /* string length */ TCOPY(uint8_t, work->data, ind, &c, 0); /* this likes to break, 'num' is way too big. */ ind += 1; /* string */ memcpy(string, &work->data[ind], c); ind += c; /* set select flag */ for (n = 0; n < slave_load_mesh_num; n++) if (strstr(slave_load_mesh_list[n].name, string) || c == 1) slave_load_mesh_list[n].flags = (slave_load_mesh_list[n].flags & 0x1) | ((slave_load_mesh_list[n].flags & 0x2) ^ 0x2); } /* zero length result */ result->ind = 0; } break; case ADRT_WORK_SHOTLINE: { tie_ray_t ray; void *mesg; int dlen; mesg = NULL; /* coordinates */ TCOPY(TIE_3, work->data, ind, ray.pos.v, 0); ind += sizeof (TIE_3); TCOPY(TIE_3, work->data, ind, ray.dir.v, 0); ind += sizeof (TIE_3); /* Fire the shot */ ray.depth = 0; render_util_shotline_list (&adrt_workspace_list[wid].tie, &ray, &mesg, &dlen); /* Make room for shot data */ TIENET_BUFFER_SIZE((*result), result->ind + dlen + 2*sizeof (TIE_3)); memcpy(&result->data[result->ind], mesg, dlen); result->ind += dlen; TCOPY(TIE_3, &ray.pos, 0, result->data, result->ind); result->ind += sizeof (TIE_3); TCOPY(TIE_3, &ray.dir, 0, result->data, result->ind); result->ind += sizeof (TIE_3); free (mesg); } break; case ADRT_WORK_SPALL: { #if 0 tie_ray_t ray; tfloat angle; void *mesg; int dlen; mesg = NULL; /* position */ TCOPY(TIE_3, data, ind, &ray.pos, 0); ind += sizeof (TIE_3); /* direction */ TCOPY(TIE_3, data, ind, &ray.dir, 0); ind += sizeof (TIE_3); /* angle */ TCOPY(tfloat, data, ind, &angle, 0); ind += sizeof (tfloat); /* Fire the shot */ ray.depth = 0; render_util_spall_list(tie, &ray, angle, &mesg, &dlen); /* Make room for shot data */ *res_len = sizeof (common_work_t) + dlen; *res_buf = (void *)realloc(*res_buf, *res_len); ind = 0; memcpy(&((char *)*res_buf)[ind], mesg, dlen); free (mesg); #endif } break; case ADRT_WORK_FRAME_ATTR: { uint16_t image_w, image_h, image_format; /* Image Size */ TCOPY(uint16_t, work->data, ind, &image_w, 0); ind += 2; TCOPY(uint16_t, work->data, ind, &image_h, 0); ind += 2; TCOPY(uint16_t, work->data, ind, &image_format, 0); ind += 2; adrt_workspace_list[wid].camera.w = image_w; adrt_workspace_list[wid].camera.h = image_h; render_camera_prep (&adrt_workspace_list[wid].camera); result->ind = 0; } break; case ADRT_WORK_FRAME: { camera_tile_t tile; uint8_t type; tfloat fov; /* Camera type */ TCOPY(uint8_t, work->data, ind, &type, 0); ind += 1; /* Camera fov */ TCOPY(tfloat, work->data, ind, &fov, 0); ind += sizeof (tfloat); /* Camera position */ TCOPY(TIE_3, work->data, ind, &pos, 0); ind += sizeof (TIE_3); /* Camera Focus */ TCOPY(TIE_3, work->data, ind, &foc, 0); ind += sizeof (TIE_3); /* Update Rendering Method if it has Changed */ rm = work->data[ind]; ind += 1; if (rm != adrt_workspace_list[wid].camera.rm || ADRT_MESSAGE_MODE_CHANGEP(rm)) { rm = ADRT_MESSAGE_MODE(rm); adrt_workspace_list[wid].camera.render.free (&adrt_workspace_list[wid].camera.render); switch (rm) { case RENDER_METHOD_DEPTH: render_depth_init(&adrt_workspace_list[wid].camera.render, NULL); break; case RENDER_METHOD_COMPONENT: render_component_init(&adrt_workspace_list[wid].camera.render, NULL); break; case RENDER_METHOD_FLOS: { TIE_3 frag_pos; char buf[BUFSIZ]; /* Extract shot position and direction */ TCOPY(TIE_3, work->data, ind, &frag_pos, 0); snprintf(buf, BUFSIZ, "#(%f %f %f)", V3ARGS(frag_pos.v)); ind += sizeof (TIE_3); render_flos_init(&adrt_workspace_list[wid].camera.render, buf); } break; case RENDER_METHOD_GRID: render_grid_init(&adrt_workspace_list[wid].camera.render, NULL); break; case RENDER_METHOD_NORMAL: render_normal_init(&adrt_workspace_list[wid].camera.render, NULL); break; case RENDER_METHOD_PATH: render_path_init(&adrt_workspace_list[wid].camera.render, "12"); break; case RENDER_METHOD_PHONG: render_phong_init(&adrt_workspace_list[wid].camera.render, NULL); break; case RENDER_METHOD_CUT: render_cut_init(&adrt_workspace_list[wid].camera.render, (char *)work->data + ind); break; case RENDER_METHOD_SPALL: { TIE_3 shot_pos, shot_dir; tfloat angle; char buf[BUFSIZ]; /* Extract shot position and direction */ TCOPY(TIE_3, work->data, ind, &shot_pos, 0); ind += sizeof (TIE_3); TCOPY(TIE_3, work->data, ind, &shot_dir, 0); ind += sizeof (TIE_3); TCOPY(tfloat, work->data, ind, &angle, 0); ind += sizeof (tfloat); snprintf(buf, BUFSIZ, "(%g %g %g) (%g %g %g) %g", V3ARGS(shot_pos.v), V3ARGS(shot_dir.v), angle); render_spall_init (&adrt_workspace_list[wid].camera.render, buf); } break; default: break; } adrt_workspace_list[wid].camera.rm = rm; } /* The portion of the image to be rendered */ ind = work->ind - sizeof (camera_tile_t); TCOPY(camera_tile_t, work->data, ind, &tile, 0); ind += sizeof (camera_tile_t); /* Update camera if different frame */ if (tile.frame != adrt_workspace_list[wid].last_frame) { adrt_workspace_list[wid].camera.type = type; adrt_workspace_list[wid].camera.fov = fov; adrt_workspace_list[wid].camera.pos = pos; adrt_workspace_list[wid].camera.focus = foc; render_camera_prep (&adrt_workspace_list[wid].camera); } adrt_workspace_list[wid].last_frame = tile.frame; render_camera_render (&adrt_workspace_list[wid].camera, &adrt_workspace_list[wid].tie, &tile, result); } break; case ADRT_WORK_MINMAX: { TCOPY(TIE_3, &adrt_workspace_list[wid].tie.min, 0, result->data, result->ind); result->ind += sizeof (TIE_3); TCOPY(TIE_3, &adrt_workspace_list[wid].tie.max, 0, result->data, result->ind); result->ind += sizeof (TIE_3); } break; default: break; } #if 0 { struct timeval tv; static int adrt_slave_completed = 0; static time_t adrt_slave_startsec = 0; if (adrt_slave_startsec == 0) adrt_slave_startsec = time(NULL); gettimeofday(&tv, NULL); printf("\t[Work Units Completed: %.6d Rays: %.5d k/sec %lld]\n", ++adrt_slave_completed, (int) ((tfloat) adrt_workspace_list[wid].tie.rays_fired / (tfloat) (1000 * (tv.tv_sec - adrt_slave_startsec + 1))), adrt_workspace_list[wid].tie.rays_fired); fflush(stdout); } #endif return; }
int render_cut_init(render_t *render, const char *buf) { int i; render_cut_t *d; static TIE_3 list[6]; TIE_3 **tlist; vect_t up, ray_pos, ray_dir; fastf_t shot_len = 100, shot_width = .02; struct tie_id_s id; struct tie_ray_s ray; double step, f[6]; if(buf == NULL) return -1; sscanf(buf, "#(%lf %lf %lf) #(%lf %lf %lf)", f, f+1, f+2, f+3, f+3+1, f+3+2); VMOVE(ray_pos, f); VMOVE(ray_dir, f); VUNITIZE(ray_dir); shot_width = 0.01 * render->tie->radius; { vect_t v; VSUB2(v, ray_pos, render->tie->mid); shot_len = 2.0 * render->tie->radius + MAGNITUDE(v) - render->tie->radius;; } /* * fire through the entire geometry, marking each intersected mesh with * ADRT_MESH_HIT */ VMOVE(ray.pos, ray_pos); VMOVE(ray.dir, ray_dir); ray.depth = 0; tie_work(render->tie, &ray, &id, render_cut_hit_cutline, &step); /* prepare cut stuff */ tlist = (TIE_3 **)bu_malloc(sizeof(TIE_3 *) * 6, "cutting plane triangles"); render->work = render_cut_work; render->free = render_cut_free; BU_ALLOC(render->data, render_cut_t); d = (render_cut_t *)render->data; VMOVE(d->ray_pos, ray_pos); VMOVE(d->ray_dir, ray_dir); /* Calculate the normal to be used for the plane */ VSET(up, 0, 0, 1); VCROSS(d->plane, ray_dir, up); VUNITIZE(d->plane); /* Construct the plane */ d->plane[3] = -VDOT( d->plane, ray_pos); /* up is really new ray_pos */ /* generate the shtuff for the blue line */ tie_init(&d->tie, 2, TIE_KDTREE_FAST); /* Triangle 1 */ VSET(list[0].v, ray_pos[0], ray_pos[1], ray_pos[2] - shot_width); VSET(list[1].v, ray_pos[0] + shot_len*ray_dir[0], ray_pos[1] + shot_len*ray_dir[1], ray_pos[2] + shot_len*ray_dir[2] - shot_width); VSET(list[2].v, ray_pos[0] + shot_len*ray_dir[0], ray_pos[1] + shot_len*ray_dir[1], ray_pos[2] + shot_len*ray_dir[2] + shot_width); /* Triangle 2 */ VMOVE(list[3].v, ray_pos); list[3].v[2] -= shot_width; VSET(list[4].v, ray_pos[0] + shot_len*ray_dir[0], ray_pos[1] + shot_len*ray_dir[1], ray_pos[2] + shot_len*ray_dir[2] + shot_width); VMOVE(list[5].v, ray_pos); list[5].v[2] += shot_width; for(i=0;i<6;i++) tlist[i] = &list[i]; tie_push(&d->tie, tlist, 2, NULL, 0); tie_prep(&d->tie); bu_free(tlist, "cutting plane triangles"); return 0; }
int render_spall_init(render_t *render, const char *buf) { struct render_spall_s *d; vect_t *tri_list, *vec_list, normal, up; fastf_t plane[4], angle; int i; /* intentionally double for scan */ double ray_pos[3], ray_dir[3]; double scan; if (buf == NULL) return -1; render->work = render_spall_work; render->free = render_spall_free; bu_sscanf(buf, "(%lg %lg %lg) (%lg %lg %lg) %lg", &ray_pos[0], &ray_pos[1], &ray_pos[2], &ray_dir[0], &ray_dir[1], &ray_dir[2], &scan); angle = scan; /* double to fastf_t */ BU_ALLOC(render->data, struct render_spall_s); d = (struct render_spall_s *)render->data; VMOVE(d->ray_pos, ray_pos); VMOVE(d->ray_dir, ray_dir); tie_init(&d->tie, TESSELLATION, TIE_KDTREE_FAST); /* Calculate the normal to be used for the plane */ up[0] = 0; up[1] = 0; up[2] = 1; VCROSS(normal, ray_dir, up); VUNITIZE(normal); /* Construct the plane */ d->plane[0] = normal[0]; d->plane[1] = normal[1]; d->plane[2] = normal[2]; plane[3] = VDOT(normal, ray_pos); /* up is really new ray_pos */ d->plane[3] = -plane[3]; /******************/ /* The spall Cone */ /******************/ vec_list = (vect_t *)bu_malloc(sizeof(vect_t) * TESSELLATION, "vec_list"); tri_list = (vect_t *)bu_malloc(sizeof(vect_t) * TESSELLATION * 3, "tri_list"); render_util_spall_vec(d->ray_dir, angle, TESSELLATION, vec_list); /* triangles to approximate */ for (i = 0; i < TESSELLATION; i++) { VMOVE(tri_list[3*i+0], ray_pos); VSCALE(tri_list[3*i+1], vec_list[i], SPALL_LEN); VADD2(tri_list[3*i+1], tri_list[3*i+1], ray_pos); if (i == TESSELLATION - 1) { VSCALE(tri_list[3*i+2], vec_list[0], SPALL_LEN); VADD2(tri_list[3*i+2], tri_list[3*i+2], ray_pos); } else { VSCALE(tri_list[3*i+2], vec_list[i+1], SPALL_LEN); VADD2(tri_list[3*i+2], tri_list[3*i+2], ray_pos); } } /* tie_push(&d->tie, tri_list, TESSELLATION, NULL, 0); */ tie_prep(&d->tie); bu_free(vec_list, "vec_list"); bu_free(tri_list, "tri_list"); return 0; }
void bench(char* proj, int cache, int image) { struct sockaddr_in server; struct sockaddr_in client; struct hostent h; int i, res_len, client_socket; common_work_t work; void *res_buf; unsigned char *image24; clock_t ticks1, ticks2, ticks3; tfloat t; ticks1 = clock(); tienet_sem_init(&bench_net_sem, 0); printf("loading and prepping ...\n"); /* Camera with no threads */ util_camera_init(&camera, 1); /* Parse Env Data */ common_db_load(&db, proj); /* * Hack the environment settings to make it think there is no cache file * if the user is generating one, otherwise it never generates one */ if (cache) db.env.kdtree_cache_file[0] = 0; /* Read the data off disk and pack it */ app_size = common_pack(&db, &app_data, proj); /* Launch a networking thread to do ipc data streaming */ pthread_create(&bench_thread, NULL, bench_ipc, 0); /* Parse the data into memory for rendering */ /* create a socket */ if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "unable to create socket, exiting.\n"); exit(1); } /* Bind any available port number */ client.sin_family = AF_INET; client.sin_addr.s_addr = htonl(INADDR_ANY); client.sin_port = htons(0); if (bind(client_socket, (struct sockaddr *)&client, sizeof(client)) < 0) { fprintf(stderr, "unable to bind socket, exiting\n"); exit(1); } /* Establish ipc connection */ if (gethostbyname("localhost")) { h = gethostbyname("localhost")[0]; } else { fprintf(stderr, "unknown host: %s\n", "localhost"); exit(1); } server.sin_family = h.h_addrtype; memcpy((char *)&server.sin_addr.s_addr, h.h_addr_list[0], h.h_length); server.sin_port = htons(LOCAL_PORT); tienet_sem_wait(&bench_net_sem); if (connect(client_socket, (struct sockaddr *)&server, sizeof(server)) < 0) { fprintf(stderr, "cannot establish connection, exiting.\n"); exit(1); } /* stream and unpack the data */ common_unpack(&db, &tie, &camera, client_socket); tie_prep(&tie); /* Prep */ common_env_prep(&db.env); util_camera_prep(&camera, &db); /* Allocate memory for a frame */ bench_frame = malloc(4 * sizeof(tfloat) * db.env.img_w * db.env.img_h); if (!bench_frame) { perror("bench_frame"); exit(1); } memset(bench_frame, 0, 4 * sizeof(tfloat) * db.env.img_w * db.env.img_h); /* Render an image */ work.orig_x = 0; work.orig_y = 0; work.size_x = db.env.img_w; work.size_y = db.env.img_h; work.format = COMMON_BIT_DEPTH_24; printf("rendering ...\n"); res_buf = NULL; ticks2 = clock(); util_camera_render(&camera, &db, &tie, &work, sizeof(common_work_t), &res_buf, &res_len); ticks3 = clock(); printf("prep time: %.3f sec\n", (tfloat)(ticks2 - ticks1) / (tfloat)CLOCKS_PER_SEC); t = (tfloat)(ticks3 - ticks2) / (tfloat)CLOCKS_PER_SEC; printf("render time: %.3f sec\n", t); printf("rays / sec: %d\n", (int)((db.env.img_w * db.env.img_h) / t)); if (image) { image24 = &((unsigned char *)res_buf)[sizeof(common_work_t)]; util_image_save_ppm("dump.ppm", image24, db.env.img_w, db.env.img_h); } close(client_socket); util_camera_free(&camera); free(app_data); free(bench_frame); common_unpack_free(&db); if (cache) { void *kdcache; unsigned int size; FILE *fh; tie_kdtree_cache_free(&tie, &kdcache); memcpy(&size, kdcache, sizeof(unsigned int)); printf("saving kd-tree cache: %d bytes\n", size); fh = fopen("kdtree.cache", "wb"); fwrite(kdcache, size, 1, fh); fclose(fh); free(kdcache); } }