BrlCadInterface::BrlCadInterface(QString file_name, QString object_name) { m_Rtip = rt_dirbuild(qPrintable(file_name), m_IdBuf, sizeof(m_IdBuf)); if (m_Rtip == RTI_NULL) { EG_ERR_RETURN("Unable to open BRL-CAD database!"); } if (rt_gettree(m_Rtip, qPrintable(object_name)) < 0) { EG_ERR_RETURN("unable to access selected object"); } rt_prep_parallel(m_Rtip, 1); application ap = {0}; m_Ap = ap; m_Ap.a_rt_i = m_Rtip; setName("BRL-CAD interface"); m_ShootRayImplemented = true; //m_Ap.a_onehit = 1; }
/** * START HERE * * This is where it all begins. */ int main(int argc, char **argv) { /* Every application needs one of these. The "application" * structure carries information about how the ray-casting should * be performed. Defined in the raytrace.h header. */ struct application ap; /* The "raytrace instance" structure contains definitions for * librt which are specific to the particular model being * processed. One copy exists for each model. Defined in * the raytrace.h header and is returned by rt_dirbuild(). */ static struct rt_i *rtip; /* optional parameter to rt_dirbuild() what can be used to capture * a title if the geometry database has one set. */ char title[1024] = {0}; /* Check for command-line arguments. Make sure we have at least a * geometry file and one geometry object on the command line. */ if (argc < 3) { bu_exit(1, "Usage: %s model.g objects...\n", argv[0]); } /* Load the specified geometry database (i.e., a ".g" file). * rt_dirbuild() returns an "instance" pointer which describes the * database to be raytraced. It also gives you back the title * string if you provide a buffer. This builds a directory of the * geometry (i.e., a table of contents) in the file. */ rtip = rt_dirbuild(argv[1], title, sizeof(title)); if (rtip == RTI_NULL) { bu_exit(2, "Building the database directory for [%s] FAILED\n", argv[1]); } /* Display the geometry database title obtained during * rt_dirbuild if a title is set. */ if (title[0]) { bu_log("Title:\n%s\n", title); } /* Walk the geometry trees. Here you identify any objects in the * database that you want included in the ray trace by iterating * of the object names that were specified on the command-line. */ while (argc > 2) { if (rt_gettree(rtip, argv[2]) < 0) bu_log("Loading the geometry for [%s] FAILED\n", argv[2]); argc--; argv++; } /* This next call gets the database ready for ray tracing. This * causes some values to be precomputed, sets up space * partitioning, computes boudning volumes, etc. */ rt_prep_parallel(rtip, 1); /* initialize all values in application structure to zero */ RT_APPLICATION_INIT(&ap); /* your application uses the raytrace instance containing the * geometry we loaded. this describes what we're shooting at. */ ap.a_rt_i = rtip; /* stop at the first point of intersection or shoot all the way * through (defaults to 0 to shoot all the way through). */ ap.a_onehit = 0; /* Set the ray start point and direction rt_shootray() uses these * two to determine what ray to fire. In this case we simply * shoot down the z axis toward the origin from 10 meters away. * * It's worth nothing that librt assumes units of millimeters. * All geometry is stored as millimeters regardless of the units * set during editing. There are libbu routines for performing * unit conversions if desired. */ VSET(ap.a_ray.r_pt, 0.0, 0.0, 10000.0); VSET(ap.a_ray.r_dir, 0.0, 0.0, -1.0); /* Simple debug printing */ VPRINT("Pnt", ap.a_ray.r_pt); VPRINT("Dir", ap.a_ray.r_dir); /* This is what callback to perform on a hit. */ ap.a_hit = hit; /* This is what callback to perform on a miss. */ ap.a_miss = miss; /* Shoot the ray. */ (void)rt_shootray(&ap); /* A real application would probably set up another ray and fire * again or do something a lot more complex in the callbacks. */ return 0; }
/** * voxelize function takes raytrace instance and user parameters as inputs */ void voxelize(struct rt_i *rtip, fastf_t sizeVoxel[3], int levelOfDetail, void (*create_boxes)(void *callBackData, int x, int y, int z, const char *regionName, fastf_t percentageFill), void *callBackData) { struct rayInfo voxelHits; int numVoxel[3]; int yMin; int zMin; int i, j, k, rayNum; fastf_t *voxelArray; fastf_t rayTraceDistance; fastf_t effectiveDistance; /* get bounding box values etc. */ rt_prep_parallel(rtip, 1); /* calculate number of voxels in each dimension */ numVoxel[0] = (int)(((rtip->mdl_max)[0] - (rtip->mdl_min)[0])/sizeVoxel[0]) + 1; numVoxel[1] = (int)(((rtip->mdl_max)[1] - (rtip->mdl_min)[1])/sizeVoxel[1]) + 1; numVoxel[2] = (int)(((rtip->mdl_max)[2] - (rtip->mdl_min)[2])/sizeVoxel[2]) + 1; if (EQUAL(numVoxel[0] - 1, (((rtip->mdl_max)[0] - (rtip->mdl_min)[0])/sizeVoxel[0]))) numVoxel[0] -=1; if (EQUAL(numVoxel[1] - 1, (((rtip->mdl_max)[1] - (rtip->mdl_min)[1])/sizeVoxel[1]))) numVoxel[1] -=1; if (EQUAL(numVoxel[2] - 1, (((rtip->mdl_max)[2] - (rtip->mdl_min)[2])/sizeVoxel[2]))) numVoxel[2] -=1; voxelHits.sizeVoxel = sizeVoxel[0]; /* voxelArray stores the distance in path of ray inside a voxel which is filled * initialize with 0s */ voxelArray = (fastf_t *)bu_calloc(numVoxel[0], sizeof(fastf_t), "voxelize:voxelArray"); /* regionList holds the names of voxels inside the voxels * initialize with NULLs */ voxelHits.regionList = (struct voxelRegion *)bu_calloc(numVoxel[0], sizeof(struct voxelRegion), "voxelize:regionList"); /* minimum value of bounding box in Y and Z directions */ yMin = (int)((rtip->mdl_min)[1]); zMin = (int)((rtip->mdl_min)[2]); BU_ASSERT_LONG(levelOfDetail, >, 0); /* 1.0 / (levelOfDetail + 1) and effectiveDistance have to be used multiple times in the following loops */ rayTraceDistance = 1. / levelOfDetail; effectiveDistance = levelOfDetail * levelOfDetail * sizeVoxel[0]; /* start shooting */ for (i = 0; i < numVoxel[2]; ++i) { for (j = 0; j < numVoxel[1]; ++j) { struct application ap; RT_APPLICATION_INIT(&ap); ap.a_rt_i = rtip; ap.a_onehit = 0; VSET(ap.a_ray.r_dir, 1., 0., 0.); ap.a_hit = hit_voxelize; ap.a_miss = NULL; ap.a_uptr = &voxelHits; voxelHits.fillDistances = voxelArray; for (rayNum = 0; rayNum < levelOfDetail; ++rayNum) { for (k = 0; k < levelOfDetail; ++k) { /* ray is hit through evenly spaced points of the unit sized voxels */ VSET(ap.a_ray.r_pt, (rtip->mdl_min)[0] - 1., yMin + (j + (k + 0.5) * rayTraceDistance) * sizeVoxel[1], zMin + (i + (rayNum + 0.5) * rayTraceDistance) * sizeVoxel[2]); rt_shootray(&ap); } } /* output results via a call-back supplied by user*/ for (k = 0; k < numVoxel[0]; ++k) { if (voxelHits.regionList[k].regionName == NULL) /* an air voxel */ create_boxes(callBackData, k, j, i, NULL, 0.); else { struct voxelRegion *tmp = voxelHits.regionList + k; struct voxelRegion *old = tmp->nextRegion; create_boxes(callBackData, k, j, i, tmp->regionName, tmp->regionDistance / effectiveDistance); if (tmp->regionName != 0) bu_free(tmp->regionName, "voxelize:voxelRegion:regionName"); while (old != NULL) { tmp = old; create_boxes(callBackData, k, j, i, tmp->regionName, tmp->regionDistance / effectiveDistance); old = tmp->nextRegion; /* free the space allocated for new regions */ if (tmp->regionName != 0) bu_free(tmp->regionName, "voxelize:voxelRegion:regionName"); BU_FREE(tmp, struct voxelRegion); } } voxelArray[k] = 0.; voxelHits.regionList[k].regionName = NULL; voxelHits.regionList[k].nextRegion = NULL; voxelHits.regionList[k].regionDistance = 0.; } } } bu_free(voxelArray, "voxelize:voxelArray"); bu_free(voxelHits.regionList, "voxelize:regionList"); }
/* 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; }