/** * Builds a directory of the object names. * * Allocate and initialize information for this instance of an RT * model database. * * Returns - * (struct rt_i *) Success * RTI_NULL Fatal Error */ struct rt_i * rt_dirbuild(const char *filename, char *buf, int len) { register struct rt_i *rtip; register struct db_i *dbip; /* Database instance ptr */ if (rt_uniresource.re_magic == 0) rt_init_resource(&rt_uniresource, 0, NULL); if ((dbip = db_open(filename, DB_OPEN_READONLY)) == DBI_NULL) return RTI_NULL; /* FAIL */ RT_CK_DBI(dbip); if (db_dirbuild(dbip) < 0) { db_close(dbip); return RTI_NULL; /* FAIL */ } rtip = rt_new_rti(dbip); /* clones dbip */ db_close(dbip); /* releases original dbip */ if (buf != (char *)NULL) bu_strlcpy(buf, dbip->dbi_title, len); return rtip; /* OK */ }
/** * Called at the start of a run. * * Returns 1 if framebuffer should be opened, else 0. */ int view_init(struct application *ap, char *file, char *UNUSED(obj), int minus_o, int minus_F) { /* * Allocate a scanline for each processor. */ ap->a_hit = rayhit; ap->a_miss = raymiss; ap->a_onehit = 1; /* * Does the user want occlusion checking? * * If so, load and prep. */ if (bu_vls_strlen(&occlusion_objects) != 0) { struct db_i *dbip; int nObjs; const char **objs; int i; bu_log("rtedge: loading occlusion geometry from %s.\n", file); if (Tcl_SplitList(NULL, bu_vls_addr(&occlusion_objects), &nObjs, &objs) == TCL_ERROR) { bu_log("rtedge: occlusion list = %s\n", bu_vls_addr(&occlusion_objects)); bu_exit(EXIT_FAILURE, "rtedge: could not parse occlusion objects list.\n"); } for (i=0; i<nObjs; ++i) { bu_log("rtedge: occlusion object %d = %s\n", i, objs[i]); } if ((dbip = db_open(file, DB_OPEN_READONLY)) == DBI_NULL) bu_exit(EXIT_FAILURE, "rtedge: could not open geometry database file %s.\n", file); RT_CK_DBI(dbip); #if 0 /* FIXME: calling this when db_open()'s mapped file doesn't * fail will cause duplicate directory entries. need to make * sure db_dirbuild rebuilds from scratch or only updates * existing entries when they exist. */ if (db_dirbuild(dbip) < 0) bu_exit(EXIT_FAILURE, "rtedge: could not read database.\n"); #endif occlusion_rtip = rt_new_rti(dbip); /* clones dbip */ for (i=0; i < MAX_PSW; i++) { rt_init_resource(&occlusion_resources[i], i, occlusion_rtip); bn_rand_init(occlusion_resources[i].re_randptr, i); } db_close(dbip); /* releases original dbip */ for (i=0; i<nObjs; ++i) if (rt_gettree(occlusion_rtip, objs[i]) < 0) bu_log("rtedge: gettree failed for %s\n", objs[i]); else bu_log("rtedge: got tree for object %d = %s\n", i, objs[i]); bu_log("rtedge: occlusion rt_gettrees done.\n"); rt_prep(occlusion_rtip); bu_log("rtedge: occlusion prep done.\n"); /* * Create a set of application structures for the occlusion * geometry. Need one per cpu, the upper half does the per- * thread allocation in worker, but that's off limits. */ occlusion_apps = (struct application **)bu_calloc(npsw, sizeof(struct application *), "occlusion application structure array"); for (i=0; i<npsw; ++i) { BU_ALLOC(occlusion_apps[i], struct application); RT_APPLICATION_INIT(occlusion_apps[i]); occlusion_apps[i]->a_rt_i = occlusion_rtip; occlusion_apps[i]->a_resource = (struct resource *)BU_PTBL_GET(&occlusion_rtip->rti_resources, i); occlusion_apps[i]->a_onehit = 1; occlusion_apps[i]->a_hit = occlusion_hit; occlusion_apps[i]->a_miss = occlusion_miss; if (rpt_overlap) occlusion_apps[i]->a_logoverlap = (void (*)(struct application *, const struct partition *, const struct bu_ptbl *, const struct partition *))NULL; else occlusion_apps[i]->a_logoverlap = rt_silent_logoverlap; } bu_log("rtedge: will perform occlusion testing.\n"); /* * If an inclusion mode has not been specified, use the default. */ if (occlusion_mode == OCCLUSION_MODE_NONE) { occlusion_mode = OCCLUSION_MODE_DEFAULT; bu_log("rtedge: occlusion mode = %d\n", occlusion_mode); } if ((occlusion_mode != OCCLUSION_MODE_NONE) && (overlay == OVERLAY_MODE_UNSET)) { bu_log("rtedge: automagically activating overlay mode.\n"); overlay = OVERLAY_MODE_DOIT; } } if (occlusion_mode != OCCLUSION_MODE_NONE && bu_vls_strlen(&occlusion_objects) == 0) { bu_exit(EXIT_FAILURE, "rtedge: occlusion mode set, but no objects were specified.\n"); } /* if non-default/inverted background was requested, swap the * foreground and background colors. */ if (!default_background) { color tmp; tmp[RED] = fgcolor[RED]; tmp[GRN] = fgcolor[GRN]; tmp[BLU] = fgcolor[BLU]; fgcolor[RED] = bgcolor[RED]; fgcolor[GRN] = bgcolor[GRN]; fgcolor[BLU] = bgcolor[BLU]; bgcolor[RED] = tmp[RED]; bgcolor[GRN] = tmp[GRN]; bgcolor[BLU] = tmp[BLU]; } if (minus_o && (overlay || blend)) { /* * Output is to a file stream. Do not allow parallel * processing since we can't seek to the rows. */ RTG.rtg_parallel = 0; bu_log("view_init: deactivating parallelism due to -o option.\n"); /* * The overlay and blend cannot be used in -o mode. Note that * the overlay directive takes precedence, they can't be used * together. */ overlay = 0; blend = 0; bu_log("view_init: deactivating overlay and blending due to -o option.\n"); } if (overlay) bu_log("view_init: will perform simple overlay.\n"); else if (blend) bu_log("view_init: will perform blending.\n"); return minus_F || (!minus_o && !minus_F); /* we need a framebuffer */ }
int ged_voxelize(struct ged *gedp, int argc, const char *argv[]) { struct rt_i *rtip; static const char *usage = "[-s \"dx dy dz\"] [-d n] [-t f] new_obj old_obj [old_obj2 old_obj3 ...]"; fastf_t sizeVoxel[3]; int levelOfDetail; genptr_t callBackData; struct voxelizeData voxDat; int c; /* intentionally double for scan */ double threshold; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialization */ bu_vls_trunc(gedp->ged_result_str, 0); /* incorrect arguments */ if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } sizeVoxel[0] = 1.0; sizeVoxel[1] = 1.0; sizeVoxel[2] = 1.0; levelOfDetail = 1; threshold = 0.5; bu_optind = 1; while ((c = bu_getopt(argc, (char * const *)argv, (const char *)"s:d:t:")) != -1) { double scan[3]; switch (c) { case 's': if (sscanf(bu_optarg, "%lf %lf %lf", &scan[0], &scan[1], &scan[2]) != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } else { /* convert from double to fastf_t */ VMOVE(sizeVoxel, scan); sizeVoxel[0] = sizeVoxel[0] * gedp->ged_wdbp->dbip->dbi_local2base; sizeVoxel[1] = sizeVoxel[1] * gedp->ged_wdbp->dbip->dbi_local2base; sizeVoxel[2] = sizeVoxel[2] * gedp->ged_wdbp->dbip->dbi_local2base; } break; case 'd': if (sscanf(bu_optarg, "%d", &levelOfDetail) != 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } break; case 't': if(sscanf(bu_optarg, "%lf", &threshold) != 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } break; default: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } } argc -= bu_optind; argv += bu_optind; if (argc < 2) { bu_vls_printf(gedp->ged_result_str, "error: missing argument(s)\n"); return GED_ERROR; } voxDat.newname = (char *)argv[0]; argc--; argv++; if (db_lookup(gedp->ged_wdbp->dbip, voxDat.newname, LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "error: solid '%s' already exists, aborting\n", voxDat.newname); return GED_ERROR; } rtip = rt_new_rti(gedp->ged_wdbp->dbip); rtip->useair = 1; /* Walk trees. Here we identify any object trees in the database * that the user wants included in the ray trace. */ while(argc > 0) { if(rt_gettree(rtip,argv[0]) < 0) { bu_vls_printf(gedp->ged_result_str, "error: object '%s' does not exists, aborting\n", argv[1]); return GED_ERROR; } argc--; argv++; } voxDat.sizeVoxel[0] = sizeVoxel[0]; voxDat.sizeVoxel[1] = sizeVoxel[1]; voxDat.sizeVoxel[2] = sizeVoxel[2]; voxDat.threshold = threshold; voxDat.wdbp = gedp->ged_wdbp; voxDat.bbMin = rtip->mdl_min; BU_LIST_INIT(&voxDat.content.l); callBackData = (void*)(&voxDat); /* voxelize function is called here with rtip(ray trace instance), userParameter and create_boxes function */ voxelize(rtip, sizeVoxel, levelOfDetail, create_boxes, callBackData); mk_comb(gedp->ged_wdbp, voxDat.newname, &voxDat.content.l, 1, "plastic", "sh=4 sp=0.5 di=0.5 re=0.1", 0, 1000, 0, 0, 100, 0, 0, 0); mk_freemembers(&voxDat.content.l); rt_free_rti(rtip); return GED_OK; }
/** * raytrace an object optionally storing the rays */ void fit_rt(char *obj, struct db_i *db, struct fitness_state *fstate) { int i; fastf_t diff[3], tmp; fastf_t min[3], max[3]; /* * uncomment to calculate # of nodes * and use in fitness calculation * struct directory *dp struct rt_db_internal in; int n_leaves; if (!rt_db_lookup_internal(db, obj, &dp, &in, LOOKUP_NOISY, &rt_uniresource)) bu_exit(EXIT_FAILURE, "Failed to read object to raytrace"); n_leaves = db_count_tree_nodes(((struct rt_comb_internal *)in.idb_ptr)->tree, 0); rt_db_free_internal(&in); */ fstate->rtip = rt_new_rti(db); fstate->row = 0; if (rt_gettree(fstate->rtip, obj) < 0) bu_exit(EXIT_FAILURE, "rt_gettree failed"); /* for (i = 0; i < fstate->max_cpus; i++) { rt_init_resource(&fstate->resource[i], i, fstate->rtip); bn_rand_init(fstate->resource[i].re_randptr, i); } */ /* stash bounding box and if comparing to source * calculate the difference between the bounding boxes */ if (fstate->capture) { VMOVE(fstate->min, fstate->rtip->mdl_min); VMOVE(fstate->max, fstate->rtip->mdl_max); /* z_max = fstate->rtip->mdl_max[Z];*/ } /*else { * instead of storing min and max, just compute * what we're going to need later for (i = 0; i < 3; i++) { diff[i] = 0; if (fstate->min[i] > fstate->rtip->mdl_min[i]) diff[i] += fstate->min[i] - fstate->rtip->mdl_min[i]; if (fstate->max[i] < fstate->rtip->mdl_max[i]) diff[i] += fstate->rtip->mdl_max[i] - fstate->max[i]; if (fstate->min[i] < fstate->rtip->mdl_min[i]) min[i] = fstate->min[i]; else min[i] = fstate->rtip->mdl_min[i]; if (fstate->max[i] > fstate->rtip->mdl_max[i]) max[i] = fstate->max[i]; else max[i] = fstate->rtip->mdl_max[i]; diff[i] = max[i] - min[i]; } fastf_t tmp = (diff[X]/fstate->gridSpacing[X]-1) * (diff[Y]/fstate->gridSpacing[Y] - 1); fstate->volume = (fstate->a_len + (max[Z] - fstate->max[Z])) * tmp; } */ /*rt_prep_parallel(fstate->rtip, fstate->ncpu)o;*/ rt_prep(fstate->rtip); if (fstate->capture) { /* Store bounding box of voxel data -- fixed bounding box for fitness */ fstate->gridSpacing[X] = (fstate->rtip->mdl_max[X] - fstate->rtip->mdl_min[X]) / (fstate->res[X] + 1); fstate->gridSpacing[Y] = (fstate->rtip->mdl_max[Y] - fstate->rtip->mdl_min[Y]) / (fstate->res[Y] + 1); fstate->a_len = fstate->max[Z]-fstate->rtip->mdl_min[Z]; /* maximum ray length (z-dist of bounding box) */ fstate->volume = fstate->a_len * fstate->res[X] * fstate->res[Y]; /* volume of bounding box */ /* allocate storage for saved rays */ fstate->ray = (struct part **)bu_malloc(sizeof(struct part *) * fstate->res[X] * fstate->res[Y], "ray"); VMOVE(fstate->min, fstate->rtip->mdl_min); VMOVE(fstate->max, fstate->rtip->mdl_max); } else { /* instead of storing min and max, just compute * what we're going to need later */ for (i = 0; i < 3; i++) { diff[i] = 0; if (fstate->min[i] < fstate->rtip->mdl_min[i]) min[i] = fstate->min[i]; else min[i] = fstate->rtip->mdl_min[i]; if (fstate->max[i] > fstate->rtip->mdl_max[i]) max[i] = fstate->max[i]; else max[i] = fstate->rtip->mdl_max[i]; diff[i] = max[i] - min[i]; } tmp = (diff[X]/fstate->gridSpacing[X]-1) * (diff[Y]/fstate->gridSpacing[Y] - 1); fstate->volume = (fstate->a_len + (max[Z] - fstate->max[Z])) * tmp; /* scale fitness to the unon of the sources and individual's bounding boxes */ /* FIXME: sloppy fastf_t tmp = (diff[X]/fstate->gridSpacing[X]-1) * (diff[Y]/fstate->gridSpacing[Y] * diff[Z] - 1); if (tmp < 0) tmp = 0;*/ } rt_worker(0, (void *)fstate); /*bu_parallel(rt_worker, fstate->ncpu, (void *)fstate);*/ /* normalize fitness if we aren't just saving the source */ if (!fstate->capture) { fstate->fitness = fstate->same / (fstate->volume ); /* reset counters for future comparisons */ fstate->diff = fstate->same = 0.0; } /* clean up resources and rtip */ /* for (i = 0; i < fstate->max_cpus; i++) rt_clean_resource(fstate->rtip, &fstate->resource[i]); */ rt_free_rti(fstate->rtip); }
union tree * gcv_region_end_mc(struct db_tree_state *tsp, const struct db_full_path *pathp, union tree *curtree, void *client_data) { union tree *tp = NULL; struct model *m = NULL; struct nmgregion *r = NULL; struct shell *s = NULL; struct bu_list vhead; int empty_region = 0; int empty_model = 0; int NMG_debug_state = 0; int count = 0; void (*write_region)(struct nmgregion *, const struct db_full_path *, int, int, float [3]); if (!tsp || !pathp || !client_data) { bu_log("INTERNAL ERROR: gcv_region_end_mc missing parameters\n"); return TREE_NULL; } write_region = ((struct gcv_data *)client_data)->func; if (!write_region) { bu_log("INTERNAL ERROR: gcv_region_end missing conversion callback function\n"); return TREE_NULL; } RT_CK_FULL_PATH(pathp); RT_CK_TREE(curtree); RT_CK_TESS_TOL(tsp->ts_ttol); BN_CK_TOL(tsp->ts_tol); NMG_CK_MODEL(*tsp->ts_m); BU_LIST_INIT(&vhead); /* if (curtree->tr_op == OP_NOP) return 0; */ /* get a copy to play with as the parameters might get clobbered * by a longjmp. FIXME: db_dup_subtree() doesn't create real copies */ tp = db_dup_subtree(curtree, &rt_uniresource); /* FIXME: we can't free curtree until we get a "real" copy form * db_dup_subtree(). right now we get a fake copy just so we can * keep the compiler quiet about clobbering curtree during longjmp */ /* db_free_tree(curtree, &rt_uniresource); */ /* Sometimes the NMG library adds debugging bits when it detects * an internal error, before bombing. Stash. */ NMG_debug_state = RTG.NMG_debug; m = nmg_mmr(); r = nmg_mrsv(m); s = BU_LIST_FIRST(shell, &r->s_hd); if (tsp->ts_rtip == NULL) tsp->ts_rtip = rt_new_rti(tsp->ts_dbip); count += nmg_mc_evaluate (s, tsp->ts_rtip, pathp, tsp->ts_ttol, tsp->ts_tol); /* empty region? */ if (count == 0) { bu_log("Region %s appears to be empty.\n", db_path_to_string(pathp)); return TREE_NULL; } /* bu_log("Target is shot, %d triangles seen.\n", count); bu_log("Fusing\n"); fflush(stdout); nmg_model_fuse(m, tsp->ts_tol); bu_log("Done\n"); fflush(stdout); */ /* Kill cracks */ while (BU_LIST_NOT_HEAD(&s->l, &r->s_hd)) { struct shell *next_s; next_s = BU_LIST_PNEXT(shell, &s->l); if (nmg_kill_cracks(s)) { if (nmg_ks(s)) { empty_region = 1; break; } } /* nmg_shell_coplanar_face_merge(s, tsp->ts_tol, 42); */ s = next_s; } if (empty_region) return _gcv_cleanup(NMG_debug_state, tp); /* kill zero length edgeuses */ empty_model = nmg_kill_zero_length_edgeuses(*tsp->ts_m); if (empty_model) return _gcv_cleanup(NMG_debug_state, tp); if (BU_SETJUMP) { /* Error, bail out */ char *sofar; /* Relinquish bomb protection */ BU_UNSETJUMP; sofar = db_path_to_string(pathp); bu_log("FAILED in triangulator: %s\n", sofar); bu_free((char *)sofar, "sofar"); /* Release any intersector 2d tables */ nmg_isect2d_final_cleanup(); /* Get rid of (m)any other intermediate structures */ if ((*tsp->ts_m)->magic == NMG_MODEL_MAGIC) nmg_km(*tsp->ts_m); else bu_log("WARNING: tsp->ts_m pointer corrupted, ignoring it.\n"); /* Now, make a new, clean model structure for next pass. */ *tsp->ts_m = nmg_mm(); nmg_kr(r); return _gcv_cleanup(NMG_debug_state, tp); } else { /* Write the region out */ write_region(r, pathp, tsp->ts_regionid, tsp->ts_gmater, tsp->ts_mater.ma_color); } BU_UNSETJUMP; /* Relinquish bomb protection */ nmg_kr(r); return _gcv_cleanup(NMG_debug_state, tp); }
/* 0 = no difference within tolerance, 1 = difference >= tolerance */ int analyze_raydiff(/* TODO - decide what to return. Probably some sort of left, common, right segment sets. See what rtcheck does... */ struct db_i *dbip, const char *obj1, const char *obj2, struct bn_tol *tol) { int ret; int count = 0; struct rt_i *rtip; int ncpus = bu_avail_cpus(); point_t min, mid, max; struct rt_pattern_data *xdata, *ydata, *zdata; fastf_t *rays; struct raydiff_container *state; if (!dbip || !obj1 || !obj2 || !tol) return 0; rtip = rt_new_rti(dbip); if (rt_gettree(rtip, obj1) < 0) return -1; if (rt_gettree(rtip, obj2) < 0) return -1; rt_prep_parallel(rtip, 1); /* Now we've got the bounding box - set up the grids */ VMOVE(min, rtip->mdl_min); VMOVE(max, rtip->mdl_max); VSET(mid, (max[0] - min[0])/2, (max[1] - min[1])/2, (max[2] - min[2])/2); BU_GET(xdata, struct rt_pattern_data); VSET(xdata->center_pt, min[0] - 0.1 * min[0], mid[1], mid[2]); VSET(xdata->center_dir, 1, 0, 0); xdata->vn = 2; xdata->pn = 2; xdata->n_vec = (vect_t *)bu_calloc(xdata->vn + 1, sizeof(vect_t), "vects array"); xdata->n_p = (fastf_t *)bu_calloc(xdata->pn + 1, sizeof(fastf_t), "params array"); xdata->n_p[0] = 50; /* TODO - get tolerances from caller */ xdata->n_p[1] = 50; VSET(xdata->n_vec[0], 0, max[1], 0); VSET(xdata->n_vec[1], 0, 0, max[2]); ret = rt_pattern(xdata, RT_PATTERN_RECT_ORTHOGRID); bu_free(xdata->n_vec, "x vec inputs"); bu_free(xdata->n_p, "x p inputs"); if (ret < 0) return -1; BU_GET(ydata, struct rt_pattern_data); VSET(ydata->center_pt, mid[0], min[1] - 0.1 * min[1], mid[2]); VSET(ydata->center_dir, 0, 1, 0); ydata->vn = 2; ydata->pn = 2; ydata->n_vec = (vect_t *)bu_calloc(ydata->vn + 1, sizeof(vect_t), "vects array"); ydata->n_p = (fastf_t *)bu_calloc(ydata->pn + 1, sizeof(fastf_t), "params array"); ydata->n_p[0] = 50; /* TODO - get tolerances from caller */ ydata->n_p[1] = 50; VSET(ydata->n_vec[0], max[0], 0, 0); VSET(ydata->n_vec[1], 0, 0, max[2]); ret = rt_pattern(ydata, RT_PATTERN_RECT_ORTHOGRID); bu_free(ydata->n_vec, "y vec inputs"); bu_free(ydata->n_p, "y p inputs"); if (ret < 0) return -1; BU_GET(zdata, struct rt_pattern_data); VSET(zdata->center_pt, mid[0], mid[1], min[2] - 0.1 * min[2]); VSET(zdata->center_dir, 0, 0, 1); zdata->vn = 2; zdata->pn = 2; zdata->n_vec = (vect_t *)bu_calloc(zdata->vn + 1, sizeof(vect_t), "vects array"); zdata->n_p = (fastf_t *)bu_calloc(zdata->pn + 1, sizeof(fastf_t), "params array"); zdata->n_p[0] = 50; /* TODO - get tolerances from caller */ zdata->n_p[1] = 50; VSET(zdata->n_vec[0], max[0], 0, 0); VSET(zdata->n_vec[1], 0, max[1], 0); ret = rt_pattern(zdata, RT_PATTERN_RECT_ORTHOGRID); bu_free(zdata->n_vec, "x vec inputs"); bu_free(zdata->n_p, "x p inputs"); if (ret < 0) return -1; /* Consolidate the grids into a single ray array */ { size_t i, j; rays = (fastf_t *)bu_calloc((xdata->ray_cnt + ydata->ray_cnt + zdata->ray_cnt + 1) * 6, sizeof(fastf_t), "rays"); count = 0; for (i = 0; i < xdata->ray_cnt; i++) { for (j = 0; j < 6; j++) { rays[6*count+j] = xdata->rays[6*i + j]; } count++; } for (i = 0; i < ydata->ray_cnt; i++) { for (j = 0; j < 6; j++) { rays[6*count+j] = ydata->rays[6*i + j]; } count++; } for (i = 0; i < zdata->ray_cnt; i++) { for (j = 0; j < 6; j++) { rays[6*count+j] = zdata->rays[6*i+j]; } count++; } } bu_free(xdata->rays, "x rays"); bu_free(ydata->rays, "y rays"); bu_free(zdata->rays, "z rays"); BU_PUT(xdata, struct rt_pattern_data); BU_PUT(ydata, struct rt_pattern_data); BU_PUT(zdata, struct rt_pattern_data); bu_log("ray cnt: %d\n", count); { int i, j; ncpus = 2; state = (struct raydiff_container *)bu_calloc(ncpus+1, sizeof(struct raydiff_container), "resources"); for (i = 0; i < ncpus+1; i++) { state[i].rtip = rtip; state[i].tol = 0.5; state[i].ncpus = ncpus; state[i].left_name = bu_strdup(obj1); state[i].right_name = bu_strdup(obj2); BU_GET(state[i].resp, struct resource); rt_init_resource(state[i].resp, i, state->rtip); BU_GET(state[i].left, struct bu_ptbl); bu_ptbl_init(state[i].left, 64, "left solid hits"); BU_GET(state[i].both, struct bu_ptbl); bu_ptbl_init(state[i].both, 64, "hits on both solids"); BU_GET(state[i].right, struct bu_ptbl); bu_ptbl_init(state[i].right, 64, "right solid hits"); state[i].rays_cnt = count; state[i].rays = rays; } bu_parallel(raydiff_gen_worker, ncpus, (void *)state); /* Collect and print all of the results */ for (i = 0; i < ncpus+1; i++) { for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j); bu_log("Result: LEFT diff vol (%s): %g %g %g -> %g %g %g\n", obj1, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt)); } for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j); bu_log("Result: BOTH): %g %g %g -> %g %g %g\n", V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt)); } for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j); bu_log("Result: RIGHT diff vol (%s): %g %g %g -> %g %g %g\n", obj2, V3ARGS(dseg->in_pt), V3ARGS(dseg->out_pt)); } } /* Free results */ for (i = 0; i < ncpus+1; i++) { for (j = 0; j < (int)BU_PTBL_LEN(state[i].left); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].left, j); BU_PUT(dseg, struct diff_seg); } bu_ptbl_free(state[i].left); BU_PUT(state[i].left, struct diff_seg); for (j = 0; j < (int)BU_PTBL_LEN(state[i].both); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].both, j); BU_PUT(dseg, struct diff_seg); } bu_ptbl_free(state[i].both); BU_PUT(state[i].both, struct diff_seg); for (j = 0; j < (int)BU_PTBL_LEN(state[i].right); j++) { struct diff_seg *dseg = (struct diff_seg *)BU_PTBL_GET(state[i].right, j); BU_PUT(dseg, struct diff_seg); } bu_ptbl_free(state[i].right); BU_PUT(state[i].right, struct diff_seg); bu_free((void *)state[i].left_name, "left name"); bu_free((void *)state[i].right_name, "right name"); BU_PUT(state[i].resp, struct resource); } bu_free(state, "free state containers"); } return 0; }
HIDDEN int _rt_generate_points(int **faces, int *num_faces, point_t **points, int *num_pnts, struct bu_ptbl *hit_pnts, struct db_i *dbip, const char *obj, fastf_t delta) { int i, dir1, j; point_t min, max; int ncpus = bu_avail_cpus(); struct rt_parallel_container *state; struct bu_vls vlsstr; bu_vls_init(&vlsstr); if (!hit_pnts || !dbip || !obj) return -1; BU_GET(state, struct rt_parallel_container); state->rtip = rt_new_rti(dbip); state->delta = delta; if (rt_gettree(state->rtip, obj) < 0) return -1; rt_prep_parallel(state->rtip, 1); state->resp = (struct resource *)bu_calloc(ncpus+1, sizeof(struct resource), "resources"); for (i = 0; i < ncpus+1; i++) { rt_init_resource(&(state->resp[i]), i, state->rtip); } state->npts = (struct rt_point_container *)bu_calloc(ncpus+1, sizeof(struct rt_point_container), "point container arrays"); int n[3]; VMOVE(min, state->rtip->mdl_min); VMOVE(max, state->rtip->mdl_max); for (i = 0; i < 3; i++) { n[i] = (int)((max[i] - min[i])/state->delta) + 2; if(n[i] < 12) n[i] = 12; } int total = 0; for (i = 0; i < 3; i++) total += n[i]*n[(i+1)%3]; if (total > 1e6) total = 1e6; for (i = 0; i < ncpus+1; i++) { state->npts[i].pts = (struct npoints *)bu_calloc(total, sizeof(struct npoints), "npoints arrays"); state->npts[i].pnt_cnt = 0; state->npts[i].capacity = total; } for (dir1 = 0; dir1 < 3; dir1++) { state->ray_dir = dir1; state->ncpus = ncpus; state->delta = delta; bu_parallel(_rt_gen_worker, ncpus, (void *)state); } int out_cnt = 0; for (i = 0; i < ncpus+1; i++) { bu_log("%d, pnt_cnt: %d\n", i, state->npts[i].pnt_cnt); for (j = 0; j < state->npts[i].pnt_cnt; j++) { struct npoints *npt = &(state->npts[i].pts[j]); if (npt->in.is_set) out_cnt++; if (npt->out.is_set) out_cnt++; } } struct rt_vert **rt_verts = (struct rt_vert **)bu_calloc(out_cnt, sizeof(struct rt_vert *), "output array"); int curr_ind = 0; for (i = 0; i < ncpus+1; i++) { for (j = 0; j < state->npts[i].pnt_cnt; j++) { struct npoints *npt = &(state->npts[i].pts[j]); if (npt->in.is_set) { rt_verts[curr_ind] = &(npt->in); curr_ind++; } if (npt->out.is_set) { rt_verts[curr_ind] = &(npt->out); curr_ind++; } } } struct spr_options opts = SPR_OPTIONS_DEFAULT_INIT; (void)spr_surface_build(faces, num_faces, (double **)points, num_pnts, (const struct cvertex **)rt_verts, out_cnt, &opts); return 0; }