//******************************************************************* // NAME constructor // // INPUTS // ti - pointer to a target // cpuID - thread ID // // DESCRIPTION // Construct the object. //******************************************************************* DbTracer::DbTracer(Interface::INativeGeometry *ti, int cpuID) : Interface::IGeometryTracer(ti) , m_cpuID(cpuID) { // set up the application object that will be used RT_APPLICATION_INIT(&m_ap); m_ap.a_rt_i = (struct rt_i *) ti->getGeometry(); m_ap.a_hit = hit_func; m_ap.a_resource = ((DbGeometry *) ti)->getResource(cpuID); m_ap.a_user = cpuID; }
/** * raytraces an object in parallel and stores or compares it to source */ void rt_worker(int UNUSED(cpu), void *g) { struct application ap; struct fitness_state *fstate = (struct fitness_state *)g; int u, v; RT_APPLICATION_INIT(&ap); ap.a_rt_i = fstate->rtip; if (fstate->capture) { ap.a_hit = capture_hit; ap.a_miss = capture_miss; } else { ap.a_hit = compare_hit; ap.a_miss = compare_miss; } ap.a_resource = &rt_uniresource;/*fstate->resource[cpu];*/ ap.a_ray.r_dir[X] = ap.a_ray.r_dir[Y] = 0.0; ap.a_ray.r_dir[Z] = 1.0; ap.a_uptr = (void *) g; u = -1; while ((v = get_next_row(fstate))) { for (u = 1; u <= fstate->res[X]; u++) { ap.a_ray.r_pt[X] = fstate->min[X] + u * fstate->gridSpacing[X]; ap.a_ray.r_pt[Y] = fstate->min[Y] + v * fstate->gridSpacing[Y]; ap.a_ray.r_pt[Z] = fstate->min[Z]; ap.a_user = (v-1)*(fstate->res[X]) + u-1; rt_shootray(&ap); } } }
HIDDEN void raydiff_gen_worker(int cpu, void *ptr) { struct application ap; struct raydiff_container *state = &(((struct raydiff_container *)ptr)[cpu]); fastf_t si, ei; int start_ind, end_ind, i; if (cpu == 0) { /* If we're serial, start at the beginning */ start_ind = 0; end_ind = state->rays_cnt - 1; } else { si = (fastf_t)(cpu - 1)/(fastf_t)state->ncpus * (fastf_t) state->rays_cnt; ei = (fastf_t)cpu/(fastf_t)state->ncpus * (fastf_t) state->rays_cnt - 1; start_ind = (int)si; end_ind = (int)ei; if (state->rays_cnt - end_ind < 3) end_ind = state->rays_cnt - 1; bu_log("start_ind (%d): %d\n", cpu, start_ind); bu_log("end_ind (%d): %d\n", cpu, end_ind); } RT_APPLICATION_INIT(&ap); ap.a_rt_i = state->rtip; ap.a_hit = raydiff_hit; ap.a_miss = raydiff_miss; ap.a_overlap = raydiff_overlap; ap.a_onehit = 0; ap.a_logoverlap = rt_silent_logoverlap; ap.a_resource = state->resp; ap.a_uptr = (void *)state; for (i = start_ind; i <= end_ind; i++) { VSET(ap.a_ray.r_pt, state->rays[6*i+0], state->rays[6*i+1], state->rays[6*i+2]); VSET(ap.a_ray.r_dir, state->rays[6*i+3], state->rays[6*i+4], state->rays[6*i+5]); rt_shootray(&ap); } }
/** * 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 handle_main_ray(struct application *ap, register struct partition *PartHeadp, struct seg *segp) { register struct partition *pp; register struct hit *hitp; /* which hit */ struct application a2; struct cell me; struct cell below; struct cell left; struct cell above; struct cell right; double intensity = 1.0; int edge = 0; int cpu; int oc = 1; RGBpixel col; RT_APPLICATION_INIT(&a2); memset(&me, 0, sizeof(struct cell)); memset(&below, 0, sizeof(struct cell)); memset(&left, 0, sizeof(struct cell)); cpu = ap->a_resource->re_cpu; if (PartHeadp == NULL || segp == NULL) { /* The main shotline missed. pack the application struct */ me.c_ishit = 0; me.c_dist = MISS_DIST; me.c_id = MISS_ID; me.c_region = 0; VSETALL(me.c_hit, MISS_DIST); VSETALL(me.c_normal, 0); VMOVE(me.c_rdir, ap->a_ray.r_dir); } else { pp = PartHeadp->pt_forw; hitp = pp->pt_inhit; /* * Stuff the information for this cell. */ me.c_ishit = 1; me.c_id = pp->pt_regionp->reg_regionid; me.c_dist = hitp->hit_dist; me.c_region = pp->pt_regionp; VMOVE(me.c_rdir, ap->a_ray.r_dir); VJOIN1(me.c_hit, ap->a_ray.r_pt, hitp->hit_dist, ap->a_ray.r_dir); RT_HIT_NORMAL(me.c_normal, hitp, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip); } /* * Now, fire a ray for both the cell below and if necessary, the * cell to the left. */ a2.a_hit = rayhit2; a2.a_miss = raymiss2; a2.a_onehit = 1; a2.a_rt_i = ap->a_rt_i; a2.a_resource = ap->a_resource; a2.a_logoverlap = ap->a_logoverlap; VSUB2(a2.a_ray.r_pt, ap->a_ray.r_pt, dy_model); /* below */ VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir); a2.a_uptr = (void *)&below; rt_shootray(&a2); if (ap->a_x == 0) { /* * For the first pixel in a scanline, we have to shoot to the * left. For each pixel afterword, we save the current cell * info to be used as the left side cell info for the * following pixel */ VSUB2(a2.a_ray.r_pt, ap->a_ray.r_pt, dx_model); /* left */ VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir); a2.a_uptr = (void *)&left; rt_shootray(&a2); } else { left.c_ishit = saved[cpu]->c_ishit; left.c_id = saved[cpu]->c_id; left.c_dist = saved[cpu]->c_dist; left.c_region = saved[cpu]->c_region; VMOVE(left.c_rdir, saved[cpu]->c_rdir); VMOVE(left.c_hit, saved[cpu]->c_hit); VMOVE(left.c_normal, saved[cpu]->c_normal); } if (both_sides) { VADD2(a2.a_ray.r_pt, ap->a_ray.r_pt, dy_model); /* above */ VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir); a2.a_uptr = (void *)&above; rt_shootray(&a2); VADD2(a2.a_ray.r_pt, ap->a_ray.r_pt, dx_model); /* right */ VMOVE(a2.a_ray.r_dir, ap->a_ray.r_dir); a2.a_uptr = (void *)&right; rt_shootray(&a2); } /* * Is this pixel an edge? */ if (both_sides) { edge = is_edge(&intensity, ap, &me, &left, &below, &right, &above); } else { edge = is_edge(&intensity, ap, &me, &left, &below, NULL, NULL); } /* * Does this pixel occlude the second geometry? Note that we must * check on edges as well since right side and top edges are * actually misses. */ if (occlusion_mode != OCCLUSION_MODE_NONE) if (me.c_ishit || edge) oc = occludes(ap, &me); /* * Perverse Pixel Painting Paradigm(tm) If a pixel should be * written to the fb, writeable is set. */ if (occlusion_mode == OCCLUSION_MODE_EDGES) writeable[cpu][ap->a_x] = (edge && oc); else if (occlusion_mode == OCCLUSION_MODE_HITS) writeable[cpu][ap->a_x] = ((me.c_ishit || edge) && oc); else if (occlusion_mode == OCCLUSION_MODE_DITHER) { if (edge && oc) writeable[cpu][ap->a_x] = 1; else if (me.c_ishit && oc) { /* * Dither mode. * * For occluding non-edges, only write every other pixel. */ if (oc == 1 && ((ap->a_x + ap->a_y) % 2) == 0) writeable[cpu][ap->a_x] = 1; else if (oc == 2) writeable[cpu][ap->a_x] = 1; else writeable[cpu][ap->a_x] = 0; } else { writeable[cpu][ap->a_x] = 0; } } else { if (edge) writeable[cpu][ap->a_x] = 1; else writeable[cpu][ap->a_x] = 0; } if (edge) { if (both_sides) { choose_color(col, intensity, &me, &left, &below, &right, &above); } else { choose_color(col, intensity, &me, &left, &below, NULL, NULL); } scanline[cpu][ap->a_x*3+RED] = col[RED]; scanline[cpu][ap->a_x*3+GRN] = col[GRN]; scanline[cpu][ap->a_x*3+BLU] = col[BLU]; } else { scanline[cpu][ap->a_x*3+RED] = bgcolor[RED]; scanline[cpu][ap->a_x*3+GRN] = bgcolor[GRN]; scanline[cpu][ap->a_x*3+BLU] = bgcolor[BLU]; } /* * Save the cell info for the next pixel. */ saved[cpu]->c_ishit = me.c_ishit; saved[cpu]->c_id = me.c_id; saved[cpu]->c_dist = me.c_dist; saved[cpu]->c_region = me.c_region; VMOVE(saved[cpu]->c_rdir, me.c_rdir); VMOVE(saved[cpu]->c_hit, me.c_hit); VMOVE(saved[cpu]->c_normal, me.c_normal); return edge; }
/** * 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"); }
int main(int argc, char **argv) { /* START # 1 */ struct application ap; /* Application struct, passed between functions. */ int idx; /* Index for rt_dirbuild & rt_gettree. */ static struct rt_i *rtip;/* Used for building directory, etc. */ char idbuf[132]; /* First id record in .g file. */ int i, j, k; /* Loop variables. */ double vec[3]; /* Temporary vector. */ double r[8]; /* Temporary variable. */ int c; /* Variable to read a character. */ char tmpstrng[150]; /* Temporary string variable. */ FILE *fpr=NULL; /* Used to read a file. */ FILE *fpw; /* Used to write a file. */ char filetmp[MAXFIL]; /* Temperature file name. */ char filernn[MAXFIL]; /* Region # & name file. */ char fileout[MAXFIL]; /* Output file name. */ char line[151]; /* Used to read one line of a file. */ int mon, day, yr; /* Month, day, and year read from PRISM file. */ float hr, min; /* Hour & minute read from PRISM file. */ int itype; /* Type of temperature file, 0=>PRISM, 1=>other. */ int numreg; /* Number of regions (includes background). */ /* User enters when using a PRISM file or read */ /* from generic file. */ int numreg_read; /* Number of regions read from region # & name */ /* file (includes background). */ int numreg_g; /* Number of regions read from .g file plus one */ /* for the background. */ double eltim; /* Elapsed time. */ double eltim_read; /* Elapsed time read from temperature file. */ int frst_line; /* Number of regions to be read in first line */ /* of PRISM file. */ int last_line; /* Number of regions to be read in last line */ /* of PRISM file. */ int full_line; /* Number of full lines of PRISM file to read. */ double center[3]; /* Center of bounding sphere or rpp. */ double radius; /* Radius of bounding sphere. */ double rppmax[3]; /* Maximum of bounding rpp. */ double rppmin[3]; /* Minimum of bounding rpp. */ double multi; /* Multiplication factor for radius. */ int region_hit; /* Region number hit by ray. */ int wide, high; /* Width & height of picture. */ double deltaw, deltah; /* Spacing between rays. */ double denom; /* Denominator for use in equations. */ double az, el; /* Viewing azimuth & elevation. */ double alpha, beta; /* Angles for rotation (rad). */ double calpha, salpha; /* Cosine & sine of alpha. */ double cbeta, sbeta; /* Cosine & sine of beta. */ int ret; /* Check to see if arguments implemented correctly. */ if (argc < 3 || argv[1]==NULL || argv[2]==NULL) { fprintf(stderr, "\nUsage: showtherm file.g objects\n\n"); } else { /* START # 4 */ /* Get beginning info such as name of temperature file, */ /* name of region # & name file, type of temperature file */ /* using. */ /* Ask type of temperature file to be used. */ fprintf(stderr, "Type of output file to be read 0=>PRISM, "); fprintf(stderr, "1=>generic.\n\t"); ret = scanf("%d", &itype); if (ret == 0) perror("scanf"); if (itype != 1) itype = 0; if (itype == 0) { /* Read info about (name & # regions) PRISM file. */ fprintf(stderr, "Enter name of the PRISM output "); fprintf(stderr, "file to be read (%d char max).\n\t", MAXFIL); ret = scanf("%25s", filetmp); /* MAXFIL */ if (ret == 0) perror("scanf"); /* Ask for number of regions. */ fprintf(stderr, "Enter the number of regions in the PRISM "); fprintf(stderr, "file, must be more\n"); fprintf(stderr, "than eight (not including the background).\n\t"); ret = scanf("%d", &numreg); if (ret == 0) perror("scanf"); } else { /* Read info about (name) generic file. */ fprintf(stderr, "Enter name of the generic output file to be "); fprintf(stderr, "read (%d char max).\n\t", MAXFIL); ret = scanf("%25s", filetmp); /* MAXFIL */ if (ret == 0) perror("scanf"); } /* Find name of region # & name file. */ fprintf(stderr, "Enter name of region # & name file to be read "); fprintf(stderr, "(%d char max).\n\t", MAXFIL); ret = scanf("%25s", filernn); /* MAXFIL */ if (ret == 0) perror("scanf"); /* Find name of output file. */ fprintf(stderr, "Enter name of output file (%d char max).\n\t", MAXFIL); ret = scanf("%25s", fileout); /*MAXFIL */ if (ret == 0) perror("scanf"); /* Find elapsed time to create graphical representation of. */ fprintf(stderr, "Enter the elapsed time to create graphical "); fprintf(stderr, "representation of.\n\t"); ret = scanf("%lf", &eltim); if (ret == 0) perror("scanf"); /* Open generic file and read number of regions if necessary. */ if (itype == 1) { fpr = fopen(filetmp, "rb"); (void)bu_fgets(line, 150, fpr); sscanf(line, "%d", &numreg); } /* Add one to number of regions to include background. */ numreg ++; printf("Number of regions (including "); (void)fflush(stdout); printf("the background): %d\n", numreg); (void)fflush(stdout); /* Malloc arrays. */ info = (struct table *)bu_malloc(numreg * sizeof (struct table), "info"); /* Zero all arrays. */ for (i=0; i<numreg; i++) { info[i].temp = 0.0; for (j=0; j<150; j++) { info[i].regname[j] = ' '; } } /* Now read the temperature file. */ if (itype == 0) { /* PRISM file. */ /* START # 2 */ fpr = fopen(filetmp, "rb"); /* Read date and print out. */ (void)bu_fgets(line, 150, fpr); sscanf(line, "%d %d %d %f %f", &mon, &day, &yr, &hr, &min); printf("%d/%d/%d ", mon, day, yr); printf(" %f:%f\n", hr, min); (void)fflush(stdout); /* Find number of lines to read. */ frst_line = 7; full_line = (numreg - frst_line) / (frst_line + 1); last_line = numreg - frst_line -(full_line * (frst_line + 1)); /* Read first line & check if correct elapsed time. */ (void)bu_fgets(line, 150, fpr); sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf", &eltim_read, &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6]); /* * while (eltim_read != eltim) */ while ((eltim_read < (eltim - VUNITIZE_TOL)) || ((eltim + VUNITIZE_TOL) < eltim_read)) { /* Page through to end of data. */ for (i=0; i<(full_line + 1); i++) { (void)bu_fgets(line, 150, fpr); } /* Read next elapsed time. */ (void)bu_fgets(line, 150, fpr); sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf", &eltim_read, &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6]); } /* When correct elapsed time is found, read data. */ /* Read first line of data. */ for (i=0; i<frst_line; i++) { info[i].temp = r[i]; } k = frst_line; /* Next region number of temperature to be read. */ /* Read full lines of data. */ for (i=0; i<full_line; i++) { (void)bu_fgets(line, 150, fpr); sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf", &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6], &r[7]); for (j=0; j<(frst_line + 1); j++) { info[k].temp = r[j]; k++; } } /* Read last line of data. */ (void)bu_fgets(line, 150, fpr); if (last_line == 1) sscanf(line, "%lf", &r[0]); if (last_line == 2) sscanf(line, "%lf %lf", &r[0], &r[1]); if (last_line == 3) sscanf(line, "%lf %lf %lf", &r[0], &r[1], &r[2]); if (last_line == 4) sscanf(line, "%lf %lf %lf %lf", &r[0], &r[1], &r[2], &r[3]); if (last_line == 5) sscanf(line, "%lf %lf %lf %lf %lf", &r[0], &r[1], &r[2], &r[3], &r[4]); if (last_line == 6) sscanf(line, "%lf %lf %lf %lf %lf %lf", &r[0], &r[1], &r[2], &r[3], &r[4], &r[5]); if (last_line == 7) sscanf(line, "%lf %lf %lf %lf %lf %lf %lf", &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6]); if (last_line == 8) sscanf(line, "%lf %lf %lf %lf %lf %lf %lf %lf", &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6], &r[7]); if (last_line != 0) { for (j=0; j<last_line; j++) { info[k].temp = r[j]; k++; } } printf("Prism out file read.\n"); (void)fflush(stdout); /* END # 2 */ } else { /* Read generic file. */ /* START # 3 */ /* File is already open. */ /* Read elapsed time. */ (void)bu_fgets(line, 150, fpr); sscanf(line, "%lf", &eltim_read); while (!EQUAL(eltim_read, eltim)) { /* Page through to end of data. */ for (i=0; i<numreg; i++) { (void)bu_fgets(line, 150, fpr); } (void)bu_fgets(line, 150, fpr); sscanf(line, "%lf", &eltim_read); } /* When correct elapsed time is found, read data. */ for (i=0; i<numreg; i++) { (void)bu_fgets(line, 150, fpr); sscanf(line, "%lf", &r[0]); info[i].temp = r[0]; } } /* END # 3 */ /* Close file. */ (void)fclose(fpr); /* Read the region # & name file. */ fpr = fopen(filernn, "rb"); printf("Region # & name file opened.\n"); (void)fflush(stdout); numreg_read = 1; c = getc(fpr); while ((c != EOF) && (numreg_read < numreg)) { (void)ungetc(c, fpr); (void)bu_fgets(line, 150, fpr); sscanf(line, "%*d%149s", tmpstrng); for (i=0; i<150; i++) { info[numreg_read].regname[i] = tmpstrng[i]; } numreg_read++; c = getc(fpr); } /* Close file. */ (void)fclose(fpr); /* Check if the number of regions read from the output file is */ /* the same as the number of regions read from the region # & */ /* name file. */ if (numreg_read == numreg) { printf("The number of regions read from the output file "); printf("and the region # & name\n"); printf("file was the same, %d (does not ", (numreg-1)); printf("include background in number).\n"); (void)fflush(stdout); } if (numreg_read != numreg) { printf("The number of regions read from the output file "); printf("and the region # & name\n"); printf("file was not the same, %d vs %d.\n", (numreg-1), (numreg_read-1)); printf("This is an ERROR.\n\n"); (void)fflush(stdout); } /* Build the directory. */ printf("Building directory.\n"); (void)fflush(stdout); idx = 1; /* Set index for rt_dirbuild. */ rtip = rt_dirbuild(argv[idx], idbuf, sizeof(idbuf)); printf("File: %s\n", argv[idx]); (void)fflush(stdout); printf("Database Title: %s\n", idbuf); (void)fflush(stdout); /* Set useair to 1, to show hits of air. Must show hits of air */ /* since other irprep programs do. */ rtip->useair = 1; /* Load desired objects. */ idx = 2; /* Set index for rt_gettree. */ while (argv[idx] != NULL) { rt_gettree(rtip, argv[idx]); printf("\t%s loaded.\n", argv[idx]); (void)fflush(stdout); idx++; } /* Find the total number of regions in the .g file & add one */ /* for background. */ numreg_g = (int)rtip->nregions + 1; if ((numreg == numreg_read) && (numreg_read == numreg_g)) { printf("The number of regions read from the output\n"); printf("file, the region # & name file, and the .g\n"); printf("file are all equal. The number of regions\n"); printf("read, including the background is %d\n", numreg_g); (void)fflush(stdout); } else { printf("The number of regions read from the output\n"); printf("file, the region # & name file, and the .g\n"); printf("file are not all equal.\n"); printf("\toutput file: %d\n", numreg); printf("\tregion # & name file: %d\n", numreg_read); printf("\t.g file: %d\n", numreg_g); (void)fflush(stdout); } /* Start preparation. */ printf("Preparation started.\n"); (void)fflush(stdout); rt_prep(rtip); /* Maximums & minimums of bounding rpp. */ rppmin[X] = rtip->mdl_min[X]; rppmin[Y] = rtip->mdl_min[Y]; rppmin[Z] = rtip->mdl_min[Z]; rppmax[X] = rtip->mdl_max[X]; rppmax[Y] = rtip->mdl_max[Y]; rppmax[Z] = rtip->mdl_max[Z]; /* Find the center of the bounding sphere or rpp. */ center[X] = rppmin[X] + (rppmax[X] - rppmin[X]) / 2.0; center[Y] = rppmin[Y] + (rppmax[Y] - rppmin[Y]) / 2.0; center[Z] = rppmin[Z] + (rppmax[Z] - rppmin[Z]) / 2.0; /* Find the length of the radius of the bounding sphere. */ radius = (rppmax[X] - rppmin[X]) * (rppmax[X] - rppmin[X]) + (rppmax[Y] - rppmin[Y]) * (rppmax[Y] - rppmin[Y]) + (rppmax[Z] - rppmin[Z]) * (rppmax[Z] - rppmin[Z]); radius = sqrt(radius) / 2.0 + 1.0; /* Make radius a bit longer. */ printf("\nMinimum & maximum X: %f - %f\n", rppmin[X], rppmax[X]); printf("Minimum & maximum Y: %f - %f\n", rppmin[Y], rppmax[Y]); printf("Minimum & maximum Z: %f - %f\n", rppmin[Z], rppmax[Z]); printf("Center of bounding sphere: %f, %f, %f\n", center[X], center[Y], center[Z]); printf("Radius of bounding sphere: %f\n", radius); printf("Enter multiplication factor for radius.\n\t"); (void)fflush(stdout); ret = scanf("%lf", &multi); if (ret == 0) perror("scanf"); /* Multiply radius by multiplication factor. */ radius = radius * multi; /* Set up parameters for rt_shootray. */ RT_APPLICATION_INIT(&ap); ap.a_hit = hit; /* User supplied hit function. */ ap.a_miss = miss; /* User supplied miss function. */ ap.a_overlap = overlap; /* User supplied overlap function. */ ap.a_rt_i = rtip; /* Pointer from rt_dirbuild. */ ap.a_onehit = 1; /* Hit flag, stop after first hit. */ ap.a_level = 0; /* Recursion level for diagnostics. */ ap.a_resource = 0; /* Address of resource struct. */ /* Open output file. */ fpw = fopen(fileout, "wb"); /* User enters grid size. */ fprintf(stderr, "Enter grid size.\n\t"); ret = scanf("%d", &wide); if (ret == 0) perror("scanf"); high = wide; /* User enters azimuth & elevation for viewing. */ fprintf(stderr, "Enter azimuth & elevation.\n\t"); ret = scanf("%lf %lf", &az, &el); if (ret == 0) perror("scanf"); alpha = az * DEG2RAD; beta = (-el) * DEG2RAD; calpha = cos(alpha); salpha = sin(alpha); cbeta = cos(beta); sbeta = sin(beta); /* Find spacing between rays. */ deltaw = 2. * radius / (float)wide; deltah = 2. * radius / (float)high; /* Print grid size, azimuth, and elevation. */ printf("gridsize: %d x %d\n", wide, high); printf("azimuth: %f degrees\n", az); printf("elevation: %f degrees\n", el); (void)fflush(stdout); /* Write size of grid to output file. */ fprintf(fpw, "%d\t%d\n", wide, high); (void)fflush(stdout); /* Set firing direction. Rotate (-1, 0, 0) to proper position. */ vec[X] = (-1.0) * cbeta * calpha; vec[Y] = (-1.0) * cbeta * salpha; vec[Z] = (-1.0) * (-1.0) * sbeta; /* Normalize. */ denom = vec[X] * vec[X] + vec[Y] * vec[Y] + vec[Z] * vec[Z]; denom = sqrt(denom); vec[X] /= denom; vec[Y] /= denom; vec[Z] /= denom; ap.a_ray.r_dir[X] = vec[X]; ap.a_ray.r_dir[Y] = vec[Y]; ap.a_ray.r_dir[Z] = vec[Z]; /* Set starting point. */ vec[X] = center[X] + radius; for (i=0; i<high; i++) { vec[Z] = center[Z] + radius - (float)i * deltah; for (j=0; j<wide; j++) { vec[Y] = center[Y] - radius + (float)j * deltaw; /* Rotate starting point. */ ap.a_ray.r_pt[X] = vec[X] * cbeta * calpha + vec[Z] * sbeta * calpha - vec[Y] * salpha; ap.a_ray.r_pt[Y] = vec[X] * cbeta * salpha + vec[Z] * sbeta * salpha + vec[Y] * calpha; ap.a_ray.r_pt[Z] = (-vec[X]) * sbeta + vec[Z] * cbeta; /* Call rt_shootray. */ region_hit = rt_shootray(&ap); /* Write temperature of region to output file. */ fprintf(fpw, "%f\n", info[region_hit].temp); (void)fflush(fpw); } } } /* END # 4 */ return 0; } /* END # 1 */
int main(int argc, char *argv[]) { struct rt_i *rtip = NULL; char db_title[TITLE_LEN+1];/* title from MGED file */ const char *tmp_str; extern char local_u_name[65]; extern double base2local; extern double local2base; FILE *fPtr; int Ch; /* Option name */ int mat_flag = 0; /* Read matrix from stdin? */ int use_of_air = 0; int print_ident_flag = 1; char ocastring[1024] = {0}; struct bu_list script_list; /* For -e and -f options */ struct script_rec *srp; extern outval ValTab[]; /* from if.c, callback functions for overlap, hit, and miss shots */ int if_overlap(struct application *, struct partition *, struct region *, struct region *, struct partition *); int if_hit(struct application *, struct partition *, struct seg *); int if_miss(struct application *); BU_LIST_INIT(&script_list); bu_setprogname(argv[0]); ocname[OVLP_RESOLVE] = "resolve"; ocname[OVLP_REBUILD_FASTGEN] = "rebuild_fastgen"; ocname[OVLP_REBUILD_ALL] = "rebuild_all"; ocname[OVLP_RETAIN] = "retain"; *ocastring = '\0'; bu_optind = 1; /* restart */ /* Handle command-line options */ while ((Ch = bu_getopt(argc, argv, OPT_STRING)) != -1) { if (bu_optopt == '?') Ch='h'; switch (Ch) { case 'A': attrib_add(bu_optarg, &need_prep); break; case 'B': rt_bot_minpieces = atoi(bu_optarg); break; case 'T': setenv("LIBRT_BOT_MINTIE", bu_optarg, 1); break; case 'b': do_backout = 1; break; case 'E': if (nirt_debug & DEBUG_SCRIPTS) show_scripts(&script_list, "before erasure"); while (BU_LIST_WHILE(srp, script_rec, &script_list)) { BU_LIST_DEQUEUE(&(srp->l)); free_script(srp); } if (nirt_debug & DEBUG_SCRIPTS) show_scripts(&script_list, "after erasure"); break; case 'e': enqueue_script(&script_list, READING_STRING, bu_optarg); if (nirt_debug & DEBUG_SCRIPTS) show_scripts(&script_list, "after enqueueing a literal"); break; case 'f': enqueue_script(&script_list, READING_FILE, bu_optarg); if (nirt_debug & DEBUG_SCRIPTS) show_scripts(&script_list, "after enqueueing a file name"); break; case 'L': listformats(); bu_exit(EXIT_SUCCESS, NULL); case 'M': mat_flag = 1; break; case 'O': sscanf(bu_optarg, "%1024s", ocastring); break; case 's': silent_flag = SILENT_YES; /* Positively yes */ break; case 'v': silent_flag = SILENT_NO; /* Positively no */ break; case 'x': sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug); break; case 'X': sscanf(bu_optarg, "%x", (unsigned int *)&nirt_debug); break; case 'u': if (sscanf(bu_optarg, "%d", &use_of_air) != 1) { (void) fprintf(stderr, "Illegal use-air specification: '%s'\n", bu_optarg); return 1; } break; case 'H': if (sscanf(bu_optarg, "%d", &print_ident_flag) != 1) { (void) fprintf(stderr, "Illegal header output option specified: '%s'\n", bu_optarg); return 1; } break; default: printusage(); bu_exit (Ch != 'h', NULL); } } /* end while getopt */ if (argc - bu_optind < 2) { printusage(); return 1; } if (isatty(0)) { if (silent_flag != SILENT_YES) silent_flag = SILENT_NO; } else { /* stdin is not a TTY */ if (silent_flag != SILENT_NO) silent_flag = SILENT_YES; } if (silent_flag != SILENT_YES && print_ident_flag) (void) fputs(brlcad_ident("Natalie's Interactive Ray Tracer"), stdout); if (use_of_air && (use_of_air != 1)) { fprintf(stderr, "Warning: useair=%d specified, will set to 1\n", use_of_air); use_of_air = 1; } switch (*ocastring) { case '\0': overlap_claims = OVLP_RESOLVE; break; case '0': case '1': case '2': case '3': if (ocastring[1] == '\0') { sscanf(ocastring, "%d", &overlap_claims); } else { fprintf(stderr, "Illegal overlap_claims specification: '%s'\n", ocastring); return 1; } break; case 'r': if (BU_STR_EQUAL(ocastring, "resolve")) overlap_claims = OVLP_RESOLVE; else if (BU_STR_EQUAL(ocastring, "rebuild_fastgen")) overlap_claims = OVLP_REBUILD_FASTGEN; else if (BU_STR_EQUAL(ocastring, "rebuild_all")) overlap_claims = OVLP_REBUILD_ALL; else if (BU_STR_EQUAL(ocastring, "retain")) overlap_claims = OVLP_RETAIN; else { fprintf(stderr, "Illegal overlap_claims specification: '%s'\n", ocastring); return 1; } break; default: fprintf(stderr, "Illegal overlap_claims specification: '%s'\n", ocastring); return 1; } db_name = argv[bu_optind]; /* build directory for target object */ if (silent_flag != SILENT_YES) { printf("Database file: '%s'\n", db_name); printf("Building the directory..."); } if ((rtip = rt_dirbuild(db_name, db_title, TITLE_LEN)) == RTI_NULL) { fflush(stdout); fprintf(stderr, "Could not load file %s\n", db_name); return 1; } rti_tab[use_of_air] = rtip; rti_tab[1 - use_of_air] = RTI_NULL; rtip->useair = use_of_air; rtip->rti_save_overlaps = (overlap_claims > 0); ++bu_optind; do_rt_gettrees(rtip, argv + bu_optind, argc - bu_optind, &need_prep); /* Initialize the table of resource structures */ rt_init_resource(&res_tab, 0, rtip); /* initialization of the application structure */ RT_APPLICATION_INIT(&ap); ap.a_hit = if_hit; /* branch to if_hit routine */ ap.a_miss = if_miss; /* branch to if_miss routine */ ap.a_overlap = if_overlap;/* branch to if_overlap routine */ ap.a_logoverlap = rt_silent_logoverlap; ap.a_onehit = 0; /* continue through shotline after hit */ ap.a_resource = &res_tab; ap.a_purpose = "NIRT ray"; ap.a_rt_i = rtip; /* rt_i pointer */ ap.a_zero1 = 0; /* sanity check, sayth raytrace.h */ ap.a_zero2 = 0; /* sanity check, sayth raytrace.h */ ap.a_uptr = (void *)a_tab.attrib; /* initialize variables */ azimuth() = 0.0; elevation() = 0.0; direct(X) = -1.0; direct(Y) = 0.0; direct(Z) = 0.0; grid(HORZ) = 0.0; grid(VERT) = 0.0; grid(DIST) = 0.0; grid2targ(); set_diameter(rtip); /* initialize the output specification */ default_ospec(); /* initialize NIRT's local units */ base2local = rtip->rti_dbip->dbi_base2local; local2base = rtip->rti_dbip->dbi_local2base; tmp_str = bu_units_string(local2base); if (tmp_str) { bu_strlcpy(local_u_name, tmp_str, sizeof(local_u_name)); } else { bu_strlcpy(local_u_name, "Unknown units", sizeof(local_u_name)); } if (silent_flag != SILENT_YES) { printf("Database title: '%s'\n", db_title); printf("Database units: '%s'\n", local_u_name); printf("model_min = (%g, %g, %g) model_max = (%g, %g, %g)\n", rtip->mdl_min[X] * base2local, rtip->mdl_min[Y] * base2local, rtip->mdl_min[Z] * base2local, rtip->mdl_max[X] * base2local, rtip->mdl_max[Y] * base2local, rtip->mdl_max[Z] * base2local); } /* Run the run-time configuration file, if it exists */ if ((fPtr = fopenrc()) != NULL) { interact(READING_FILE, fPtr, rtip); fclose(fPtr); } /* Run all scripts specified on the command line */ run_scripts(&script_list, rtip); /* Perform the user interface */ if (mat_flag) { read_mat(rtip); return 0; } else { interact(READING_FILE, stdin, rtip); } return 0; }
/* * This is called (from viewshade() in shade.c) once for each hit point * to be shaded. The purpose here is to fill in values in the shadework * structure. */ HIDDEN int osl_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp) /* defined in ../h/shadework.h */ /* ptr to the shader-specific struct */ { register struct osl_specific *osl_sp = (struct osl_specific *)dp; void * thread_info; int nsamples; /* Number of samples */ /* check the validity of the arguments we got */ RT_AP_CHECK(ap); RT_CHECK_PT(pp); CK_OSL_SP(osl_sp); if (rdebug&RDEBUG_SHADE) bu_struct_print("osl_render Parameters:", osl_print_tab, (char *)osl_sp); bu_semaphore_acquire(BU_SEM_SYSCALL); /* Check if it is the first time this thread is calling this function */ bool visited = false; for (size_t i = 0; i < visited_addrs.size(); i++) { if (ap->a_resource == visited_addrs[i]) { visited = true; thread_info = thread_infos[i]; break; } } if (!visited) { visited_addrs.push_back(ap->a_resource); /* Get thread specific information from OSLRender system */ thread_info = oslr->CreateThreadInfo(); thread_infos.push_back(thread_info); } if (ap->a_level == 0) { default_a_hit = ap->a_hit; /* save the default hit callback (colorview @ rt) */ default_a_miss = ap->a_miss; } bu_semaphore_release(BU_SEM_SYSCALL); Color3 acc_color(0.0f); /* ----------------------------------- * Fill in all necessary information for the OSL renderer * ----------------------------------- */ RenderInfo info; /* Set hit point */ VMOVE(info.P, swp->sw_hit.hit_point); /* Set normal at the point */ VMOVE(info.N, swp->sw_hit.hit_normal); /* Set incidence ray direction */ VMOVE(info.I, ap->a_ray.r_dir); /* U-V mapping stuff */ info.u = swp->sw_uv.uv_u; info.v = swp->sw_uv.uv_v; VSETALL(info.dPdu, 0.0f); VSETALL(info.dPdv, 0.0f); /* x and y pixel coordinates */ info.screen_x = ap->a_x; info.screen_y = ap->a_y; info.depth = ap->a_level; info.surfacearea = 1.0f; info.shader_ref = osl_sp->shader_ref; /* We assume that the only information that will be written is thread_info, so that oslr->QueryColor is thread safe */ info.thread_info = thread_info; // Ray-tracing (local illumination) /* We only perform reflection if application decides to */ info.doreflection = 0; info.out_ray_type = 0; Color3 weight = oslr->QueryColor(&info); /* Fire another ray */ if ((info.out_ray_type & RAY_REFLECT) || (info.out_ray_type & RAY_TRANSMIT)) { struct application new_ap; RT_APPLICATION_INIT(&new_ap); new_ap = *ap; /* struct copy */ new_ap.a_onehit = 1; new_ap.a_hit = default_a_hit; new_ap.a_level = info.depth + 1; new_ap.a_flag = 0; VMOVE(new_ap.a_ray.r_dir, info.out_ray.dir); VMOVE(new_ap.a_ray.r_pt, info.out_ray.origin); /* This next ray represents refraction */ if (info.out_ray_type & RAY_TRANSMIT) { /* Displace the hit point a little bit in the direction of the next ray */ Vec3 tmp; VSCALE(tmp, info.out_ray.dir, 1e-4); VADD2(new_ap.a_ray.r_pt, new_ap.a_ray.r_pt, tmp); new_ap.a_onehit = 1; new_ap.a_refrac_index = 1.5; new_ap.a_flag = 2; /* mark as refraction */ new_ap.a_hit = osl_refraction_hit; } (void)rt_shootray(&new_ap); Color3 rec; VMOVE(rec, new_ap.a_color); Color3 res = rec*weight; VMOVE(swp->sw_color, res); } else { /* Final color */ VMOVE(swp->sw_color, weight); } return 1; }
int main(int argc, char **argv) { /* START # 99 */ struct application ap; /* Structure passed between functions. */ struct rt_i *rtip; /* Used to build directory. */ int index; /* Index for rt_dirbuild & rt_gettree. */ char idbuf[32]; /* Contains data base info. */ struct region *pr; /* Used in finding region names. */ int numreg; /* Number of regions. */ double centall[3]; /* Center of entire model. */ double minall[3]; /* Minimum of entire model. */ double maxall[3]; /* Maximum of entire model. */ double areaall; /* Surface area of bounding sphere. */ double radall; /* Radius of bounding sphere. */ long seed; /* Seed for random number generator. */ double rayfir; /* Number of rays to be fired. */ double rho, phi, theta;/* Spherical coordinates for starting point. */ double elev, az, rds; /* Elevation, azimuth, & radius for finding vector */ /* in yz-plane. */ double strtpt[3]; /* Starting point. */ double strtdir[3]; /* Starting direction. */ double denom; /* Denominator. */ int ians; /* Answer to question. */ int i, j, k, m; /* Loop counters. */ double r; /* Loop counter. */ double q; /* Temporary variable. */ double s[3], t[3]; /* Temporary variables. */ FILE *fpw; /* Allows a file to be written. */ char outfile[26]; /* Output file name. */ char errfile[26]; /* Error file name. */ FILE *fpw2; /* Allows a file to be written. */ char lwxfile[26]; /* Longwave radiation exchange file for PRISM */ /* (not quite PRISM ready). */ struct bn_unif *msr = NULL; /* Check to see if arguments are implimented correctly. */ if ( (argv[1] == NULL) || (argv[2] == NULL) ) { (void)fprintf(stderr, "\nusage: %s file.g objects\n\n", *argv); } else { /* START # 100 */ /* Find name of output file. */ (void)printf("Enter name of output file (25 char max).\n\t"); (void)fflush(stdout); (void)scanf("%25s", outfile); /* Find name of longwave radiation exchange (lwx) file */ /* for use with PRISM (not quite PRISM ready). */ (void)printf("Enter name of longwave radiation exchange"); (void)printf(" file (25 char max).\n\t"); (void)fflush(stdout); (void)scanf("%25s", lwxfile); /* Find name of error file. */ (void)printf("Enter name of error file (25 char max).\n\t"); (void)fflush(stdout); (void)scanf("%25s", errfile); /* Open files. */ fpw = fopen(outfile, "w"); fpw1 = fopen(errfile, "w"); fpw2 = fopen(lwxfile, "w"); /* Write info to output & error file. */ (void)fprintf(fpw, "\n.g file used: %s\n", argv[1]); (void)fprintf(fpw, "regions used:\n"); (void)fprintf(fpw1, "\n.g file used: %s\n", argv[1]); (void)fprintf(fpw1, "regions used:\n"); i = 2; while (argv[i] != NULL) { (void)fprintf(fpw, "\t%s\n", argv[i]); (void)fprintf(fpw1, "\t%s\n", argv[i]); i++; } (void)fprintf(fpw, "output file created: %s\n", outfile); (void)fprintf(fpw, "error file created: %s\n", errfile); (void)fprintf(fpw, "lwx file created: %s\n", errfile); (void)fflush(fpw); (void)fprintf(fpw1, "output file created: %s\n", outfile); (void)fprintf(fpw1, "error file created: %s\n", errfile); (void)fprintf(fpw1, "lwx file created: %s\n", errfile); (void)fflush(fpw1); /* Build directory. */ index = 1; /* Set index for rt_dirbuild. */ rtip = rt_dirbuild(argv[index], idbuf, sizeof(idbuf)); (void)printf("Database Title: %s\n", idbuf); (void)fflush(stdout); /* Set useair to 0 to show no hits of air. */ rtip->useair = 0; /* Load desired objects. */ index = 2; /* Set index. */ while (argv[index] != NULL) { rt_gettree(rtip, argv[index]); index += 1; } /* Find number of regions. */ numreg = (int)rtip->nregions; (void)fprintf(stderr, "Number of regions: %d\n", numreg); (void)fflush(stderr); /* Malloc everything now that the number of regions is known. */ info = (struct table *)bu_malloc(numreg * sizeof(*info), "info"); for (i=0; i<numreg; i++) { info[i].intrays = (double *)bu_malloc(numreg * sizeof(double), "info[i].intrays"); info[i].sf = (double *)bu_malloc(numreg * sizeof(double), "info[i].sf"); } /* Zero all arrays. */ for (i=0; i<numreg; i++) { /* START # 110 */ info[i].name = "\0"; info[i].lvrays = 0.; for (j=0; j<numreg; j++) { info[i].intrays[j] = 0.; info[i].sf[j] = 0.; } info[i].regarea = 0.; } /* END # 110 */ /* Get database ready by starting prep. */ rt_prep(rtip); /* Find the center of the bounding rpp of entire model. */ centall[X] = rtip->mdl_min[X] + (rtip->mdl_max[X] - rtip->mdl_min[X]) / 2.; centall[Y] = rtip->mdl_min[Y] + (rtip->mdl_max[Y] - rtip->mdl_min[Y]) / 2.; centall[Z] = rtip->mdl_min[Z] + (rtip->mdl_max[Z] - rtip->mdl_min[Z]) / 2.; /* Find minimum and maximum of entire model. */ minall[X] = rtip->mdl_min[X]; minall[Y] = rtip->mdl_min[Y]; minall[Z] = rtip->mdl_min[Z]; maxall[X] = rtip->mdl_max[X]; maxall[Y] = rtip->mdl_max[Y]; maxall[Z] = rtip->mdl_max[Z]; /* Find radius of bounding sphere. */ radall = (maxall[X] - minall[X]) * (maxall[X] - minall[X]) + (maxall[Y] - minall[Y]) * (maxall[Y] - minall[Y]) + (maxall[Z] - minall[Z]) * (maxall[Z] - minall[Z]); /* Add .5 to make sure completely outside the rpp. */ radall = sqrt(radall) / 2. + .5; /* Find surface area of bounding sphere. */ areaall = 4 * M_PI * radall * radall; /* Print info on min, max, center, radius, & surface area */ /* of entire model. */ (void)printf("Min & max for entire model.\n"); (void)printf("\tX: %f - %f\n", minall[X], maxall[X]); (void)printf("\tY: %f - %f\n", minall[Y], maxall[Y]); (void)printf("\tZ: %f - %f\n", minall[Z], maxall[Z]); (void)printf("Center: %f, %f, %f\n\n", centall[X], centall[Y], centall[Z]); (void)printf("Radius: %f\n", radall); (void)printf("Surface Area: %f\n\n", areaall); (void)fflush(stdout); /* Find number of rays to fire. */ (void)printf("Enter the number of rays to be fired.\n\t"); (void)fflush(stdout); (void)scanf("%lf", &rayfir); /* Write info to files. */ (void)fprintf(fpw, "Min & max for entire region:\n"); (void)fprintf(fpw, "\tX: %f - %f\n", minall[X], maxall[X]); (void)fprintf(fpw, "\tY: %f - %f\n", minall[Y], maxall[Y]); (void)fprintf(fpw, "\tZ: %f - %f\n", minall[Z], maxall[Z]); (void)fprintf(fpw, "Center: %f, %f, %f\n", centall[X], centall[Y], centall[Z]); (void)fprintf(fpw, "Radius: %f\n", radall); (void)fprintf(fpw, "Surface area: %f\n", areaall); (void)fprintf(fpw, "Number of rays fired: %f\n\n", rayfir); (void)fflush(fpw); (void)fprintf(fpw1, "Min & max for entire region:\n"); (void)fprintf(fpw1, "\tX: %f - %f\n", minall[X], maxall[X]); (void)fprintf(fpw1, "\tY: %f - %f\n", minall[Y], maxall[Y]); (void)fprintf(fpw1, "\tZ: %f - %f\n", minall[Z], maxall[Z]); (void)fprintf(fpw1, "Center: %f, %f, %f\n", centall[X], centall[Y], centall[Z]); (void)fprintf(fpw1, "Radius: %f\n", radall); (void)fprintf(fpw1, "Surface area: %f\n", areaall); (void)fprintf(fpw1, "Number of rays fired: %f\n\n", rayfir); (void)fflush(fpw1); /* Put region names into structure. */ pr = BU_LIST_FIRST(region, &rtip->HeadRegion); for (i=0; i<numreg; i++) { info[(int)(pr->reg_bit)].name = pr->reg_name; pr = BU_LIST_FORW(region, &(pr->l) ); } (void)printf("Region names in structure.\n"); (void)fflush(stdout); /* Write region names to error file. */ for (i=0; i<numreg; i++) { (void)fprintf(fpw1, "region %d: %s\n", (i + 1), info[i].name); (void)fflush(fpw1); } (void)fprintf(fpw1, "\n"); (void)fflush(fpw1); /* Set seed for random number generator. */ seed = 1; (void)printf("Do you wish to enter your own seed (0) or "); (void)printf("use the default of 1 (1)?\n\t"); (void)fflush(stdout); (void)scanf("%d", &ians); if (ians == 0) { (void)printf("Enter unsigned integer seed.\n\t"); (void)fflush(stdout); (void)scanf("%ld", &seed); } msr = bn_unif_init(seed, 0); (void)printf("Seed initialized\n"); (void)fflush(stdout); /* Set up parameters for rt_shootray. */ RT_APPLICATION_INIT(&ap); ap.a_hit = hit; /* User supplied hit func. */ ap.a_miss = miss; /* User supplied miss func. */ ap.a_overlap = overlap; /* User supplied overlap func. */ ap.a_rt_i = rtip; /* Pointer from rt_dirbuild. */ ap.a_onehit = 0; /* Look at all hits. */ ap.a_level = 0; /* Recursion level for diagnostics. */ ap.a_resource = 0; /* Address for resource struct. */ /* * (void)printf("Parameters for rt_shootray set.\n"); * (void)fflush(stdout); */ /* Loop through for each ray fired. */ for (r=0; r<rayfir; r++) { /* START # 150 */ /* * (void)printf("In loop - %f\n", r); * (void)fflush(stdout); */ /* Find point on the bounding sphere. The negative */ /* of the unit vector of this point will be the */ /* firing direction. */ q = BN_UNIF_DOUBLE(msr) + 0.5; theta = q * 2. * M_PI; q = BN_UNIF_DOUBLE(msr) + 0.5; phi = (q * 2.) - 1.; phi = acos(phi); rho = radall; strtdir[X] = rho * sin(phi) * cos(theta); strtdir[Y] = rho * sin(phi) * sin(theta); strtdir[Z] = rho * cos(phi); /* Elevation & azimuth for finding a vector in a plane. */ elev = M_PI / 2. - phi; az = theta; /* Find vector in yz-plane. */ q = BN_UNIF_DOUBLE(msr) + 0.5; theta = q * 2. * M_PI; q = BN_UNIF_DOUBLE(msr) + 0.5; rds = rho * sqrt(q); s[X] = 0.; s[Y] = rds * cos(theta); s[Z] = rds * sin(theta); /* Rotate vector. */ t[X] = s[X] * cos(elev) * cos(az) - s[Z] * sin(elev) * cos(az) - s[Y] * sin(az); t[Y] = s[X] * cos(elev) * sin(az) - s[Z] * sin(elev) * sin(az) + s[Y] * cos(az); t[Z] = s[X] * sin(elev) + s[Z] * cos(elev); /* Translate the point. This is the starting point. */ strtpt[X] = t[X] + strtdir[X]; strtpt[Y] = t[Y] + strtdir[Y]; strtpt[Z] = t[Z] + strtdir[Z]; /* Now transfer the starting point so that it is in the */ /* absolute coordinates not the origin's. */ strtpt[X] += centall[X]; strtpt[Y] += centall[Y]; strtpt[Z] += centall[Z]; /* Normalize starting direction & make negative. */ denom = strtdir[X] *strtdir[X] + strtdir[Y] *strtdir[Y] + strtdir[Z] *strtdir[Z]; denom = sqrt(denom); strtdir[X] /= (-denom); strtdir[Y] /= (-denom); strtdir[Z] /= (-denom); /* Set up firing point & direction. */ ap.a_ray.r_pt[X] = strtpt[X]; ap.a_ray.r_pt[Y] = strtpt[Y]; ap.a_ray.r_pt[Z] = strtpt[Z]; ap.a_ray.r_dir[X] = strtdir[X]; ap.a_ray.r_dir[Y] = strtdir[Y]; ap.a_ray.r_dir[Z] = strtdir[Z]; /* * (void)printf("Calling rt_shootray.\n"); * (void)fflush(stdout); */ /* Call rt_shootray. */ (void)rt_shootray(&ap); /* * (void)printf("Rt_shootray finished.\n"); * (void)fflush(stdout); */ } /* END # 150 */ /* * (void)printf("Finished loop.\n"); * (void)fflush(stdout); */ for (i=0; i<numreg; i++) { /* START # 160 */ /* Write region names to output file. */ (void)fprintf(fpw, "Region %d: %s\n", (i+1), info[i].name); (void)fflush(fpw); /* Find shape factors & print. */ if (info[i].lvrays == 0) { /* START # 1060 */ (void)fprintf(fpw1, "** ERROR - # or rays hitting region "); (void)fprintf(fpw1, "%d is 0. **\n", i); (void)fflush(fpw1); } /* END # 1060 */ else { /* START # 1070 */ /* Must divide by 2. since looking forwards & backwards. */ info[i].regarea = info[i].lvrays / rayfir * areaall / 2.; for (j=0; j<numreg; j++) { /* START # 1080 */ info[i].sf[j] = info[i].intrays[j] / info[i].lvrays; (void)fprintf(fpw, "\t%d %d %f\n", (i + 1), (j + 1), info[i].sf[j]); (void)fflush(fpw); (void)fprintf(fpw1, "reg %d - reg %d - rays leave ", (i + 1), (j + 1)); (void)fprintf(fpw1, "& int %f - rays leave %f ", info[i].intrays[j], info[i].lvrays); (void)fprintf(fpw1, "- sf %f - area %f\n", info[i].sf[j], info[i].regarea); (void)fflush(fpw1); } /* END # 1080 */ } /* END # 1070 */ } /* END # 160 */ /* Write lwx file. */ (void)fprintf(fpw2, "Longwave Radiation Exchange Factors "); (void)fprintf(fpw2, "for %s\n", argv[1]); (void)fprintf(fpw2, "Number of Regions = %4d\n", numreg); (void)fprintf(fpw2, "TEMIS\n\n"); for (i=0; i<numreg; i++) { /* START # 1090 */ (void)fprintf(fpw2, "Region\tArea\tEmissivity\n"); /* Area is put into square meters. */ (void)fprintf(fpw2, "%d\t%f\n", (i + 1), (info[i].regarea / 1000. / 1000.)); /* Count the number of shape factors. */ k = 0; for (j=0; j<numreg; j++) { if (info[i].sf[j] != 0.) k++; } (void)fprintf(fpw2, "Bij\t%d\n", k); /* Print shape factors. */ m = 0; for (j=0; j<numreg; j++) { /* START # 1100 */ if (info[i].sf[j] != 0.) { /* START # 1110 */ (void)fprintf(fpw2, "%4d %.4f ", (j + 1), info[i].sf[j]); m++; if (m == 5) { /* START # 1120 */ m = 0; (void)fprintf(fpw2, "\n"); } /* END # 1120 */ } /* END # 1110 */ } /* END # 1100 */ if (m != 0) (void)fprintf(fpw2, "\n"); (void)fprintf(fpw2, " Gnd Sky\n\n"); (void)fflush(fpw2); } /* END # 1090 */ /* free memory */ for (i=0; i<numreg; i++) { bu_free(info[i].intrays, "info[i].intrays"); bu_free(info[i].sf, "info[i].sf"); } bu_free(info, "info"); /* Close files. */ (void)fclose(fpw); (void)fclose(fpw1); (void)fclose(fpw2); } /* END # 100 */ return 0; } /* END # 99 */
/* * R R _ H I T * * This routine is called when an internal reflection ray hits something * (which is ordinarily the case). * * Generally, there will be one or two partitions on the hit list. * The values for pt_outhit for the second partition should not be used, * as a_onehit was set to 3, getting a maximum of 3 valid hit points. * * Explicit Returns - * 0 dreadful internal error * 1 treat as escaping ray & reshoot * 2 Proper exit point determined, with Implicit Returns: * a_uvec exit Point * a_vvec exit Normal (inward pointing) * a_refrac_index RI of *next* material */ HIDDEN int rr_hit(struct application *ap, struct partition *PartHeadp, struct seg *UNUSED(segp)) { register struct partition *pp; register struct hit *hitp; register struct soltab *stp; struct partition *psave = (struct partition *)NULL; struct shadework sw; struct application appl; int ret; RT_AP_CHECK(ap); RT_APPLICATION_INIT(&appl); for (pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw) if (pp->pt_outhit->hit_dist > 0.0) break; if (pp == PartHeadp) { if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) { bu_log("rr_hit: %d, %d no hit out front?\n", ap->a_x, ap->a_y); ret = 0; /* error */ goto out; } ret = 1; /* treat as escaping ray */ goto out; } /* * Ensure that the partition we are given is part of the same * region that we started in. When the internal reflection * is happening very near an edge or corner, this is not always * the case, and either (a) a small sliver of some other region * is found to be in the way, or (b) the ray completely misses the * region that it started in, although not by much. */ psave = pp; if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_hit(%s)\n", psave->pt_regionp->reg_name); for (; pp != PartHeadp; pp = pp->pt_forw) if (pp->pt_regionp == (struct region *)(ap->a_uptr)) break; if (pp == PartHeadp) { if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) { bu_log("rr_hit: %d, %d Ray internal to %s landed unexpectedly in %s\n", ap->a_x, ap->a_y, ((struct region *)(ap->a_uptr))->reg_name, psave->pt_regionp->reg_name); ret = 0; /* error */ goto out; } ret = 1; /* treat as escaping ray */ goto out; } /* * At one time, this was a check for pp->pt_inhit->hit_dist * being NEAR zero. That was a mistake, because we may have * been at the edge of a subtracted out center piece when * internal reflection happened, except that floating point * error (being right on the surface of the interior solid) * prevented us from "seeing" that solid on the next ray, * causing our ray endpoints to be quite far from the starting * point, yet with the ray still validly inside the glass region. * * There is a major problem if the entry point * is further ahead than the firing point, i.e., >0. * * Because this error has not yet been encountered, it is * considered dreadful. Some recovery may be possible. * * For now, this seems to happen when a reflected ray starts outside * the glass and doesn't even intersect the glass, so treat it as * an escaping ray. */ if (pp->pt_inhit->hit_dist > 10) { stp = pp->pt_inseg->seg_stp; if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_hit: %d, %d %s inhit %g > 10.0! (treating as escaping ray)\n", ap->a_x, ap->a_y, pp->pt_regionp->reg_name, pp->pt_inhit->hit_dist); ret = 1; /* treat as escaping ray */ goto out; } /* * If there is a very small crack in the glass, perhaps formed * by a small error when taking the Union of two solids, * attempt to find the real exit point. * NOTE that this is usually taken care of inside librt * in the bool_weave code, but it is inexpensive to check for it * here. If this case is detected, push on, and log it. * This code is not expected to be needed. */ while (pp->pt_forw != PartHeadp) { register fastf_t d; d = pp->pt_forw->pt_inhit->hit_dist - pp->pt_outhit->hit_dist; if (!NEAR_ZERO(d, AIR_GAP_TOL)) break; if (pp->pt_forw->pt_regionp != pp->pt_regionp) break; if (R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) bu_log( "rr_hit: %d, %d fusing small crack in glass %s\n", ap->a_x, ap->a_y, pp->pt_regionp->reg_name); pp = pp->pt_forw; } hitp = pp->pt_outhit; stp = pp->pt_outseg->seg_stp; if (hitp->hit_dist >= INFINITY) { bu_log("rr_hit: %d, %d infinite glass (%g, %g) %s\n", ap->a_x, ap->a_y, pp->pt_inhit->hit_dist, hitp->hit_dist, pp->pt_regionp->reg_name); ret = 0; /* dreadful error */ goto out; } VJOIN1(hitp->hit_point, ap->a_ray.r_pt, hitp->hit_dist, ap->a_ray.r_dir); RT_HIT_NORMAL(ap->a_vvec, hitp, stp, &(ap->a_ray), pp->pt_outflip); /* For refraction, want exit normal to point inward. */ VREVERSE(ap->a_vvec, ap->a_vvec); VMOVE(ap->a_uvec, hitp->hit_point); ap->a_cumlen += (hitp->hit_dist - pp->pt_inhit->hit_dist); ap->a_refrac_index = RI_AIR; /* Default medium: air */ /* * Look ahead, and see if there is more glass to come. * If so, obtain its refractive index, to enable correct * calculation of the departing refraction angle. */ if (pp->pt_forw != PartHeadp) { register fastf_t d; d = pp->pt_forw->pt_inhit->hit_dist - hitp->hit_dist; if (NEAR_ZERO(d, AIR_GAP_TOL)) { /* * Make a private copy of the application struct, * because viewshade() may change various fields. */ appl = *ap; /* struct copy */ memset((char *)&sw, 0, sizeof(sw)); sw.sw_transmit = sw.sw_reflect = 0.0; /* Set default in case shader doesn't fill this in. */ sw.sw_refrac_index = RI_AIR; /* Set special flag so that we get only shader * parameters (refractive index, in this case). * We don't even care about transmitted energy. */ sw.sw_xmitonly = 2; sw.sw_inputs = 0; /* no fields filled yet */ #ifdef RT_MULTISPECTRAL sw.msw_color = bn_tabdata_get_constval(1.0, spectrum); sw.msw_basecolor = bn_tabdata_get_constval(1.0, spectrum); #else VSETALL(sw.sw_color, 1); VSETALL(sw.sw_basecolor, 1); #endif if (R_DEBUG&(RDEBUG_SHADE|RDEBUG_REFRACT)) bu_log("rr_hit calling viewshade to discover refractive index\n"); (void)viewshade(&appl, pp->pt_forw, &sw); #ifdef RT_MULTISPECTRAL bu_free(sw.msw_color, "sw.msw_color"); bu_free(sw.msw_basecolor, "sw.msw_basecolor"); #endif if (R_DEBUG&(RDEBUG_SHADE|RDEBUG_REFRACT)) bu_log("rr_hit refractive index = %g\n", sw.sw_refrac_index); if (sw.sw_transmit > 0) { ap->a_refrac_index = sw.sw_refrac_index; if (R_DEBUG&RDEBUG_SHADE) { bu_log("rr_hit a_refrac_index=%g (trans=%g)\n", ap->a_refrac_index, sw.sw_transmit); } ret= 3; /* OK -- more glass follows */ goto out; } } } ret = 2; /* OK -- no more glass */ out: if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_hit(%s) return=%d\n", psave ? psave->pt_regionp->reg_name : "", ret); return ret; }
/* * R R _ R E N D E R */ int rr_render(register struct application *ap, const struct partition *pp, struct shadework *swp) { struct application sub_ap; vect_t work; vect_t incident_dir; fastf_t shader_fract; fastf_t reflect; fastf_t transmit; #ifdef RT_MULTISPECTRAL struct bn_tabdata *ms_filter_color = BN_TABDATA_NULL; struct bn_tabdata *ms_shader_color = BN_TABDATA_NULL; struct bn_tabdata *ms_reflect_color = BN_TABDATA_NULL; struct bn_tabdata *ms_transmit_color = BN_TABDATA_NULL; #else vect_t filter_color; vect_t shader_color; vect_t reflect_color; vect_t transmit_color; #endif fastf_t attenuation; vect_t to_eye; int code; RT_AP_CHECK(ap); RT_APPLICATION_INIT(&sub_ap); #ifdef RT_MULTISPECTRAL sub_ap.a_spectrum = BN_TABDATA_NULL; ms_reflect_color = bn_tabdata_get_constval(0.0, spectrum); #endif /* * sw_xmitonly is set primarily for light visibility rays. * Need to compute (partial) transmission through to the light, * or procedural shaders won't be able to cast shadows * and light won't be able to get through glass * (including "stained glass" and "filter glass"). * * On the other hand, light visibility rays shouldn't be refracted, * it is pointless to shoot at where the light isn't. */ if (swp->sw_xmitonly) { /* Caller wants transmission term only, don't fire reflected rays */ transmit = swp->sw_transmit + swp->sw_reflect; /* Don't loose energy */ reflect = 0; } else { reflect = swp->sw_reflect; transmit = swp->sw_transmit; } if (R_DEBUG&RDEBUG_REFRACT) { bu_log("rr_render(%s) START: lvl=%d reflect=%g, transmit=%g, xmitonly=%d\n", pp->pt_regionp->reg_name, ap->a_level, reflect, transmit, swp->sw_xmitonly); } if (reflect <= 0 && transmit <= 0) goto out; if (ap->a_level > max_bounces) { /* Nothing more to do for this ray */ static long count = 0; /* Not PARALLEL, should be OK */ if ((R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) && ( count++ < MSG_PROLOGUE || (count%MSG_INTERVAL) == 3 )) { bu_log("rr_render: %d, %d MAX BOUNCES=%d: %s\n", ap->a_x, ap->a_y, ap->a_level, pp->pt_regionp->reg_name); } /* * Return the basic color of the object, ignoring the * the fact that it is supposed to be * filtering or reflecting light here. * This is much better than returning just black, * but something better might be done. */ #ifdef RT_MULTISPECTRAL BN_CK_TABDATA(swp->msw_color); BN_CK_TABDATA(swp->msw_basecolor); bn_tabdata_copy(swp->msw_color, swp->msw_basecolor); #else VMOVE(swp->sw_color, swp->sw_basecolor); #endif ap->a_cumlen += pp->pt_inhit->hit_dist; goto out; } #ifdef RT_MULTISPECTRAL BN_CK_TABDATA(swp->msw_basecolor); ms_filter_color = bn_tabdata_dup(swp->msw_basecolor); #else VMOVE(filter_color, swp->sw_basecolor); #endif if ((swp->sw_inputs & (MFI_HIT|MFI_NORMAL)) != (MFI_HIT|MFI_NORMAL)) shade_inputs(ap, pp, swp, MFI_HIT|MFI_NORMAL); /* * If this ray is being fired from the exit point of * an object, and is directly entering another object, * (i.e., there is no intervening air-gap), and * the two refractive indices match, then do not fire a * reflected ray -- just take the transmission contribution. * This is important, e.g., for glass gun tubes projecting * through a glass armor plate. :-) */ if (NEAR_ZERO(pp->pt_inhit->hit_dist, AIR_GAP_TOL) && ZERO(ap->a_refrac_index - swp->sw_refrac_index)) { transmit += reflect; reflect = 0; } /* * Diminish base color appropriately, and add in * contributions from mirror reflection & transparency */ shader_fract = 1 - (reflect + transmit); if (shader_fract < 0) { shader_fract = 0; } else if (shader_fract >= 1) { goto out; } if (R_DEBUG&RDEBUG_REFRACT) { bu_log("rr_render: lvl=%d start shader=%g, reflect=%g, transmit=%g %s\n", ap->a_level, shader_fract, reflect, transmit, pp->pt_regionp->reg_name); } #ifdef RT_MULTISPECTRAL BN_GET_TABDATA(ms_shader_color, swp->msw_color->table); bn_tabdata_scale(ms_shader_color, swp->msw_color, shader_fract); #else VSCALE(shader_color, swp->sw_color, shader_fract); #endif /* * Compute transmission through an object. * There may be a mirror reflection, which will be handled * by the reflection code later */ if (transmit > 0) { if (R_DEBUG&RDEBUG_REFRACT) { bu_log("rr_render: lvl=%d transmit=%g. Calculate refraction at entrance to %s.\n", ap->a_level, transmit, pp->pt_regionp->reg_name); } /* * Calculate refraction at entrance. */ sub_ap = *ap; /* struct copy */ #ifdef RT_MULTISPECTRAL sub_ap.a_spectrum = bn_tabdata_dup((struct bn_tabdata *)ap->a_spectrum); #endif sub_ap.a_level = 0; /* # of internal reflections */ sub_ap.a_cumlen = 0; /* distance through the glass */ sub_ap.a_user = -1; /* sanity */ sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge; sub_ap.a_diverge = 0.0; sub_ap.a_uptr = (genptr_t)(pp->pt_regionp); VMOVE(sub_ap.a_ray.r_pt, swp->sw_hit.hit_point); VMOVE(incident_dir, ap->a_ray.r_dir); /* If there is an air gap, reset ray's RI to air */ if (pp->pt_inhit->hit_dist > AIR_GAP_TOL) sub_ap.a_refrac_index = RI_AIR; if (!ZERO(sub_ap.a_refrac_index - swp->sw_refrac_index) && !rr_refract(incident_dir, /* input direction */ swp->sw_hit.hit_normal, /* exit normal */ sub_ap.a_refrac_index, /* current RI */ swp->sw_refrac_index, /* next RI */ sub_ap.a_ray.r_dir /* output direction */ )) { /* * Ray was mirror reflected back outside solid. * Just add contribution to reflection, * and quit. */ reflect += transmit; transmit = 0; #ifdef RT_MULTISPECTRAL ms_transmit_color = bn_tabdata_get_constval(0.0, spectrum); #else VSETALL(transmit_color, 0); #endif if (R_DEBUG&RDEBUG_REFRACT) { bu_log("rr_render: lvl=%d change xmit into reflection %s\n", ap->a_level, pp->pt_regionp->reg_name); } goto do_reflection; } if (R_DEBUG&RDEBUG_REFRACT) { bu_log("rr_render: lvl=%d begin transmission through %s.\n", ap->a_level, pp->pt_regionp->reg_name); } /* * Find new exit point from the inside. * We will iterate, but not recurse, due to the special * (non-recursing) hit and miss routines used here for * internal reflection. * * a_onehit is set to 3, so that where possible, * rr_hit() will be given three accurate hit points: * the entry and exit points of this glass region, * and the entry point into the next region. * This permits calculation of the departing * refraction angle based on the RI of the current and * *next* regions along the ray. */ sub_ap.a_purpose = "rr first glass transmission ray"; sub_ap.a_flag = 0; do_inside: sub_ap.a_hit = rr_hit; sub_ap.a_miss = rr_miss; sub_ap.a_logoverlap = ap->a_logoverlap; sub_ap.a_onehit = 3; sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge; sub_ap.a_diverge = 0.0; switch (code = rt_shootray(&sub_ap)) { case 3: /* More glass to come. * uvec=exit_pt, vvec=N, a_refrac_index = next RI. */ break; case 2: /* No more glass to come. * uvec=exit_pt, vvec=N, a_refrac_index = next RI. */ break; case 1: /* Treat as escaping ray */ if (R_DEBUG&RDEBUG_REFRACT) bu_log("rr_refract: Treating as escaping ray\n"); goto do_exit; case 0: default: /* Dreadful error */ #ifdef RT_MULTISPECTRAL bu_bomb("rr_refract: Stuck in glass. Very green pixel, unsupported in multi-spectral mode\n"); #else VSET(swp->sw_color, 0, 99, 0); /* very green */ #endif goto out; /* abandon hope */ } if (R_DEBUG&RDEBUG_REFRACT) { bu_log("rr_render: calculating refraction @ exit from %s (green)\n", pp->pt_regionp->reg_name); bu_log("Start point to exit point:\n\ vdraw open rr;vdraw params c 00ff00; vdraw write n 0 %g %g %g; vdraw wwrite n 1 %g %g %g; vdraw send\n", V3ARGS(sub_ap.a_ray.r_pt), V3ARGS(sub_ap.a_uvec)); } /* NOTE: rr_hit returns EXIT Point in sub_ap.a_uvec, * and returns EXIT Normal in sub_ap.a_vvec, * and returns next RI in sub_ap.a_refrac_index */ if (R_DEBUG&RDEBUG_RAYWRITE) { wraypts(sub_ap.a_ray.r_pt, sub_ap.a_ray.r_dir, sub_ap.a_uvec, 2, ap, stdout); /* 2 = ?? */ } if (R_DEBUG&RDEBUG_RAYPLOT) { /* plotfp */ bu_semaphore_acquire(BU_SEM_SYSCALL); pl_color(stdout, 0, 255, 0); pdv_3line(stdout, sub_ap.a_ray.r_pt, sub_ap.a_uvec); bu_semaphore_release(BU_SEM_SYSCALL); } /* Advance. Exit point becomes new start point */ VMOVE(sub_ap.a_ray.r_pt, sub_ap.a_uvec); VMOVE(incident_dir, sub_ap.a_ray.r_dir); /* * Calculate refraction at exit point. * Use "look ahead" RI value from rr_hit. */ if (!ZERO(sub_ap.a_refrac_index - swp->sw_refrac_index) && !rr_refract(incident_dir, /* input direction */ sub_ap.a_vvec, /* exit normal */ swp->sw_refrac_index, /* current RI */ sub_ap.a_refrac_index, /* next RI */ sub_ap.a_ray.r_dir /* output direction */ )) { static long count = 0; /* not PARALLEL, should be OK */ /* Reflected internally -- keep going */ if ((++sub_ap.a_level) <= max_ireflect) { sub_ap.a_purpose = "rr reflected internal ray, probing for glass exit point"; sub_ap.a_flag = 0; goto do_inside; } /* * Internal Reflection limit exceeded -- just let * the ray escape, continuing on current course. * This will cause some energy from somewhere in the * scene to be received through this glass, * which is much better than just returning * grey or black, as before. */ if ((R_DEBUG&(RDEBUG_SHOWERR|RDEBUG_REFRACT)) && ( count++ < MSG_PROLOGUE || (count%MSG_INTERVAL) == 3 )) { bu_log("rr_render: %d, %d Int.reflect=%d: %s lvl=%d\n", sub_ap.a_x, sub_ap.a_y, sub_ap.a_level, pp->pt_regionp->reg_name, ap->a_level); } VMOVE(sub_ap.a_ray.r_dir, incident_dir); goto do_exit; } do_exit: /* * Compute internal spectral transmittance. * Bouger's law. pg 30 of "color science" * * Apply attenuation factor due to thickness of the glass. * sw_extinction is in terms of fraction of light absorbed * per linear meter of glass. a_cumlen is in mm. */ /* XXX extinction should be a spectral curve, not scalor */ if (swp->sw_extinction > 0 && sub_ap.a_cumlen > 0) { attenuation = pow(10.0, -1.0e-3 * sub_ap.a_cumlen * swp->sw_extinction); } else { attenuation = 1; } /* * Process the escaping refracted ray. * This is the only place we might recurse dangerously, * so we are careful to use our caller's recursion level+1. * NOTE: point & direction already filled in */ sub_ap.a_hit = ap->a_hit; sub_ap.a_miss = ap->a_miss; sub_ap.a_logoverlap = ap->a_logoverlap; sub_ap.a_onehit = ap->a_onehit; sub_ap.a_level = ap->a_level+1; sub_ap.a_uptr = ap->a_uptr; sub_ap.a_rbeam = ap->a_rbeam + swp->sw_hit.hit_dist * ap->a_diverge; sub_ap.a_diverge = 0.0; if (code == 3) { sub_ap.a_purpose = "rr recurse on next glass"; sub_ap.a_flag = 0; } else { sub_ap.a_purpose = "rr recurse on escaping internal ray"; sub_ap.a_flag = 1; sub_ap.a_onehit = sub_ap.a_onehit > -3 ? -3 : sub_ap.a_onehit; } /* sub_ap.a_refrac_index was set to RI of next material by rr_hit(). */ sub_ap.a_cumlen = 0; (void) rt_shootray(&sub_ap); /* a_user has hit/miss flag! */ if (sub_ap.a_user == 0) { #ifdef RT_MULTISPECTRAL ms_transmit_color = bn_tabdata_dup(background); #else VMOVE(transmit_color, background); #endif sub_ap.a_cumlen = 0; } else { #ifdef RT_MULTISPECTRAL ms_transmit_color = bn_tabdata_dup(sub_ap.a_spectrum); #else VMOVE(transmit_color, sub_ap.a_color); #endif } transmit *= attenuation; #ifdef RT_MULTISPECTRAL bn_tabdata_mul(ms_transmit_color, ms_filter_color, ms_transmit_color); #else VELMUL(transmit_color, filter_color, transmit_color); #endif if (R_DEBUG&RDEBUG_REFRACT) { bu_log("rr_render: lvl=%d end of xmit through %s\n", ap->a_level, pp->pt_regionp->reg_name); } } else {
/* * M A I N */ int main(int argc, char **argv) { struct rt_i *rtip = NULL; char *title_file = NULL, *title_obj = NULL; /* name of file and first object */ char idbuf[RT_BUFSIZE] = {0}; /* First ID record info */ void application_init(); struct bu_vls times; int i; #if defined(_WIN32) && !defined(__CYGWIN__) setmode(fileno(stdin), O_BINARY); setmode(fileno(stdout), O_BINARY); setmode(fileno(stderr), O_BINARY); #else bu_setlinebuf( stdout ); bu_setlinebuf( stderr ); #endif #ifdef HAVE_SBRK beginptr = (char *) sbrk(0); #endif azimuth = 35.0; /* GIFT defaults */ elevation = 25.0; AmbientIntensity=0.4; background[0] = background[1] = 0.0; background[2] = 1.0/255.0; /* slightly non-black */ /* Before option processing, get default number of processors */ npsw = bu_avail_cpus(); /* Use all that are present */ if ( npsw > MAX_PSW ) npsw = MAX_PSW; /* Before option processing, do application-specific initialization */ RT_APPLICATION_INIT( &ap ); application_init(); /* Process command line options */ if ( !get_args( argc, argv ) ) { (void)fputs(usage, stderr); return 1; } /* Identify the versions of the libraries we are using. */ if (rt_verbosity & VERBOSE_LIBVERSIONS) { (void)fprintf(stderr, "%s%s%s%s\n", brlcad_ident(title), rt_version(), bn_version(), bu_version() ); } #if defined(DEBUG) (void)fprintf(stderr, "Compile-time debug symbols are available\n"); #endif #if defined(NO_BOMBING_MACROS) || defined(NO_MAGIC_CHECKING) || defined(NO_BADRAY_CECHKING) || defined(NO_DEBUG_CHECKING) (void)fprintf(stderr, "WARNING: Run-time debugging is disabled and may enhance performance\n"); #endif /* Identify what host we're running on */ if (rt_verbosity & VERBOSE_LIBVERSIONS) { char hostname[512] = {0}; #ifndef _WIN32 if ( gethostname( hostname, sizeof(hostname) ) >= 0 && hostname[0] != '\0' ) (void)fprintf(stderr, "Running on %s\n", hostname); #else sprintf(hostname, "Microsoft Windows"); (void)fprintf(stderr, "Running on %s\n", hostname); #endif } if ( bu_optind >= argc ) { fprintf(stderr, "%s: MGED database not specified\n", argv[0]); (void)fputs(usage, stderr); return 1; } if (rpt_overlap) ap.a_logoverlap = ((void (*)())0); else ap.a_logoverlap = rt_silent_logoverlap; /* If user gave no sizing info at all, use 512 as default */ if ( width <= 0 && cell_width <= 0 ) width = 512; if ( height <= 0 && cell_height <= 0 ) height = 512; /* If user didn't provide an aspect ratio, use the image * dimensions ratio as a default. */ if (aspect <= 0.0) { aspect = (fastf_t)width / (fastf_t)height; } if ( sub_grid_mode ) { /* check that we have a legal subgrid */ if ( sub_xmax >= width || sub_ymax >= height ) { fprintf( stderr, "rt: illegal values for subgrid %d,%d,%d,%d\n", sub_xmin, sub_ymin, sub_xmax, sub_ymax ); fprintf( stderr, "\tFor a %d X %d image, the subgrid must be within 0, 0,%d,%d\n", width, height, width-1, height-1 ); return 1; } } if ( incr_mode ) { int x = height; if ( x < width ) x = width; incr_nlevel = 1; while ( (1<<incr_nlevel) < x ) incr_nlevel++; height = width = 1<<incr_nlevel; if (rt_verbosity & VERBOSE_INCREMENTAL) fprintf(stderr, "incremental resolution, nlevels = %d, width=%d\n", incr_nlevel, width); } /* * Handle parallel initialization, if applicable. */ #ifndef PARALLEL npsw = 1; /* force serial */ #endif if ( npsw < 0 ) { /* Negative number means "all but" npsw */ npsw = bu_avail_cpus() + npsw; } /* allow debug builds to go higher than the max */ if (!(bu_debug & BU_DEBUG_PARALLEL)) { if ( npsw > MAX_PSW ) { npsw = MAX_PSW; } } if (npsw > 1) { rt_g.rtg_parallel = 1; if (rt_verbosity & VERBOSE_MULTICPU) fprintf(stderr, "Planning to run with %d processors\n", npsw ); } else { rt_g.rtg_parallel = 0; } /* Initialize parallel processor support */ bu_semaphore_init( RT_SEM_LAST ); /* * Do not use bu_log() or bu_malloc() before this point! */ if ( bu_debug ) { bu_printb( "libbu bu_debug", bu_debug, BU_DEBUG_FORMAT ); bu_log("\n"); } if ( RT_G_DEBUG ) { bu_printb( "librt rt_g.debug", rt_g.debug, DEBUG_FORMAT ); bu_log("\n"); } if ( rdebug ) { bu_printb( "rt rdebug", rdebug, RDEBUG_FORMAT ); bu_log("\n"); } /* We need this to run rt_dirbuild */ rt_init_resource( &rt_uniresource, MAX_PSW, NULL ); bn_rand_init( rt_uniresource.re_randptr, 0 ); title_file = argv[bu_optind]; title_obj = argv[bu_optind+1]; nobjs = argc - bu_optind - 1; objtab = &(argv[bu_optind+1]); if ( nobjs <= 0 ) { bu_log("%s: no objects specified -- raytrace aborted\n", argv[0]); return 1; } /* Echo back the command line arugments as given, in 3 Tcl commands */ if (rt_verbosity & VERBOSE_MODELTITLE) { struct bu_vls str; bu_vls_init(&str); bu_vls_from_argv( &str, bu_optind, (const char **)argv ); bu_vls_strcat( &str, "\nopendb " ); bu_vls_strcat( &str, title_file ); bu_vls_strcat( &str, ";\ntree " ); bu_vls_from_argv( &str, nobjs <= 16 ? nobjs : 16, (const char **)argv+bu_optind+1 ); if ( nobjs > 16 ) bu_vls_strcat( &str, " ..."); else bu_vls_putc( &str, ';' ); bu_log("%s\n", bu_vls_addr(&str) ); bu_vls_free(&str); } /* Build directory of GED database */ bu_vls_init( × ); rt_prep_timer(); if ( (rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL ) { bu_log("rt: rt_dirbuild(%s) failure\n", title_file); return 2; } ap.a_rt_i = rtip; (void)rt_get_timer( ×, NULL ); if (rt_verbosity & VERBOSE_MODELTITLE) bu_log("db title: %s\n", idbuf); if (rt_verbosity & VERBOSE_STATS) bu_log("DIRBUILD: %s\n", bu_vls_addr(×) ); bu_vls_free( × ); memory_summary(); /* Copy values from command line options into rtip */ rtip->rti_space_partition = space_partition; rtip->rti_nugrid_dimlimit = nugrid_dimlimit; rtip->rti_nu_gfactor = nu_gfactor; rtip->useair = use_air; rtip->rti_save_overlaps = save_overlaps; if ( rt_dist_tol > 0 ) { rtip->rti_tol.dist = rt_dist_tol; rtip->rti_tol.dist_sq = rt_dist_tol * rt_dist_tol; } if ( rt_perp_tol > 0 ) { rtip->rti_tol.perp = rt_perp_tol; rtip->rti_tol.para = 1 - rt_perp_tol; } if (rt_verbosity & VERBOSE_TOLERANCE) rt_pr_tol( &rtip->rti_tol ); /* before view_init */ if ( outputfile && strcmp( outputfile, "-") == 0 ) outputfile = (char *)0; /* * Initialize application. * Note that width & height may not have been set yet, * since they may change from frame to frame. */ if ( view_init( &ap, title_file, title_obj, outputfile!=(char *)0, framebuffer!=(char *)0 ) != 0 ) { /* Framebuffer is desired */ register int xx, yy; int zoom; /* Ask for a fb big enough to hold the image, at least 512. */ /* This is so MGED-invoked "postage stamps" get zoomed up big enough to see */ xx = yy = 512; if ( width > xx || height > yy ) { xx = width; yy = height; } bu_semaphore_acquire( BU_SEM_SYSCALL ); fbp = fb_open( framebuffer, xx, yy ); bu_semaphore_release( BU_SEM_SYSCALL ); if ( fbp == FBIO_NULL ) { fprintf(stderr, "rt: can't open frame buffer\n"); return 12; } bu_semaphore_acquire( BU_SEM_SYSCALL ); /* If fb came out smaller than requested, do less work */ if ( fb_getwidth(fbp) < width ) width = fb_getwidth(fbp); if ( fb_getheight(fbp) < height ) height = fb_getheight(fbp); /* If the fb is lots bigger (>= 2X), zoom up & center */ if ( width > 0 && height > 0 ) { zoom = fb_getwidth(fbp)/width; if ( fb_getheight(fbp)/height < zoom ) zoom = fb_getheight(fbp)/height; } else { zoom = 1; } (void)fb_view( fbp, width/2, height/2, zoom, zoom ); bu_semaphore_release( BU_SEM_SYSCALL ); } if ( (outputfile == (char *)0) && (fbp == FBIO_NULL) ) { /* If not going to framebuffer, or to a file, then use stdout */ if ( outfp == NULL ) outfp = stdout; /* output_is_binary is changed by view_init, as appropriate */ if ( output_is_binary && isatty(fileno(outfp)) ) { fprintf(stderr, "rt: attempting to send binary output to terminal, aborting\n"); return 14; } } /* * Initialize all the per-CPU memory resources. * The number of processors can change at runtime, init them all. */ for ( i=0; i < MAX_PSW; i++ ) { rt_init_resource( &resource[i], i, rtip ); bn_rand_init( resource[i].re_randptr, i ); } memory_summary(); #ifdef SIGUSR1 (void)signal( SIGUSR1, siginfo_handler ); #endif #ifdef SIGINFO (void)signal( SIGINFO, siginfo_handler ); #endif if ( !matflag ) { int frame_retval; def_tree( rtip ); /* Load the default trees */ do_ae( azimuth, elevation ); frame_retval = do_frame( curframe ); if (frame_retval != 0) { /* Release the framebuffer, if any */ if ( fbp != FBIO_NULL ) { fb_close(fbp); } return 1; } } else if ( !isatty(fileno(stdin)) && old_way( stdin ) ) { ; /* All is done */ } else { register char *buf; register int ret; /* * New way - command driven. * Process sequence of input commands. * All the work happens in the functions * called by rt_do_cmd(). */ while ( (buf = rt_read_cmd( stdin )) != (char *)0 ) { if ( R_DEBUG&RDEBUG_PARSE ) fprintf(stderr, "cmd: %s\n", buf ); ret = rt_do_cmd( rtip, buf, rt_cmdtab ); bu_free( buf, "rt_read_cmd command buffer" ); if ( ret < 0 ) break; } if ( curframe < desiredframe ) { fprintf(stderr, "rt: Desired frame %d not reached, last was %d\n", desiredframe, curframe); } } /* Release the framebuffer, if any */ if (fbp != FBIO_NULL) { fb_close(fbp); } return(0); }
int main(int argc, char **argv) { /* START # 1 */ struct application ap; /* Structure passed between functions. */ static struct rt_i *rtip; /* *rtip pointer to structure of */ /* type rt_i */ char idbuf[132]; /* first ID record info, used in */ /* rt_dirbuild */ int index; /* index for rt_dirbuild & rt_gettree */ FILE *fp; /* used in opening file for second pass */ char spfile[16]; /* second pass file name */ FILE *fp1=NULL; /* conductivity file */ char confile[16]; /* conductivity file */ FILE *fp2; /* conductivity table file */ char tblfile[16]; /* conductivity table file */ int i, j; /* integers used in loops */ int numreg; /* number of regions */ int nmged; /* number of regions in mged file */ double gridspace; /* spacing between fired rays */ int iwrite; /* 0 => write to standard out, 1 => write */ /* to file */ int typeout; /* Type of file to be written, 0 => PRISM file, */ /* 1 => generic file. */ FILE *fp6; /* Used in writing generic file. */ char genfile[16]; /* Generic file name. */ FILE *fp3=NULL; /* used for writing output to file */ char filename[16]; /* output file name */ FILE *fp5; /* material file */ char filemat[16]; /* material file */ char line[150]; /* used for reading a line from a file */ double k[41]; /* thermal conductivity */ int itype; /* type of length measurement to use for */ /* rk calculations */ double rki, rkj; /* used in finding rk */ double ki, kj; /* thermal conductivity of region */ double leni, lenj; /* lengths used in finding rk */ double areai; /* areas used in finding rk */ double a1; /* area used in writing conductivity table */ double l1, l2, l3, l4; /* lengths used in writing conductivity table */ FILE *fp4; /* error file */ char fileerr[16]; /* error file */ double angle[3]; /* Angles of rotation. angle[0]-rotation about */ /* x-axis, angle[1]-rotation about y-axis, & */ /* angle[2]-rotation about z-axis. */ double strtpt[3]; /* Starting point of fired ray. */ double strtdir[3]; /* Starting direction of fired ray. */ double r[3], t[3]; /* Used in computing rotations. */ double center[3]; /* Center point of bounding rpp. */ double diagonal; /* Length of diagonal of bounding rpp. */ double xmin, xmax; /* Maximum & minimum x of grid. */ double ymin, ymax; /* Maximum & minimum y of grid. */ double zmin, zmax; /* Maximum & minimum z of grid. */ int nadjreg; /* Number of adjacent regions. */ int prmrel; /* PRISM release number, 2=>2.0, 3=>3.0. */ int ifire; /* Number of sets of rays to be fired, 0=> */ /* fire from 3 orthogonal postions, 1=>fire */ /* from 1 position. */ /* Check to see if arguments implimented correctly. */ if (argv[1] == NULL || argv[2] == NULL) { (void)fprintf(stderr, "\nusage: secpass file.g objects\n\n"); } else { /* START # 2 */ /* Ask if output goes to standard out or to a file. */ (void)fprintf(stdout, "Write output to standard out (0) or a file(1) "); (void)fprintf(stdout, "not at all (2)? "); (void)fflush(stdout); (void)scanf("%d", &iwrite); if ((iwrite != 0) && (iwrite != 1)) iwrite=2; if (iwrite == 1) { (void)fprintf(stdout, "Enter name of output file (15 char max). "); (void)fflush(stdout); (void)scanf("%15s", filename); fp3 = fopen(filename, "wb"); } /* Which file that has second pass information in it? */ (void)fprintf(stdout, "Enter name of file that has second pass "); (void)fprintf(stdout, "information\nin it (15 char max). "); (void)fflush(stdout); (void)scanf("%15s", spfile); /* Ask for type of output file to be generated. */ (void)printf("Enter type of output file to be generated.\n"); (void)printf("\t 0 - PRISM File\n"); (void)printf("\t 1 - Generic File\n"); (void)fflush(stdout); (void)scanf("%d", &typeout); /* Read name of file to write conductivity information */ /* to for use in PRISM. */ if (typeout == 0) { (void)fprintf(stdout, "Enter name of file to be created for PRISM "); (void)fprintf(stdout, "conductivity\ninformation (15 char max). "); (void)fflush(stdout); (void)scanf("%15s", confile); /* Find which release of PRISM is being used. The format */ /* for writing region numbers is I3 for PRISM 2.0 & I6 for */ /* PRISM 3.0. */ prmrel = 2; (void)printf("Which release of PRISM is being used, 2.0 (2) "); (void)printf("or 3.0 (3)? "); (void)fflush(stdout); (void)scanf("%d", &prmrel); if (prmrel != 3) prmrel = 2; } /* Read generic file name if necessary. */ if (typeout == 1) { (void)printf("Enter name of generic file to be created (15 char "); (void)printf("max). "); (void)fflush(stdout); (void)scanf("%15s", genfile); } /* Which calculated length should be used when writing to */ /* this file: 1 -> average length, 2 -> rms length, 3 -> */ /* minimum length, and 4 -> maximum length. */ (void)fprintf(stdout, "Which length calculation should be used when\n"); (void)fprintf(stdout, "computing conduction\nbetween regions?\n"); (void)fprintf(stdout, "\t1 - average length\n"); (void)fprintf(stdout, "\t2 - rms length\n"); (void)fprintf(stdout, "\t3 - minimum length\n"); (void)fprintf(stdout, "\t4 - maximum length\n"); (void)fflush(stdout); (void)scanf("%d", &itype); /* Read name of file to write conductivity information to */ /* in table format. */ (void)fprintf(stdout, "Enter name of file to be created for "); (void)fprintf(stdout, "conductivity\ntable (15 char max). "); (void)fflush(stdout); (void)scanf("%15s", tblfile); /* Read name of material file that contains thermal */ /* conductivity information. */ (void)fprintf(stdout, "Enter name of material file (15 char max). "); (void)fflush(stdout); (void)scanf("%15s", filemat); /* Read name of error file. */ (void)fprintf(stdout, "Enter name of error file to be created "); (void)fprintf(stdout, "(15 char max). "); (void)fflush(stdout); (void)scanf("%15s", fileerr); /* Choose whether 3 orthogonal sets of rays are to be fired */ /* or 1 set of rays is to be fired. */ (void)printf("Should there be 3 sets of orhogonal rays fired "); (void)printf("(0) or 1 set (1)?\n\t"); (void)fflush(stdout); (void)scanf("%d", &ifire); if (ifire != 0) ifire = 1; if (ifire == 0) { (void)printf("3 sets of orthogonal rays will be fired.\n"); } if (ifire == 1) { (void)printf("1 set of rays will be fired.\n"); } (void)fflush(stdout); /* Write out file information. */ if (iwrite ==1) { (void)fprintf(fp3, "\nsecond pass file: %s\n", spfile); (void)fprintf(fp3, "material file: %s\n", filemat); if (typeout == 0) { (void)fprintf(fp3, "conductivity file for use "); (void)fprintf(fp3, "with PRISM: %s\n", confile); (void)fprintf(fp3, " (format is PRISM %d.0)\n", prmrel); } if (typeout == 1) (void)fprintf(fp3, "generic file: %s\n", genfile); (void)fflush(fp3); if (itype == 1) (void)fprintf(fp3, "\taverage length being used\n"); if (itype == 2) (void)fprintf(fp3, "\trms length being used\n"); if (itype == 3) (void)fprintf(fp3, "\tminimum length being used\n"); if (itype == 4) (void)fprintf(fp3, "\tmaximum length being used\n"); (void)fprintf(fp3, "conductivity table file: %s\n", tblfile); (void)fprintf(fp3, "error file: %s\n\n", fileerr); (void)fflush(fp3); } /* Read thermal conductivity file. */ fp5 = fopen(filemat, "rb"); for (i=0; i<41; i++) { (void)bu_fgets(line, 151, fp5); (void)sscanf(line, "%*d%*f%*f%*f%*f%lf", &k[i]); } /* Print out the thermal conductivity. */ /* * for (i=0; i<41; i++) * { * (void)fprintf(stdout, " thermal conductivity %d = %f\n", i, k[i]); * (void)fflush(stdout); * } */ /* Build the directory. */ index = 1; /* Set index for rt_dirbuild. */ rtip=rt_dirbuild(argv[index], idbuf, sizeof(idbuf)); (void)fprintf(stdout, "Database title: %s\n", idbuf); (void)fflush(stdout); /* Set useair to 1, to show hits of air. */ rtip->useair = 1; /* Load desired objects. */ index = 2; /* Set index for rt_gettree. */ while (argv[index] != NULL) { rt_gettree(rtip, argv[index]); index += 1; } /* Find total number of regions in mged file. */ nmged = (int)rtip->nregions; (void)fprintf(stdout, "Number of regions in mged file: %d\n", nmged); (void)fflush(stdout); if (iwrite == 1) { (void)fprintf(fp3, "Number of regions in mged file: %d\n", nmged); (void)fflush(fp3); } /* Number of regions known, everything can be malloced. */ (void)fprintf(stdout, "Mallocing arrays.\n"); (void)fflush(stdout); cond = (struct table *)bu_malloc( nmged * sizeof(struct table), "cond" ); (void)fprintf(stdout, "cond malloced\n"); (void)fflush(stdout); for (i=0; i<nmged; i++) { cond[i].shrarea = (double *)bu_malloc( nmged * sizeof(double), "cond[i].shrarea" ); cond[i].avglen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].avglen" ); cond[i].rmslen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rmslen" ); cond[i].minlen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].minlen" ); cond[i].maxlen = (double *)bu_malloc( nmged * sizeof(double), "cond[i].maxlen" ); cond[i].numcal = (double *)bu_malloc( nmged * sizeof(double), "cond[i].numcal" ); cond[i].rkavg = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkavg" ); cond[i].rkrms = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkrms" ); cond[i].rkmin = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkmin" ); cond[i].rkmax = (double *)bu_malloc( nmged * sizeof(double), "cond[i].rkmax" ); } (void)fprintf(stdout, "loop malloced\n"); (void)fflush(stdout); /* All variables 'dimensioned', now zero all variables. */ for (i=0; i<nmged; i++) { cond[i].centroid[0] = (double)0.; cond[i].centroid[1] = (double)0.; cond[i].centroid[2] = (double)0.; cond[i].mat = (int)0; for (j=0; j<nmged; j++) { cond[i].shrarea[j] = (double)0.; cond[i].avglen[j] = (double)0.; cond[i].rmslen[j] = (double)0.; cond[i].minlen[j] = (double)0.; cond[i].maxlen[j] = (double)0.; cond[i].numcal[j] = (double)0.; cond[i].rkavg[j] = (double)0.; cond[i].rkrms[j] = (double)0.; cond[i].rkmin[j] = (double)0.; cond[i].rkmax[j] = (double)0.; } } (void)fprintf(stdout, "All variables zeroed.\n"); (void)fflush(stdout); /* Now open file with second pass information in it. */ fp = fopen(spfile, "rb"); (void)fprintf(stdout, "second pass file opened\n"); (void)fflush(stdout); /* Read number of regions in file. */ (void)fscanf(fp, "%d\n", &numreg); (void)fprintf(stdout, "The number of regions read was %d\n", numreg); (void)fflush(stdout); if (iwrite == 1) { (void)fprintf(fp3, "number of regions read from second "); (void)fprintf(fp3, "pass file: %d\n", numreg); (void)fflush(fp3); } /* Read all information in file. */ for (i=0; i<numreg; i++) { (void)fscanf(fp, "%*d%le%le%le%d\n", &cond[i].centroid[0], &cond[i].centroid[1], &cond[i].centroid[2], &cond[i].mat); /* * (void)fprintf(stdout, "reg=%8d, centroid: %10.0f, %10.0f, %10.0f\n", * i, cond[i].centroid[0], cond[i].centroid[1], cond[i].centroid[2]); * (void)fflush(stdout); */ for (j=0; j<numreg; j++) { (void)fscanf(fp, "%*d%le\n", &cond[i].shrarea[j]); /* * (void)fprintf(stdout, "\treg=%8d, area=%10.0f\n", * j, cond[i].shrarea[j]); * (void)fflush(stdout); */ } } (void)fclose(fp); /* Check that the number of regions in the mged file */ /* and the second pass file are equal. */ if (nmged != numreg) { (void)fprintf(stdout, "ERROR -- The number of regions in the mged\n"); (void)fprintf(stdout, "file (%d) does not equal the number of\n", nmged); (void)fprintf(stdout, "regions in the second pass file (%d).\n", numreg); (void)fprintf(stdout, "Watch for unexplained errors.\n"); (void)fflush(stdout); if (iwrite == 1) { (void)fprintf(fp3, "ERROR -- The number of regions in the mged\n"); (void)fprintf(fp3, "file (%d) does not equal the number of\n", nmged); (void)fprintf(fp3, "regions in the second pass file (%d).\n", numreg); (void)fprintf(fp3, "Watch for unexplained errors.\n"); (void)fflush(fp3); } } /* Get database ready by starting preparation. */ rt_prep(rtip); /* Find center of bounding rpp. */ center[X] = rtip->mdl_min[X] + (rtip->mdl_max[X] - rtip->mdl_min[X]) / 2.; center[Y] = rtip->mdl_min[Y] + (rtip->mdl_max[Y] - rtip->mdl_min[Y]) / 2.; center[Z] = rtip->mdl_min[Z] + (rtip->mdl_max[Z] - rtip->mdl_min[Z]) / 2.; /* Find length of diagonal. */ diagonal = (rtip->mdl_max[X] - rtip->mdl_min[X]) * (rtip->mdl_max[X] - rtip->mdl_min[X]) + (rtip->mdl_max[Y] - rtip->mdl_min[Y]) * (rtip->mdl_max[Y] - rtip->mdl_min[Y]) + (rtip->mdl_max[Z] - rtip->mdl_min[Z]) * (rtip->mdl_max[Z] - rtip->mdl_min[Z]); diagonal = sqrt(diagonal) / 2. + .5; /* Find minimum & maximum of grid. */ xmin = center[X] - diagonal; xmax = center[X] + diagonal; ymin = center[Y] - diagonal; ymax = center[Y] + diagonal; zmin = center[Z] - diagonal; zmax = center[Z] + diagonal; /* Print center of bounding rpp, diagonal, & maximum */ /* & minimum of grid. */ (void)fprintf(stdout, "Center of bounding rpp ( %f, %f, %f )\n", center[X], center[Y], center[Z]); (void)fprintf(stdout, "Length of diagonal of bounding rpp: %f\n", diagonal); (void)fprintf(stdout, "Minimums & maximums of grid:\n"); (void)fprintf(stdout, " %f - %f\n", xmin, xmax); (void)fprintf(stdout, " %f - %f\n", ymin, ymax); (void)fprintf(stdout, " %f - %f\n\n", zmin, zmax); (void)fflush(stdout); /* Write model minimum & maximum. */ (void)fprintf(stdout, "Model minimum & maximum.\n"); (void)fprintf(stdout, "\tX: %f to %f\n\tY: %f to %f\n\tZ: %f to %f\n\n", rtip->mdl_min[X], rtip->mdl_max[X], rtip->mdl_min[Y], rtip->mdl_max[Y], rtip->mdl_min[Z], rtip->mdl_max[Z]); (void)fflush(stdout); if (iwrite == 1) { (void)fprintf(fp3, "Model minimum & maximum.\n"); (void)fprintf(fp3, "\tX: %f to %f\n\tY: %f kto %f\n", rtip->mdl_min[X], rtip->mdl_max[X], rtip->mdl_min[Y], rtip->mdl_max[Y]); (void)fprintf(fp3, "\tZ: %f to %f\n\n", rtip->mdl_min[Z], rtip->mdl_max[Z]); (void)fflush(fp3); } /* User enters grid spacing. All units are in mm. */ (void)fprintf(stdout, "Enter spacing (mm) between fired rays. "); (void)fflush(stdout); (void)scanf("%lf", &gridspace); (void)fprintf(stdout, "\ngrid spacing: %f\n", gridspace); (void)fflush(stdout); if (iwrite == 1) { (void)fprintf(fp3, "gridspacing: %f\n\n", gridspace); (void)fflush(fp3); } /* Set up parameters for rt_shootray. */ RT_APPLICATION_INIT(&ap); ap.a_hit = hit; /* User supplied hit function. */ ap.a_miss = miss; /* User supplied miss function. */ ap.a_overlap = ovrlap; /* user supplied overlap function. */ ap.a_rt_i = rtip; /* Pointer from rt_dirbuild. */ ap.a_onehit = 0; /* Hit flag (returns all hits). */ ap.a_level = 0; /* Recursion level for diagnostics. */ ap.a_resource = 0; /* Address of resource structure (NULL). */ /* Put angles for rotation into radians. */ angle[X] = radians((double)GAMMA); angle[Y] = radians((double)BETA); angle[Z] = radians((double)ALPHA); /* Set up and shoot down the 1st axis, positive to negative */ /* (x-axis). */ (void)fprintf(stdout, "\nShooting down 1st axis.\n"); (void)fflush(stdout); strtpt[X] = xmax; strtpt[Y] = ymin + gridspace / 2.; strtpt[Z] = zmin + gridspace / 2.; strtdir[X] = (-1); strtdir[Y] = 0; strtdir[Z] = 0; /* Rotate starting point. (new pt = C + R[P -C]) */ t[X] = strtpt[X] - center[X]; t[Y] = strtpt[Y] - center[Y]; t[Z] = strtpt[Z] - center[Z]; (void)rotate(t, angle, r); ap.a_ray.r_pt[X] = center[X] + r[X]; ap.a_ray.r_pt[Y] = center[Y] + r[Y]; ap.a_ray.r_pt[Z] = center[Z] + r[Z]; /* Rotate firing direction. (new dir = R[D]) */ (void)rotate(strtdir, angle, r); ap.a_ray.r_dir[X] = r[X]; ap.a_ray.r_dir[Y] = r[Y]; ap.a_ray.r_dir[Z] = r[Z]; while (strtpt[Z] <= zmax) { /* START # 3 */ iprev = (-1); /* No previous shots. */ /* Call rt_shootray. */ (void)rt_shootray ( &ap ); strtpt[Y] += gridspace; if (strtpt[Y] > ymax) { strtpt[Y] = ymin + gridspace / 2.; strtpt[Z] += gridspace; } t[X] = strtpt[X] - center[X]; t[Y] = strtpt[Y] - center[Y]; t[Z] = strtpt[Z] - center[Z]; (void)rotate(t, angle, r); ap.a_ray.r_pt[X] = center[X] + r[X]; ap.a_ray.r_pt[Y] = center[Y] + r[Y]; ap.a_ray.r_pt[Z] = center[Z] + r[Z]; } /* END # 3 */ /* Shoot down 2nd & 3rd axes if necessary. */ if (ifire == 0) { /* START # 1000 */ /* Set up & shoot down the 2nd axis (y-axis). */ (void)printf("\nShooting down the 2nd axis.\n"); (void)fflush(stdout); strtpt[X] = xmin + gridspace / 2.; strtpt[Y] = ymax; strtpt[Z] = zmin + gridspace / 2.; strtdir[X] = 0.; strtdir[Y] = (-1.); strtdir[X] = 0.; /* Rotate starting point (new pt = C + R[P - C]). */ t[X] = strtpt[X] - center [X]; t[Y] = strtpt[Y] - center [Y]; t[Z] = strtpt[Z] - center [Z]; (void)rotate(t, angle, r); ap.a_ray.r_pt[X] = center[X] + r[X]; ap.a_ray.r_pt[Y] = center[Y] + r[Y]; ap.a_ray.r_pt[Z] = center[Z] + r[Z]; /* Rotate firing direction (new dir = R[D]) */ (void)rotate(strtdir, angle, r); ap.a_ray.r_dir[X] = r[X]; ap.a_ray.r_dir[Y] = r[Y]; ap.a_ray.r_dir[Z] = r[Z]; while (strtpt[Z] <= zmax) { /* START # 1010 */ iprev = (-1); /* No previous shots. */ /* Call rt_shootray. */ (void)rt_shootray(&ap); strtpt[X] += gridspace; if (strtpt[X] > xmax) { strtpt[X] = xmin + gridspace / 2.; strtpt[Z] += gridspace; } t[X] = strtpt[X] - center[X]; t[Y] = strtpt[Y] - center[Y]; t[Z] = strtpt[Z] - center[Z]; (void)rotate(t, angle, r); ap.a_ray.r_pt[X] = center[X] + r[X]; ap.a_ray.r_pt[Y] = center[Y] + r[Y]; ap.a_ray.r_pt[Z] = center[Z] + r[Z]; } /* END # 1010 */ /* Set up & shoot down the 3rd axis (z-axis). */ (void)printf("\nShooting down the 3rd axis.\n"); (void)fflush(stdout); strtpt[X] = xmin + gridspace / 2.; strtpt[Y] = ymin + gridspace / 2.; strtpt[Z] = zmax; strtdir[X] = 0.; strtdir[Y] = 0.; strtdir[Z] = (-1.); /* Rotate starting points (new pt = C + R[P - C]). */ t[X] = strtpt[X] - center[X]; t[Y] = strtpt[Y] - center[Y]; t[Z] = strtpt[Z] - center[Z]; (void)rotate(t, angle, r); ap.a_ray.r_pt[X] = r[X]; ap.a_ray.r_pt[Y] = r[Y]; ap.a_ray.r_pt[Z] = r[Z]; while (strtpt[Y] <= ymax) { /* START # 1020 */ iprev = (-1); /* No previous shots. */ /* Call rt_shootray. */ (void)rt_shootray(&ap); strtpt[X] += gridspace; if (strtpt[X] > xmax) { strtpt[X] = xmin + gridspace / 2.; strtpt[Y] += gridspace; } t[X] = strtpt[X] - center[X]; t[Y] = strtpt[Y] - center[Y]; t[Z] = strtpt[Z] - center[Z]; (void)rotate(t, angle, r); ap.a_ray.r_pt[X] = center[X] + r[X]; ap.a_ray.r_pt[Y] = center[Y] + r[Y]; ap.a_ray.r_pt[Z] = center[Z] + r[Z]; } /* END # 1020 */ } /* END # 1000 */ /* Calculate final length between centroid & shared surface area. */ if (iwrite == 0) { (void)fprintf(stdout, "\n\nFinal numbers.\n"); (void)fflush(stdout); } for (i=0; i<numreg; i++) { if (iwrite == 0) { (void)fprintf(stdout, "reg#=%d, matid=%d\n", (i+1), cond[i].mat); (void)fflush(stdout); } if (iwrite == 1) { (void)fprintf(fp3, "reg#=%d, matid=%d\n", (i+1), cond[i].mat); (void)fflush(fp3); } for (j=0; j<numreg; j++) { if (cond[i].numcal[j] > ZEROTOL) { cond[i].avglen[j] /= cond[i].numcal[j]; cond[i].rmslen[j] /= cond[i].numcal[j]; cond[i].rmslen[j] = sqrt(cond[i].rmslen[j]); if (iwrite == 0) { (void)fprintf(stdout, "\tadjreg=%d, numcal=%f, shrarea=%f, ", (j+1), cond[i].numcal[j], cond[i].shrarea[j]); (void)fprintf(stdout, "avglen=%f\n", cond[i].avglen[j]); (void)fprintf(stdout, "\t\trmslen=%f, ", cond[i].rmslen[j]); (void)fprintf(stdout, "minlen=%f, maxlen=%f\n", cond[i].minlen[j], cond[i].maxlen[j]); (void)fflush(stdout); } if (iwrite == 1) { (void)fprintf(fp3, "\tadjreg=%d, numcal=%f, shrarea=%f, ", (j+1), cond[i].numcal[j], cond[i].shrarea[j]); (void)fprintf(fp3, "avglen=%f\n", cond[i].avglen[j]); (void)fprintf(fp3, "\t\trmslen=%f, ", cond[i].rmslen[j]); (void)fprintf(fp3, "minlen=%f, maxlen=%f\n", cond[i].minlen[j], cond[i].maxlen[j]); (void)fflush(fp3); } } else { cond[i].avglen[j] = 0.; cond[i].rmslen[j] = 0.; } } } if (iwrite == 1) { /* Print summary of all files used. */ (void)fprintf(fp3, "\n\nSUMMARY OF FILES USED & CREATED\n"); (void)fprintf(fp3, "\t.g file used: %s\n", argv[1]); (void)fprintf(fp3, "\tregions used:\n"); (void)fflush(fp3); i=2; while (argv[i] != NULL) { (void)fprintf(fp3, "\t\t%s\n", argv[i]); (void)fflush(fp3); i++; } (void)fprintf(fp3, "\tfile containing second pass information: %s\n", spfile); (void)fprintf(fp3, "\tmaterial file used: %s\n", filemat); (void)fprintf(fp3, "\toutput file created: %s\n", filename); if (typeout == 0) { (void)fprintf(fp3, "\tconductivity file created: %s\n", confile); (void)fprintf(fp3, "\t (format is PRISM %d.0)\n", prmrel); } if (typeout == 1) (void)fprintf(fp3, "\tgeneric file created: %s\n" , genfile); (void)fprintf(fp3, "\tconductivity table file created: %s\n", tblfile); (void)fprintf(fp3, "\terror file created: %s\n\n\n", fileerr); (void)fflush(fp3); (void)fclose(fp3); } /*------------------------------------------------------------------*/ /* Open conductivity file to be used with PRISM if needed. */ if (typeout == 0) { fp1=fopen(confile, "wb"); (void)fprintf(fp1, "Conductivity file for use with PRISM.\n"); (void)fflush(fp1); } /* Make calculations & write to conductivity file. */ for (i=0; i<numreg; i++) { /* START # 6 */ /* Make conductivity file triangular. This program still */ /* computes the ENTIRE matrix. */ for (j=(i+1); j<numreg; j++) { /* START # 7 */ if ( (cond[i].avglen[j] != 0) ) { /* START # 8 */ /* Find correct thermal conductivity. */ /* If ki or kj = 0 => rk = 0. */ ki = k[cond[i].mat]; kj = k[cond[j].mat]; /* All calculations will be in meters & */ /* square meters. */ areai = cond[i].shrarea[j] * 1.e-6; /* average length */ leni = cond[i].avglen[j] * 1.e-3; lenj = cond[j].avglen[i] * 1.e-3; if (((-ZEROTOL < ki) && (ki < ZEROTOL)) || ((-ZEROTOL < kj) && (kj < ZEROTOL))) cond[i].rkavg[j] = 0.; else { rki = leni / (ki * areai); rkj = lenj / (kj * areai); cond[i].rkavg[j] = 1. / (rki + rkj); } /* rms length */ leni = cond[i].rmslen[j] * 1.e-3; lenj = cond[j].rmslen[i] * 1.e-3; if (((-ZEROTOL < ki) && (ki < ZEROTOL)) || ((-ZEROTOL < kj) && (kj < ZEROTOL))) cond[i].rkrms[j] = 0.; else { rki = leni / (ki * areai); rkj = lenj / (kj * areai); cond[i].rkrms[j] = 1. / (rki + rkj); } /* minimum length */ leni = cond[i].minlen[j] * 1.e-3; lenj = cond[j].minlen[i] * 1.e-3; if (((-ZEROTOL < ki) && (ki < ZEROTOL)) || ((-ZEROTOL < kj) && (kj < ZEROTOL))) cond[i].rkmin[j] = 0.; else { rki = leni / (ki * areai); rkj = lenj / (kj * areai); cond[i].rkmin[j] = 1. / (rki + rkj); } /* maximum length */ leni = cond[i].maxlen[j] * 1.e-3; lenj = cond[j].maxlen[i] * 1.e-3; if (((-ZEROTOL < ki) && (ki < ZEROTOL)) || ((-ZEROTOL < kj) && (kj < ZEROTOL))) cond[i].rkmax[j] = 0.; else { rki = leni / (ki * areai); rkj = lenj / (kj * areai); cond[i].rkmax[j] = 1. / (rki + rkj); } /* Print if had adjacent regions, conductivity */ /* may be zero. */ /* Print only if PRISM file is to be created. */ if (typeout == 0) { /* START # 8A */ if ( (itype == 1) && (cond[i].shrarea[j] > ZEROTOL) ) { if (prmrel == 2) (void)fprintf(fp1, "%3d %3d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkavg[j], (cond[i].shrarea[j] * 1.0e-6)); if (prmrel == 3) (void)fprintf(fp1, "%6d %6d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkavg[j], (cond[i].shrarea[j] * 1.0e-6)); } if ( (itype == 2) && (cond[i].shrarea[j] > ZEROTOL) ) { if (prmrel == 2) (void)fprintf(fp1, "%3d %3d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkrms[j], (cond[i].shrarea[j] * 1.0e-6)); if (prmrel == 3) (void)fprintf(fp1, "%6d %6d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkrms[j], (cond[i].shrarea[j] * 1.0e-6)); } if ( (itype == 3) && (cond[i].shrarea[j] > ZEROTOL) ) { if (prmrel == 2) (void)fprintf(fp1, "%3d %3d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkmin[j], (cond[i].shrarea[j] * 1.0e-6)); if (prmrel == 3) (void)fprintf(fp1, "%6d %6d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkmin[j], (cond[i].shrarea[j] * 1.0e-6)); } if ( (itype == 4) && (cond[i].shrarea[j] > ZEROTOL) ) { if (prmrel == 2) (void)fprintf(fp1, "%3d %3d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkmax[j], (cond[i].shrarea[j] * 1.0e-6)); if (prmrel == 3) (void)fprintf(fp1, "%6d %6d %7.3f %.3e\n", (j+1), (i+1), cond[i].rkmax[j], (cond[i].shrarea[j] * 1.0e-6)); } (void)fflush(fp1); } /* END of # 8A */ } /* END # 8 */ } /* END # 7 */ } /* END # 6 */ if (typeout == 0) (void)fclose(fp1); /*------------------------------------------------------------------*/ /* Open and write to generic file if necessary. */ /* The format follows. */ /* 4 region number number of adjacent regions */ /* adjacent region shared area conduction distance */ if (typeout == 1) { /* Open file. */ fp6 = fopen(genfile, "wb"); (void)printf("Opened generic file.\n"); (void)fflush(stdout); for (i=0; i<numreg; i++) { /* Find number of adjacent regions. */ /* * (void)printf("Ready to find number of adjacent areas.\n"); * (void)fflush(stdout); */ nadjreg = 0; /* * (void)printf("nadjreg = %d\n", nadjreg); * (void)fflush(stdout); */ for (j=0; j<numreg; j++) { /* * (void)printf("%d, %d, %f\n", i, j, cond[i].shrarea[j]); * (void)fflush(stdout); */ if (cond[i].shrarea[j] > ZEROTOL) nadjreg += 1; } /* * (void)printf("Found number of adjacent areas.\n"); * (void)fflush(stdout); */ (void)fprintf(fp6, "4 %5d %5d\n", (i+1), nadjreg); (void)fflush(fp6); for (j=0; j<numreg; j++) { if (cond[i].shrarea[j] > ZEROTOL) { (void)fprintf(fp6, " %5d %.3e ", (j+1), (cond[i].shrarea[j] * 1.e-6)); if (itype == 1) (void)fprintf(fp6, "%.3e\n", (cond[i].avglen[j] * 1.e-3)); if (itype == 2) (void)fprintf(fp6, "%.3e\n", (cond[i].rmslen[j] * 1.e-3)); if (itype == 3) (void)fprintf(fp6, "%.3e\n", (cond[i].minlen[j] * 1.e-3)); if (itype == 4) (void)fprintf(fp6, "%.3e\n", (cond[i].maxlen[j] * 1.e-3)); } (void)fflush(fp6); } } (void)fclose(fp6); } /*------------------------------------------------------------------*/ /* Open conductivity table file and write information to */ /* it. All units will be in meters or square meters. */ fp2=fopen(tblfile, "wb"); (void)fprintf(fp2, "Conductivity table. Units are in meters or "); (void)fprintf(fp2, "square meters.\n"); (void)fprintf(fp2, " reg, mat, adj, shrarea,"); (void)fprintf(fp2, " avglen, rkavg,"); (void)fprintf(fp2, " rmslen, rkrms,"); (void)fprintf(fp2, " minlen, rkmin,"); (void)fprintf(fp2, " maxlen, rkmax\n"); (void)fflush(fp2); for (i=0; i<numreg; i++) { /* START # 9 */ for (j=0; j<numreg; j++) { /* START # 10 */ if (cond[i].shrarea[j] != 0) { /* START # 11 */ a1 = cond[i].shrarea[j] * 1.e-6; l1 = cond[i].avglen[j] * 1.e-3; l2 = cond[i].rmslen[j] * 1.e-3; l3 = cond[i].minlen[j] * 1.e-3; l4 = cond[i].maxlen[j] * 1.e-3; (void)fprintf(fp2, "%4d,%4d,%4d, %.3e,", (i+1), cond[i].mat, (j+1), a1); if (j > i) { (void)fprintf(fp2, " %.3e, %.3e,", l1, cond[i].rkavg[j]); (void)fprintf(fp2, " %.3e, %.3e,", l2, cond[i].rkrms[j]); (void)fprintf(fp2, " %.3e, %.3e,", l3, cond[i].rkmin[j]); (void)fprintf(fp2, " %.3e, %.3e\n", l4, cond[i].rkmax[j]); } else { (void)fprintf(fp2, " %.3e, %.3e,", l1, cond[j].rkavg[i]); (void)fprintf(fp2, " %.3e, %.3e,", l2, cond[j].rkrms[i]); (void)fprintf(fp2, " %.3e, %.3e,", l3, cond[j].rkmin[i]); (void)fprintf(fp2, " %.3e, %.3e\n", l4, cond[j].rkmax[i]); } (void)fflush(fp2); } /* END # 11 */ } /* END # 10 */ } /* END # 9 */ (void)fclose(fp2); /*------------------------------------------------------------------*/ /* Print summary of all files used. */ (void)fprintf(stdout, "\n\nSUMMARY OF FILES USED & CREATED\n"); (void)fprintf(stdout, "\t.g file used: %s\n", argv[1]); (void)fprintf(stdout, "\tregions used:\n"); (void)fflush(stdout); i=2; while (argv[i] != NULL) { (void)fprintf(stdout, "\t\t%s\n", argv[i]); (void)fflush(stdout); i++; } (void)fprintf(stdout, "\tfile containing second pass information: %s\n", spfile); (void)fprintf(stdout, "\tmaterial file used: %s\n", filemat); if (iwrite == 1) { (void)fprintf(stdout, "\toutput file created: %s\n", filename); } if (typeout == 0) { (void)fprintf(stdout, "\tconductivity file created: %s\n", confile); (void)fprintf(stdout, "\t (format is PRISM %d.0)\n", prmrel); } if (typeout == 1) (void)printf("\tgeneric file created: %s\n", genfile); (void)fprintf(stdout, "\tconductivity table file created: %s\n", tblfile); (void)fprintf(stdout, "\terror file created: %s\n\n\n", fileerr); (void)fflush(stdout); /*------------------------------------------------------------------*/ /* Open error file. */ fp4 = fopen(fileerr, "wb"); /* Write errors to error file. */ (void)fprintf(fp4, "\nERRORS from secpass\n\n"); /* Write type of file created to error file. */ if (typeout == 0) { (void)fprintf(fp4, "PRISM %d.0 conductivity file, %s, created.\n\n", prmrel, confile); } if (typeout == 1) (void)fprintf(fp4, "Generic file, %s, created.\n\n", genfile); (void)fflush(fp4); for (i=0; i<numreg; i++) { for (j=0; j<numreg; j++) { if ( (cond[i].numcal[j] > ZEROTOL) && ( cond[i].numcal[j] < MINCAL ) ) { (void)fprintf(fp4, "region %d, adjacent region %d:\n", (i+1), (j+1)); (void)fprintf(fp4, "\tnumber of length calculations "); (void)fprintf(fp4, "below minimum of %d\n", MINCAL); (void)fflush(fp4); } } } (void)fclose(fp4); /*------------------------------------------------------------------*/ /* Everything completed, free memory. */ (void)fprintf(stdout, "Freeing memory.\n"); (void)fflush(stdout); for (i=0; i<nmged; i++) { bu_free(cond[i].shrarea, "cond[i].shrarea"); bu_free(cond[i].avglen, "cond[i].avglen"); bu_free(cond[i].rmslen, "cond[i].rmslen"); bu_free(cond[i].minlen, "cond[i].minlen"); bu_free(cond[i].maxlen, "cond[i].maxlen"); bu_free(cond[i].numcal, "cond[i].numcal"); bu_free(cond[i].rkavg, "cond[i].rkavg"); bu_free(cond[i].rkrms, "cond[i].rkrms"); bu_free(cond[i].rkmin, "cond[i].rkmin"); bu_free(cond[i].rkmax, "cond[i].rkmax"); } bu_free(cond, "cond"); } /* END # 2 */ return(0); } /* END # 1 */
/** * absurdly inefficient way to perform sub-pixel anti-aliasing. we * shoot additional rays to estimate the intensity contribution of * this edge cell. */ static void get_intensity(double *intensity, struct application *ap, const struct cell *UNUSED(here), const struct cell *left, const struct cell *below, const struct cell *right, const struct cell *above) { vect_t dy, dx, dy3, dx3; struct application aaap; struct cell grid[4][4]; /* Grid layout: * * left right * _____________________ * |0, 0 | AL | AR | 0, 3| above * |____|____|____|____| * | TL | UL | UR | TR | top/upper * |____|____|____|____| * | BL | LL | LR | BR | bottom/lower * |____|____|____|____| * |3, 0 | DL | DR | 3, 3| debajo * |____|____|____|____| */ struct cell *AL = &grid[0][1]; struct cell *AR = &grid[0][2]; struct cell *TL = &grid[1][0]; struct cell *UL = &grid[1][1]; struct cell *UR = &grid[1][2]; struct cell *TR = &grid[1][3]; struct cell *BL = &grid[2][0]; struct cell *LL = &grid[2][1]; struct cell *LR = &grid[2][2]; struct cell *BR = &grid[2][3]; struct cell *DL = &grid[3][1]; struct cell *DR = &grid[3][2]; RT_APPLICATION_INIT(&aaap); memset(&grid, 0, sizeof(struct cell) * 16); /* 4x4 sub-pixel grid, dx gets to inner cells */ VSCALE(dy, dy_model, 0.125); VSCALE(dx, dx_model, 0.125); /* 4x4 sub-pixel grid, dx*3 gets to outer cells */ VSCALE(dy3, dy_model, 0.375); VSCALE(dx3, dx_model, 0.375); /* setup */ aaap.a_hit = rayhit2; aaap.a_miss = raymiss2; aaap.a_onehit = 1; aaap.a_rt_i = ap->a_rt_i; aaap.a_resource = ap->a_resource; aaap.a_logoverlap = ap->a_logoverlap; /* Above Left */ aaap.a_uptr = (void *)AL; VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3); VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("AL", aaap.a_ray.r_pt); #endif /* Above Right */ aaap.a_uptr = (void *)AR; VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3); VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("AR", aaap.a_ray.r_pt); #endif /* Top Left */ aaap.a_uptr = (void *)TL; VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("TL", aaap.a_ray.r_pt); #endif /* Upper Left */ aaap.a_uptr = (void *)UL; VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("UL", aaap.a_ray.r_pt); #endif /* Upper Right */ aaap.a_uptr = (void *)UR; VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("UR", aaap.a_ray.r_pt); #endif /* Top Right */ aaap.a_uptr = (void *)TR; VADD2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("TR", aaap.a_ray.r_pt); #endif /* Bottom Left */ aaap.a_uptr = (void *)BL; VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("BL", aaap.a_ray.r_pt); #endif /* Lower Left */ aaap.a_uptr = (void *)LL; VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("LL", aaap.a_ray.r_pt); #endif /* Lower Right */ aaap.a_uptr = (void *)LR; VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("LR", aaap.a_ray.r_pt); #endif /* Bottom Right */ aaap.a_uptr = (void *)BR; VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy); VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx3); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("BR", aaap.a_ray.r_pt); #endif /* Debajo Left */ aaap.a_uptr = (void *)DL; VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3); VSUB2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("DL", aaap.a_ray.r_pt); #endif /* Debajo Right */ aaap.a_uptr = (void *)DR; VSUB2(aaap.a_ray.r_pt, ap->a_ray.r_pt, dy3); VADD2(aaap.a_ray.r_pt, aaap.a_ray.r_pt, dx); VMOVE(aaap.a_ray.r_dir, ap->a_ray.r_dir); rt_shootray(&aaap); #ifdef VEDEBUG VPRINT("DR", aaap.a_ray.r_pt); #endif #define TWOBYTWO 1 #ifdef TWOBYTWO if (is_edge(NULL, NULL, UL, left, LL, UR, above)) { *intensity += 0.25; } if (is_edge(NULL, NULL, UR, UL, LR, right, above)) { *intensity += 0.25; } if (is_edge(NULL, NULL, LL, left, below, LR, UL)) { *intensity += 0.25; } if (is_edge(NULL, NULL, LR, LL, below, right, UR)) { *intensity += 0.25; } #else if (is_edge(NULL, NULL, UL, TL, LL, UR, AL)) { *intensity += 0.25; } if (is_edge(NULL, NULL, UR, UL, LR, TR, AR)) { *intensity += 0.25; } if (is_edge(NULL, NULL, LL, BL, DL, LR, UL)) { *intensity += 0.25; } if (is_edge(NULL, NULL, LR, LL, DR, BR, UR)) { *intensity += 0.25; } #endif }
/* * M A I N */ int main(int argc, char **argv) { struct application ap; static struct rt_i *rtip; char *title_file; char idbuf[RT_BUFSIZE] = {0}; /* First ID record info */ char *ptr; int attr_count=0, i; char **attrs = (char **)NULL; if ( argc < 3 ) { bu_exit(1, usage); } RT_APPLICATION_INIT(&ap); argc--; argv++; while ( argv[0][0] == '-' ) switch ( argv[0][1] ) { case 'R': bundle_radius = atof( argv[1] ); argc -= 2; argv += 2; break; case 'n': num_rings = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'c': rays_per_ring = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'v': /* count the number of attribute names provided */ ptr = argv[1]; while ( *ptr ) { while ( *ptr && isspace( *ptr ) ) ptr++; if ( *ptr ) attr_count++; while ( *ptr && !isspace( *ptr ) ) ptr++; } if ( attr_count == 0 ) { bu_log( "missing list of attribute names!\n" ); bu_exit( 1, usage ); } /* allocate enough for a null terminated list */ attrs = (char **)bu_calloc( attr_count + 1, sizeof( char *), "attrs" ); /* use strtok to actually grab the names */ i = 0; ptr = strtok( argv[1], "\t " ); while ( ptr && i < attr_count ) { attrs[i] = bu_strdup( ptr ); ptr = strtok( (char *)NULL, "\t " ); i++; } argc -= 2; argv += 2; break; case 't': rt_bot_tri_per_piece = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'b': rt_bot_minpieces = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'o': sscanf( argv[1], "%d", &set_onehit ); argc -= 2; argv += 2; break; case 'r': { float ray_len; sscanf( argv[1], "%f", &ray_len ); set_ray_length = ray_len; } argc -= 2; argv += 2; break; case 'U': sscanf( argv[1], "%d", &use_air ); argc -= 2; argv += 2; break; case 'u': sscanf( argv[1], "%x", (unsigned int *)&bu_debug ); fprintf(stderr, "librt bu_debug=x%x\n", bu_debug); argc -= 2; argv += 2; break; case 'x': sscanf( argv[1], "%x", (unsigned int *)&rt_g.debug ); fprintf(stderr, "librt rt_g.debug=x%x\n", rt_g.debug); argc -= 2; argv += 2; break; case 'X': sscanf( argv[1], "%x", (unsigned int *)&rdebug ); fprintf(stderr, "rdebug=x%x\n", rdebug); argc -= 2; argv += 2; break; case 'N': sscanf( argv[1], "%x", (unsigned int *)&rt_g.NMG_debug); fprintf(stderr, "librt rt_g.NMG_debug=x%x\n", rt_g.NMG_debug); argc -= 2; argv += 2; break; case 'd': if ( argc < 4 ) goto err; ap.a_ray.r_dir[X] = atof( argv[1] ); ap.a_ray.r_dir[Y] = atof( argv[2] ); ap.a_ray.r_dir[Z] = atof( argv[3] ); set_dir = 1; argc -= 4; argv += 4; continue; case 'p': if ( argc < 4 ) goto err; ap.a_ray.r_pt[X] = atof( argv[1] ); ap.a_ray.r_pt[Y] = atof( argv[2] ); ap.a_ray.r_pt[Z] = atof( argv[3] ); set_pt = 1; argc -= 4; argv += 4; continue; case 'a': if ( argc < 4 ) goto err; at_vect[X] = atof( argv[1] ); at_vect[Y] = atof( argv[2] ); at_vect[Z] = atof( argv[3] ); set_at = 1; argc -= 4; argv += 4; continue; case 'O': { if ( !strcmp( argv[1], "resolve" ) || !strcmp( argv[1], "0") ) overlap_claimant_handling = 0; else if ( !strcmp( argv[1], "rebuild_fastgen" ) || !strcmp( argv[1], "1") ) overlap_claimant_handling = 1; else if ( !strcmp( argv[1], "rebuild_all" ) || !strcmp( argv[1], "2") ) overlap_claimant_handling = 2; else if ( !strcmp( argv[1], "retain" ) || !strcmp( argv[1], "3") ) overlap_claimant_handling = 3; else { bu_log( "Illegal argument (%s) to '-O' option. Must be:\n", argv[1] ); bu_log( "\t'resolve' or '0'\n"); bu_log( "\t'rebuild_fastgen' or '1'\n"); bu_log( "\t'rebuild_all' or '2'\n"); bu_log( "\t'retain' or '3'\n"); bu_exit(1, NULL); } argc -= 2; argv += 2; } continue; default: err: bu_exit(1, usage); } if ( argc < 2 ) { (void)fputs(usage, stderr); bu_exit(1, "rtshot: MGED database not specified\n"); } if ( set_dir + set_pt + set_at != 2 ) goto err; if ( num_rings != 0 || rays_per_ring != 0 || bundle_radius != 0.0 ) { if ( num_rings <= 0 || rays_per_ring <= 0 || bundle_radius <= 0.0 ) { fprintf( stderr, "Must have all of \"-R\", \"-n\", and \"-c\" set\n" ); goto err; } } /* Load database */ title_file = argv[0]; argv++; argc--; if ( (rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL ) { bu_exit(2, "rtshot: rt_dirbuild failure\n"); } if ( overlap_claimant_handling ) rtip->rti_save_overlaps = 1; ap.a_rt_i = rtip; fprintf(stderr, "db title: %s\n", idbuf); rtip->useair = use_air; /* Walk trees */ if ( rt_gettrees_and_attrs( rtip, (const char **)attrs, argc, (const char **)argv, 1 ) ) { bu_exit(1, "rt_gettrees FAILED\n"); } ap.attrs = attrs; rt_prep(rtip); if ( R_DEBUG&RDEBUG_RAYPLOT ) { if ( (plotfp = fopen("rtshot.plot", "w")) == NULL ) { perror("rtshot.plot"); bu_exit(1, NULL); } pdv_3space( plotfp, rtip->rti_pmin, rtip->rti_pmax ); } /* Compute r_dir and r_pt from the inputs */ if ( set_at ) { if ( set_dir ) { vect_t diag; fastf_t viewsize; VSUB2( diag, rtip->mdl_max, rtip->mdl_min ); viewsize = MAGNITUDE( diag ); VJOIN1( ap.a_ray.r_pt, at_vect, -viewsize/2.0, ap.a_ray.r_dir ); } else { /* set_pt */ VSUB2( ap.a_ray.r_dir, at_vect, ap.a_ray.r_pt ); } } VUNITIZE( ap.a_ray.r_dir ); if ( rays_per_ring ) { bu_log( "Central Ray:\n" ); } VPRINT( "Pnt", ap.a_ray.r_pt ); VPRINT( "Dir", ap.a_ray.r_dir ); if ( set_onehit ) ap.a_onehit = set_onehit; else ap.a_onehit = 0; if ( set_ray_length > 0.0 ) ap.a_ray_length = set_ray_length; else ap.a_ray_length = 0.0; /* Shoot Ray */ ap.a_purpose = "main ray"; ap.a_hit = hit; ap.a_miss = miss; if ( rays_per_ring ) { vect_t avec, bvec; struct xray *rp; /* create orthogonal rays for basis of bundle */ bn_vec_ortho( avec, ap.a_ray.r_dir ); VCROSS( bvec, ap.a_ray.r_dir, avec ); VUNITIZE( bvec ); rp = (struct xray *)bu_calloc( sizeof( struct xray ), (rays_per_ring * num_rings) + 1, "ray bundle" ); rp[0] = ap.a_ray; /* struct copy */ rp[0].magic = RT_RAY_MAGIC; rt_raybundle_maker( rp, bundle_radius, avec, bvec, rays_per_ring, num_rings ); (void)rt_shootray_bundle( &ap, rp, (rays_per_ring * num_rings) + 1 ); } else { (void)rt_shootray( &ap ); } return(0); }
/** * NOTE that the [0] element here corresponds with the caller's (1) * element. */ void BU_FORTRAN(frshot, FRSHOT)(int *nloc, /* input & output */ double *indist, /* output only */ double *outdist, int *region_ids, struct context *context, struct rt_i **rtip, /* input only */ double *pt, double *dir) { struct application ap; register struct partition *pp; int ret; register int i; RT_CHECK_RTI(*rtip); if (*nloc <= 0) { bu_log("ERROR frshot: nloc=%d\n", *nloc); *nloc = 0; return; } RT_APPLICATION_INIT(&ap); ap.a_ray.r_pt[X] = pt[0]; ap.a_ray.r_pt[Y] = pt[1]; ap.a_ray.r_pt[Z] = pt[2]; ap.a_ray.r_dir[X] = dir[0]; ap.a_ray.r_dir[Y] = dir[1]; ap.a_ray.r_dir[Z] = dir[2]; VUNITIZE(ap.a_ray.r_dir); ap.a_hit = fr_hit; ap.a_miss = fr_miss; ap.a_level = 0; ap.a_onehit = *nloc * 2; ap.a_resource = &rt_uniresource; rt_uniresource.re_magic = RESOURCE_MAGIC; ap.a_purpose = "frshot"; ap.a_rt_i = *rtip; /* * Actually fire the ray. The list of results will be linked to * fr_global_head by fr_hit(), for further use below. * * It is a bit risky to rely on the segment structures pointed to * by the partition list to still be valid, because rt_shootray * has already put them back on the free segment queue. However, * they will remain unchanged until the next call to * rt_shootray(), so copying out the data here will work fine. */ ret = rt_shootray(&ap); if (ret <= 0) { /* Signal no hits */ *nloc = 0; return; } /* Copy hit information from linked list to argument arrays */ pp = fr_global_head.pt_forw; if (pp == &fr_global_head) { *nloc = 0; return; } for (i=0; i < *nloc; i++, pp=pp->pt_forw) { register struct context *ctp; if (pp == &fr_global_head) break; indist[i] = pp->pt_inhit->hit_dist; outdist[i] = pp->pt_outhit->hit_dist; /* This might instead be reg_regionid ?? */ region_ids[i] = pp->pt_regionp->reg_bit+1; ctp = &context[i]; ctp->co_stp = pp->pt_inseg->seg_stp; VMOVE(ctp->co_vpriv, pp->pt_inhit->hit_vpriv); ctp->co_priv = pp->pt_inhit->hit_private; ctp->co_inflip = pp->pt_inflip; } *nloc = i; /* Will have been incremented above, if successful */ /* Free linked list storage */ for (pp = fr_global_head.pt_forw; pp != &fr_global_head;) { register struct partition *newpp; newpp = pp; pp = pp->pt_forw; FREE_PT(newpp, (&rt_uniresource)); } }
int main(int argc, char **argv) { struct application ap; /* Structure passed between functions. */ struct rt_i *rtip; int idx; /* Index for rt_dirbuild & rt_gettree. */ char idbuf[32]; /* Contains database name. */ struct region *pr; /* Used in finding region names. */ double rho, phi, theta;/* Spherical coordinates for starting point. */ double areabs=0.0; /* Area of bounding sphere (mm**2). */ int ians; /* Answer of question. */ double strtpt[3]; /* Starting point of ray. */ double strtdir[3]; /* Starting direction. */ size_t loops; /* Number of rays fired. */ size_t r; /* Variable in loops. */ int i, j, k; /* Variable in loops. */ long seed; /* Initial seed for random number generator. */ double denom; /* Denominator. */ double elev; /* Elevation, used to find point on yz-plane. */ double az; /* Azimuth, used to find point on yz-plane. */ double rad; /* Radius, used to find point on yz-plane. */ double s[3], t[3]; /* Temporary variables used to find points. */ double q; /* Temporary variable used to find points. */ int numreg; /* Number of regions. */ double center[3]; /* Center of the bounding rpp. */ double sf; /* Used to print shape factor. */ double dump; /* How often a dump is to occur. */ int idump; /* 1=>dump to occur. */ FILE *fp; /* Used to open files. */ char outfile[16]; /* Output file. */ FILE *fp1; /* Used to read region # & name file. */ char rnnfile[16]; /* Region # & name file. */ FILE *fp2; /* Used to write the error file. */ char errfile[16]; /* Error file. */ double totalsf; /* Sum of shape factors. */ double totalnh; /* Sum of number of hits. */ int itype; /* Type of file to be created, 0=>regular, */ /* 1=>generic. */ char line[500]; /* Buffer to read a line of data into. */ int c; /* Reads one character of information. */ int icnt; /* Counter for shape factor. */ char tmpname[150]; /* Temporary name. */ int tmpreg; /* Temporary region number. */ char rnnname[800][150]; /* Region name from region # & name file. */ int rnnnum; /* Number of regions in region # & name file. */ int rnnchar[800]; /* Number of characters in name. */ int rnnreg[800]; /* Region number from region # & name file. */ int jcnt; /* Counter. */ int equal; /* 0=>equal, 1=>not equal. */ double rcpi, rcpj; /* Used to check reciprocity. */ double rcp_diff; /* Difference in reciprocity. */ double rcp_pdiff; /* Percent difference in reciprocity. */ int ret; struct bn_unif *msr = NULL; /* Check to see if arguments are implemented correctly. */ if ((argc < 3 || argv[1] == NULL) || (argv[2] == NULL)) { fprintf(stderr, "\nUsage: %s file.g objects\n\n", *argv); } else { /* START # 1 */ /* Ask what type of file is to be created - regular */ /* or generic. */ printf("Enter type of file to be written (0=>regular or "); printf("1=>generic). "); (void)fflush(stdout); ret = scanf("%1d", &itype); if (ret == 0) bu_exit(-1, "scanf failure when reading file type"); if (itype != 1) itype = 0; /* Enter names of files to be used. */ fprintf(stderr, "Enter name of output file (15 char max).\n\t"); (void)fflush(stderr); ret = scanf("%15s", outfile); if (ret == 0) bu_exit(-1, "scanf failure when reading output file name"); /* Read name of the error file to be written. */ printf("Enter the name of the error file (15 char max).\n\t"); (void)fflush(stdout); ret = scanf("%15s", errfile); if (ret == 0) bu_exit(-1, "scanf failure when reading error file name"); { /* Enter name of region # & name file to be read. */ printf("Enter region # & name file to be read "); printf("(15 char max).\n\t"); (void)fflush(stdout); ret = scanf("%15s", rnnfile); if (ret == 0) bu_exit(-1, "scanf failure when reading region # + name file"); } /* Check if dump is to occur. */ idump = 0; printf("Do you want to dump intermediate shape factors to "); printf("screen (0-no, 1-yes)? "); (void)fflush(stdout); ret = scanf("%1d", &idump); if (ret == 0) bu_exit(-1, "scanf failure - intermediate shape factors setting"); /* Find number of rays to be fired. */ fprintf(stderr, "Enter number of rays to be fired. "); (void)fflush(stderr); ret = scanf("%llu", (unsigned long long *)&loops); if (ret == 0) bu_exit(-1, "scanf failure - number of rays to be fired"); /* clamp loops */ if (loops > UINT32_MAX) loops = UINT32_MAX; /* Set seed for random number generator. */ seed = 1; fprintf(stderr, "Do you wish to enter your own seed (0) or "); fprintf(stderr, "use the default of 1 (1)? "); (void)fflush(stderr); ret = scanf("%1d", &ians); if (ret == 0) bu_exit(-1, "scanf failure - seed use setting"); if (ians == 0) { fprintf(stderr, "Enter unsigned integer seed. "); (void)fflush(stderr); ret = scanf("%ld", &seed); if (ret == 0) bu_exit(-1, "scanf failure - seed"); } msr = bn_unif_init(seed, 0); bu_log("seed initialized\n"); /* Read region # & name file. */ rnnnum = 0; fp1 = fopen(rnnfile, "rb"); c = getc(fp1); while (c != EOF) { (void)ungetc(c, fp1); (void)bu_fgets(line, 200, fp1); sscanf(line, "%d%149s", &tmpreg, tmpname); for (i=0; i<150; i++) { rnnname[rnnnum][i] = tmpname[i]; } rnnreg[rnnnum] = tmpreg; rnnnum++; c = getc(fp1); } (void)fclose(fp1); printf("Number of regions read from region # & name file: %d\n", rnnnum); (void)fflush(stdout); /* Find number of characters in each region name. */ for (i=0; i<rnnnum; i++) { jcnt = 0; while (rnnname[i][jcnt] != '\0') { jcnt++; } rnnchar[i] = jcnt; } /* Build directory. */ idx = 1; /* Set index for rt_dirbuild. */ rtip = rt_dirbuild(argv[idx], idbuf, sizeof(idbuf)); printf("Database Title: %s\n", idbuf); (void)fflush(stdout); /* Set useair to 1 to show hits of air. */ rtip->useair = 1; /* Load desired objects. */ idx = 2; /* Set index. */ while (argv[idx] != NULL) { rt_gettree(rtip, argv[idx]); idx += 1; } /* Find number of regions. */ numreg = (int)rtip->nregions; fprintf(stderr, "Number of regions: %d\n", numreg); (void)fflush(stderr); /* Zero all arrays. */ for (i=0; i<numreg; i++) { info[i].name = "\0"; info[i].regnum = (-1); info[i].numchar = 0; info[i].lvrays = 0.0; info[i].engarea = 0.0; for (j=0; j<numreg; j++) { info[i].intrays[j] = 0.0; } } nummiss = 0.0; /* Get database ready by starting prep. */ rt_prep(rtip); /* Find the center of the bounding rpp. */ center[X] = rtip->mdl_min[X] + (rtip->mdl_max[X] - rtip->mdl_min[X]) / 2.0; center[Y] = rtip->mdl_min[Y] + (rtip->mdl_max[Y] - rtip->mdl_min[Y]) / 2.0; center[Z] = rtip->mdl_min[Z] + (rtip->mdl_max[Z] - rtip->mdl_min[Z]) / 2.0; /* Put region names into structure. */ pr = BU_LIST_FIRST(region, &rtip->HeadRegion); for (i=0; i<numreg; i++) { info[(int)(pr->reg_bit)].name = pr->reg_name; pr = BU_LIST_FORW(region, &(pr->l)); } /* Set up parameters for rt_shootray. */ RT_APPLICATION_INIT(&ap); ap.a_hit = hit; /* User supplied hit function. */ ap.a_miss = miss; /* User supplied miss function. */ ap.a_overlap = overlap; /* User supplied overlap function. */ ap.a_rt_i = rtip; /* Pointer from rt_dirbuild. */ ap.a_onehit = 0; /* Look at all hits. */ ap.a_level = 0; /* Recursion level for diagnostics. */ ap.a_resource = 0; /* Address for resource structure. */ dump = 1000000.0; /* Used for dumping info. */ for (r=0; r<loops; r++) { /* Number of rays fired. */ /* START # 2 */ /* Find length of 'diagonal' (rho). (In reality rho is */ /* the radius of bounding sphere). */ rho = (rtip->mdl_max[X] - rtip->mdl_min[X]) * (rtip->mdl_max[X] - rtip->mdl_min[X]) +(rtip->mdl_max[Y] - rtip->mdl_min[Y]) * (rtip->mdl_max[Y] - rtip->mdl_min[Y]) +(rtip->mdl_max[Z] - rtip->mdl_min[Z]) * (rtip->mdl_max[Z] - rtip->mdl_min[Z]); rho = sqrt(rho) / 2.0 + .5; /* find surface area of bounding sphere. */ areabs = 4.0 * M_PI * rho * rho; /* Second way to find starting point and direction. */ /* This approach finds the starting point and direction */ /* by using parallel rays. */ /* Find point on the bounding sphere. (The negative */ /* of the unit vector of this point will eventually be */ /* the firing direction. */ q = BN_UNIF_DOUBLE(msr) + 0.5; theta = q * M_2PI; q = BN_UNIF_DOUBLE(msr) + 0.5; phi = (q * 2.0) - 1.0; phi = acos(phi); strtdir[X] = rho * sin(phi) * cos(theta); strtdir[Y] = rho * sin(phi) * sin(theta); strtdir[Z] = rho * cos(phi); /* Elevation and azimuth for finding a vector in a plane. */ elev = M_PI_2 - phi; az = theta; /* Find vector in yz-plane. */ q = BN_UNIF_DOUBLE(msr) + 0.5; theta = q * M_2PI; q = BN_UNIF_DOUBLE(msr) + 0.5; rad = rho * sqrt(q); s[X] = 0.0; s[Y] = rad * cos(theta); s[Z] = rad * sin(theta); /* Rotate vector. */ t[X] = s[X] * cos(elev) * cos(az) - s[Z] * sin(elev) * cos(az) - s[Y] * sin(az); t[Y] = s[X] * cos(elev) * sin(az) - s[Z] * sin(elev) * sin(az) + s[Y] * cos(az); t[Z] = s[X] * sin(elev) + s[Z] * cos(elev); /* Translate the point. This is starting point. */ strtpt[X] = t[X] + strtdir[X]; strtpt[Y] = t[Y] + strtdir[Y]; strtpt[Z] = t[Z] + strtdir[Z]; /* Now transfer starting point so that it is in */ /* the absolute coordinates not the origin's. */ strtpt[X] += center[X]; strtpt[Y] += center[Y]; strtpt[Z] += center[Z]; /* Normalize starting direction and make negative. */ denom = strtdir[X] * strtdir[X] + strtdir[Y] * strtdir[Y] + strtdir[Z] * strtdir[Z]; denom = sqrt(denom); strtdir[X] /= (-denom); strtdir[Y] /= (-denom); strtdir[Z] /= (-denom); /* Set up firing point and direction. */ ap.a_ray.r_pt[X] = strtpt[X]; ap.a_ray.r_pt[Y] = strtpt[Y]; ap.a_ray.r_pt[Z] = strtpt[Z]; ap.a_ray.r_dir[X] = strtdir[X]; ap.a_ray.r_dir[Y] = strtdir[Y]; ap.a_ray.r_dir[Z] = strtdir[Z]; /* Call rt_shootray for "forward ray". */ (void)rt_shootray(&ap); if (EQUAL(r, (dump - 1.0))) { printf("%llu rays have been fired in forward direction.\n", (unsigned long long)(r+1)); (void)fflush(stdout); if (idump == 1) { /* START # 3 */ printf("\n****************************************"); printf("****************************************\n"); (void)fflush(stdout); /* Dump info to file. */ for (i=0; i<numreg; i++) { for (j=0; j<numreg; j++) { sf = 0.0; if ((info[i].lvrays < -ZEROTOL) || (ZEROTOL < info[i].lvrays)) sf = info[i].intrays[j] / info[i].lvrays; printf("%d\t%d\t%f\n", i, j, sf); (void)fflush(stdout); } } } /* START # 3 */ dump = dump + 1000000.0; } } /* END # 2 */ /* Find area bounded by engine air using Monte Carlo method. */ for (i=0; i<numreg; i++) { /* Old way, only incrementing info[i].allvrays for forward */ /* ray therefore do not divide by 2. Division by 2 is to */ /* include the backwards ray also. */ /* * info[i].engarea = info[i].allvrays * areabs / loops / 2.0; */ info[i].engarea = info[i].allvrays * areabs / (double)loops; /* Put area into square meters. */ info[i].engarea *= 1.e-6; } /* Find number of characters in each region name. */ for (i=0; i<numreg; i++) { jcnt = 0; while (info[i].name[jcnt] != '\0') { jcnt++; } info[i].numchar = jcnt; } /* Find correct region number. */ printf("Finding correct region numbers.\n"); (void)fflush(stdout); for (i=0; i<numreg; i++) { for (j=0; j<rnnnum; j++) { equal = 0; /* 1=>not equal. */ jcnt = rnnchar[j]; for (k=info[i].numchar; k>=0; k--) { if (jcnt<0) equal = 1; else if (info[i].name[k] != rnnname[j][jcnt]) equal = 1; jcnt--; } if (equal == 0) info[i].regnum = rnnreg[j]; } } printf("Finished finding correct region numbers.\n"); (void)fflush(stdout); /******************************************************************/ /* Check for reciprocity. */ /* Open error file. */ fp2 = fopen(errfile, "wb"); fprintf(fp2, "\nError file for shapefact.\n"); fprintf(fp2, "Shape factor file created: %s\n\n", outfile); fprintf(fp2, "Regions with reciprocity errors greater "); fprintf(fp2, "than 10%%.\n\n"); (void)fflush(fp2); for (i=0; i<numreg; i++) { for (j=0; j<numreg; j++) { rcpi = 0.0; rcpj = 0.0; if ((info[i].lvrays < -ZEROTOL) || (ZEROTOL < info[i].lvrays)) rcpi = info[i].intrays[j] * info[i].engarea /info[i].lvrays; if ((info[j].lvrays < -ZEROTOL) || (ZEROTOL < info[j].lvrays)) rcpj = info[j].intrays[i] * info[j].engarea /info[j].lvrays; rcp_diff = rcpi - rcpj; if (rcp_diff < 0.0) rcp_diff = (-rcp_diff); if ((rcpi < -ZEROTOL) || (ZEROTOL < rcpi)) rcp_pdiff = rcp_diff / rcpi; else rcp_pdiff = 0.0; /* Don't divide by 0. */ /* Print reciprocity errors greater than 10%. */ if (rcp_pdiff > 0.1) { fprintf(fp2, "%d %d %f %f %f %f\n", info[i].regnum, info[j].regnum, rcpi, rcpj, rcp_diff, (rcp_pdiff * 100.0)); (void)fflush(fp2); } } } /* Close error file. */ (void)fclose(fp2); /******************************************************************/ /* Print out shape factor to regular output file. */ if (itype == 0) { fp = fopen(outfile, "wb"); fprintf(fp, "Number of forward rays fired: %llu\n\n", (unsigned long long)loops); (void)fflush(fp); /* Print out structure. */ for (i=0; i<numreg; i++) { /* Print region number, region name, & engine area. */ fprintf(fp, "%d\t%s\t%e\n", info[i].regnum, info[i].name, info[i].engarea); (void)fflush(fp); /* Zero sums for shape factors & rays hit. */ totalsf = 0.0; totalnh = 0.0; for (j=0; j<numreg; j++) { sf = 0.0; if ((info[i].lvrays < -ZEROTOL) || (ZEROTOL < info[i].lvrays)) sf = info[i].intrays[j] / info[i].lvrays; /* Print region number & shape factor. */ fprintf(fp, " %d\t%e\n", info[j].regnum, sf); (void)fflush(fp); /* Add to sum of shape factors & number of hits. */ totalsf += sf; totalnh += info[i].intrays[j]; } /* Print sum of hits & sum of shape factors. */ fprintf(fp, " sum of hits: %f\n", totalnh); fprintf(fp, " sum of shape factors: %f\n\n", totalsf); (void)fflush(fp); } (void)fclose(fp); } /******************************************************************/ /* Create and write to generic shape factor file. */ if (itype == 1) { fp = fopen(outfile, "wb"); for (i=0; i<numreg; i++) { /* Count the number of shape factors. */ icnt = 0; for (j=0; j<numreg; j++) { if (info[i].intrays[j] > ZEROTOL) icnt++; } /* Print the # 5, region number (matches firpass & */ /* secpass), engine area, & number of shape factors. */ fprintf(fp, " 5 %d %e %d\n", info[i].regnum, info[i].engarea, icnt); (void)fflush(fp); for (j=0; j<numreg; j++) { if (info[i].intrays[j] > ZEROTOL) { sf = info[i].intrays[j] / info[i].lvrays; /* Print each region # & shape factor. */ fprintf(fp, " %d %e\n", info[j].regnum, sf); (void)fflush(fp); } } } (void)fclose(fp); } } /* END # 1 */ return 0; }
/** * 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; }
void _rt_gen_worker(int cpu, void *ptr) { int i, j; struct application ap; struct rt_parallel_container *state = (struct rt_parallel_container *)ptr; point_t min, max; int ymin, ymax; int dir1, dir2, dir3; fastf_t d[3]; int n[3]; RT_APPLICATION_INIT(&ap); ap.a_rt_i = state->rtip; ap.a_hit = add_hit_pnts; ap.a_miss = ignore_miss; ap.a_onehit = 0; ap.a_logoverlap = rt_silent_logoverlap; ap.a_resource = &state->resp[cpu]; ap.a_uptr = (void *)(&state->npts[cpu]); /* get min and max points of bounding box */ VMOVE(min, state->rtip->mdl_min); VMOVE(max, state->rtip->mdl_max); /* Make sure we've got at least 10 steps in all 3 dimensions, * regardless of delta */ for (i = 0; i < 3; i++) { n[i] = (max[i] - min[i])/state->delta; if(n[i] < 10) n[i] = 10; d[i] = (max[i] - min[i])/n[i]; } dir1 = state->ray_dir; dir2 = (state->ray_dir+1)%3; dir3 = (state->ray_dir+2)%3; if (state->ncpus == 1) { ymin = 0; ymax = n[dir3]; } else { ymin = n[dir3]/state->ncpus * (cpu - 1) + 1; ymax = n[dir3]/state->ncpus * (cpu); if (cpu == 1) ymin = 0; if (cpu == state->ncpus) ymax = n[dir3]; } ap.a_ray.r_dir[state->ray_dir] = -1; ap.a_ray.r_dir[dir2] = 0; ap.a_ray.r_dir[dir3] = 0; VMOVE(ap.a_ray.r_pt, min); ap.a_ray.r_pt[state->ray_dir] = max[state->ray_dir] + 100; for (i = 0; i < n[dir2]; i++) { ap.a_ray.r_pt[dir3] = min[dir3] + d[dir3] * ymin; for (j = ymin; j < ymax; j++) { rt_shootray(&ap); ap.a_ray.r_pt[dir3] += d[dir3]; } ap.a_ray.r_pt[dir2] += d[dir2]; } }