/* * Determine whether the current hitpoint along a series of * reflections is visible from the origin of the ray. * (which is the location of our "point" eye for now) * * Strategy: we shoot back toward the origin of the ray * If we don't hit anything (i.e. miss) we made it. * If we hit something we made it if that distance is greater * than the distance back to the eye. */ static int isvisible(struct application *ap, struct hit *hitp, const fastf_t *norm) { struct application sub_ap; vect_t rdir; /* compute the ray direction */ VSUB2( rdir, firstray.r_pt, hitp->hit_point ); VUNITIZE( rdir ); if ( VDOT(rdir, norm) < 0 ) return( 0 ); /* backfacing */ sub_ap = *ap; /* struct copy */ sub_ap.a_level = ap->a_level+1; sub_ap.a_onehit = 1; sub_ap.a_hit = hiteye; sub_ap.a_miss = hittrue; /* * New origin is one unit in the ray direction in * order to get away from the surface we intersected. */ VADD2( sub_ap.a_ray.r_pt, hitp->hit_point, rdir ); VMOVE( sub_ap.a_ray.r_dir, rdir ); return( rt_shootray( &sub_ap ) ); }
/* * Determine whether the current hitpoint along a series of * reflections is visible from the origin of the ray. * (which is the location of our "point" eye for now) * * Strategy: we shoot back toward the origin of the ray * If we don't hit anything (i.e. miss) we made it. * If we hit something we made it if that distance is greater * than the distance back to the eye. */ static int isvisible( struct application *ap, struct hit *hitp, const vect_t norm ) { int cpu_num; struct application sub_ap; vect_t rdir; if ( ap->a_resource == RESOURCE_NULL) cpu_num = 0; else cpu_num = ap->a_resource->re_cpu; /* compute the ray direction */ VSUB2( rdir, firstray[cpu_num].r_pt, hitp->hit_point ); VUNITIZE( rdir ); if ( VDOT(rdir, norm) < 0 ) return 0; /* backfacing */ sub_ap = *ap; /* struct copy */ sub_ap.a_level = ap->a_level+1; sub_ap.a_onehit = 1; sub_ap.a_purpose = "sight"; sub_ap.a_hit = hiteye; sub_ap.a_miss = hittrue; /* * New origin is one unit in the ray direction in * order to get away from the surface we intersected. */ VADD2( sub_ap.a_ray.r_pt, hitp->hit_point, rdir ); VMOVE( sub_ap.a_ray.r_dir, rdir ); return rt_shootray( &sub_ap ); }
//******************************************************************* // NAME fireRay // // INPUTS // data - pointer to a tracer_ray_data // // DESCRIPTION // Perform a shotline. //******************************************************************* void DbTracer::fireRay(Interface::trace_data *ray) { // set application data for this ray VMOVE(m_ap.a_ray.r_pt, ray->point); VMOVE(m_ap.a_ray.r_dir, ray->direc); m_ap.a_ray_length = ray->length; m_ap.a_uptr = (void *) &(ray->results); m_ap.a_x = ray->results.x; m_ap.a_y = ray->results.y; // perform shot (void)rt_shootray(&m_ap); }
/** * 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); } }
bool BrlCadInterface::brlCadShootRay(vec3_t x, vec3_t v, vec3_t &x_in, vec3_t &x_out, vec3_t &n_in, vec3_t &n_out, double &r_in, double &r_out) { if (!checkVector(x)) { EG_BUG; } if (!checkVector(v)) { EG_BUG; } VSET(m_Ap.a_ray.r_pt, x[0], x[1], x[2]); VSET(m_Ap.a_ray.r_dir, v[0], v[1], v[2]); m_Hit = false; m_Ap.a_hit = BrlCadInterface::hit; m_Ap.a_miss = BrlCadInterface::miss; rt_shootray(&m_Ap); x_in = m_XIn; n_in = m_InNormal; r_in = m_InRadius; x_out = m_XOut; n_out = m_OutNormal; r_out = m_OutRadius; x = x_out; if (!checkVector(x_in)) { EG_BUG; } if (!checkVector(x_out)) { EG_BUG; } if (!checkVector(n_in)) { EG_BUG; } if (!checkVector(n_out)) { EG_BUG; } return m_Hit; }
static int occludes(struct application *ap, struct cell *here) { int cpu = ap->a_resource->re_cpu; int oc_hit = 0; /* * Test the hit distance on the second geometry. If the second * geometry is closer, do not color pixel */ VMOVE(occlusion_apps[cpu]->a_ray.r_pt, ap->a_ray.r_pt); VMOVE(occlusion_apps[cpu]->a_ray.r_dir, ap->a_ray.r_dir); oc_hit = rt_shootray(occlusion_apps[cpu]); if (!oc_hit) { /* * The occlusion ray missed, therefore this pixel occludes the * second geometry. * * Return 2 so that the fact that there is no geometry behind * can be conveyed to the OCCLUSION_MODE_DITHER section. */ return 2; } if (occlusion_apps[cpu]->a_dist < here->c_dist) { /* * The second geometry is close than the edge, therefore it is * 'foreground'. Do not draw the edge. * * This pixel DOES NOT occlude the second geometry. */ return 0; } return 1; }
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; }
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 */
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 */
/** * 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) { 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; }
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]; } }
/** * 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; }
static int radhit(register struct application *ap, struct partition *PartHeadp, struct seg *segHeadp) { register struct partition *pp; register struct hit *hitp; struct application sub_ap; fastf_t f; vect_t to_eye, work; int depth; for ( pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw ) if ( pp->pt_outhit->hit_dist >= 0.0 ) break; if ( pp == PartHeadp ) { bu_log("radhit: no hit out front?\n"); return(0); } if (R_DEBUG&RDEBUG_HITS) { rt_pr_pt( ap->a_rt_i, pp ); } hitp = pp->pt_inhit; if ( hitp->hit_dist >= INFINITY ) { bu_log("radhit: entry beyond infinity\n"); return(1); } /* Check to see if eye is "inside" the solid */ if ( hitp->hit_dist < 0 ) { /* XXX */ bu_log("radhit: GAK, eye inside solid (%g)\n", hitp->hit_dist ); for ( pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw ) rt_pr_pt( ap->a_rt_i, pp ); return(0); } rayp = &rayinfo[ ap->a_level ]; RT_HIT_NORMAL( rayp->norm, hitp, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip ); if (R_DEBUG&RDEBUG_HITS) { rt_pr_hit( " In", hitp ); } rayp->dist = hitp->hit_dist; rayp->reg = pp->pt_regionp->reg_regionid; rayp->sol = pp->pt_inseg->seg_stp->st_id; rayp->surf = hitp->hit_surfno; RT_CURVATURE( &(rayp->curvature), hitp, pp->pt_inflip, pp->pt_inseg->seg_stp ); if ( VDOT( rayp->norm, ap->a_ray.r_dir ) < 0 ) { bu_log(" debug: flipping curvature\n"); rayp->curvature.crv_c1 = - rayp->curvature.crv_c1; rayp->curvature.crv_c2 = - rayp->curvature.crv_c2; } VMOVE( rayp->ip, hitp->hit_point ); /* Compute the specular direction */ VREVERSE( to_eye, ap->a_ray.r_dir ); f = 2 * VDOT( to_eye, rayp->norm ); VSCALE( work, rayp->norm, f ); /* I have been told this has unit length */ VSUB2( rayp->spec, work, to_eye ); /* Save info for 1st ray */ if ( ap->a_level == 0 ) { firstray = ap->a_ray; /* struct copy */ rayp->sight = 1; /* the 1st intersect is always visible */ } else { /* Check for visibility */ rayp->sight = isvisible( ap, hitp, rayp->norm ); } /* * Shoot another ray in the specular direction. */ if ( ap->a_level < numreflect-1 ) { sub_ap = *ap; /* struct copy */ sub_ap.a_level = ap->a_level+1; VMOVE( sub_ap.a_ray.r_pt, hitp->hit_point ); VMOVE( sub_ap.a_ray.r_dir, rayp->spec ); depth = rt_shootray( &sub_ap ); } else { bu_log( "radhit: max reflections exceeded [%d %d]\n", ap->a_x, ap->a_y ); depth = 0; } if ( ap->a_level == 0 ) { /* We're the 1st ray, output the raylist */ dumpall( ap, depth+1 ); } return(depth+1); /* report hit to main routine */ }
/** * 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)); } }
/** * 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 }
void do_pixel(int cpu, int pat_num, int pixelnum) { struct application a; struct pixel_ext pe; vect_t stereo_point; /* Ref point on eye or view plane */ vect_t point; /* Ref point on eye or view plane */ vect_t colorsum = {(fastf_t)0.0, (fastf_t)0.0, (fastf_t)0.0}; int samplenum = 0; static const double one_over_255 = 1.0 / 255.0; const int pindex = (pixelnum * sizeof(RGBpixel)); if (lightmodel == 8) { /* Add timer here to start pixel-time for heat * graph, when asked. */ rt_prep_timer(); } /* Obtain fresh copy of global application struct */ a = APP; /* struct copy */ a.a_resource = &resource[cpu]; if (incr_mode) { register int i = 1<<incr_level; a.a_y = pixelnum/i; a.a_x = pixelnum - (a.a_y * i); /* a.a_x = pixelnum%i; */ if (incr_level != 0) { /* See if already done last pass */ if (((a.a_x & 1) == 0) && ((a.a_y & 1) == 0)) return; } a.a_x <<= (incr_nlevel-incr_level); a.a_y <<= (incr_nlevel-incr_level); } else { a.a_y = pixelnum/width; a.a_x = pixelnum - (a.a_y * width); /* a.a_x = pixelnum%width; */ } if (Query_one_pixel) { if (a.a_x == query_x && a.a_y == query_y) { rdebug = query_rdebug; RTG.debug = query_debug; } else { RTG.debug = rdebug = 0; } } if (sub_grid_mode) { if (a.a_x < sub_xmin || a.a_x > sub_xmax) return; if (a.a_y < sub_ymin || a.a_y > sub_ymax) return; } if (fullfloat_mode) { register struct floatpixel *fp; fp = &curr_float_frame[a.a_y*width + a.a_x]; if (fp->ff_frame >= 0) { return; /* pixel was reprojected */ } } /* Check the pixel map to determine if this image should be * rendered or not. */ if (pixmap) { a.a_user= 1; /* Force Shot Hit */ if (pixmap[pindex + RED] + pixmap[pindex + GRN] + pixmap[pindex + BLU]) { /* non-black pixmap pixel */ a.a_color[RED]= (double)(pixmap[pindex + RED]) * one_over_255; a.a_color[GRN]= (double)(pixmap[pindex + GRN]) * one_over_255; a.a_color[BLU]= (double)(pixmap[pindex + BLU]) * one_over_255; /* we're done */ view_pixel(&a); if ((size_t)a.a_x == width-1) { view_eol(&a); /* End of scan line */ } return; } } /* our starting point, used for non-jitter */ VJOIN2 (point, viewbase_model, a.a_x, dx_model, a.a_y, dy_model); /* not tracing the corners of a prism by default */ a.a_pixelext=(struct pixel_ext *)NULL; /* black or no pixmap, so compute the pixel(s) */ /* LOOP BELOW IS UNROLLED ONE SAMPLE SINCE THAT'S THE COMMON CASE. * * XXX - If you edit the unrolled or non-unrolled section, be sure * to edit the other section. */ if (hypersample == 0) { /* not hypersampling, so just do it */ /****************/ /* BEGIN UNROLL */ /****************/ if (jitter & JITTER_CELL) { jitter_start_pt(point, &a, samplenum, pat_num); } if (a.a_rt_i->rti_prismtrace) { /* compute the four corners */ pe.magic = PIXEL_EXT_MAGIC; VJOIN2(pe.corner[0].r_pt, viewbase_model, a.a_x, dx_model, a.a_y, dy_model); VJOIN2(pe.corner[1].r_pt, viewbase_model, (a.a_x+1), dx_model, a.a_y, dy_model); VJOIN2(pe.corner[2].r_pt, viewbase_model, (a.a_x+1), dx_model, (a.a_y+1), dy_model); VJOIN2(pe.corner[3].r_pt, viewbase_model, a.a_x, dx_model, (a.a_y+1), dy_model); a.a_pixelext = &pe; } if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, point, eye_model); VUNITIZE(a.a_ray.r_dir); VMOVE(a.a_ray.r_pt, eye_model); if (a.a_rt_i->rti_prismtrace) { VSUB2(pe.corner[0].r_dir, pe.corner[0].r_pt, eye_model); VSUB2(pe.corner[1].r_dir, pe.corner[1].r_pt, eye_model); VSUB2(pe.corner[2].r_dir, pe.corner[2].r_pt, eye_model); VSUB2(pe.corner[3].r_dir, pe.corner[3].r_pt, eye_model); } } else { VMOVE(a.a_ray.r_pt, point); VMOVE(a.a_ray.r_dir, APP.a_ray.r_dir); if (a.a_rt_i->rti_prismtrace) { VMOVE(pe.corner[0].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[1].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[2].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[3].r_dir, a.a_ray.r_dir); } } if (report_progress) { report_progress = 0; bu_log("\tframe %d, xy=%d, %d on cpu %d, samp=%d\n", curframe, a.a_x, a.a_y, cpu, samplenum); } a.a_level = 0; /* recursion level */ a.a_purpose = "main ray"; (void)rt_shootray(&a); if (stereo) { fastf_t right, left; right = CRT_BLEND(a.a_color); VSUB2(stereo_point, point, left_eye_delta); if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, stereo_point, eye_model); VUNITIZE(a.a_ray.r_dir); VADD2(a.a_ray.r_pt, eye_model, left_eye_delta); } else { VMOVE(a.a_ray.r_pt, stereo_point); } a.a_level = 0; /* recursion level */ a.a_purpose = "left eye ray"; (void)rt_shootray(&a); left = CRT_BLEND(a.a_color); VSET(a.a_color, left, 0, right); } VADD2(colorsum, colorsum, a.a_color); /**************/ /* END UNROLL */ /**************/ } else { /* hypersampling, so iterate */ for (samplenum=0; samplenum<=hypersample; samplenum++) { /* shoot at a point based on the jitter pattern number */ /**********************/ /* BEGIN NON-UNROLLED */ /**********************/ if (jitter & JITTER_CELL) { jitter_start_pt(point, &a, samplenum, pat_num); } if (a.a_rt_i->rti_prismtrace) { /* compute the four corners */ pe.magic = PIXEL_EXT_MAGIC; VJOIN2(pe.corner[0].r_pt, viewbase_model, a.a_x, dx_model, a.a_y, dy_model); VJOIN2(pe.corner[1].r_pt, viewbase_model, (a.a_x+1), dx_model, a.a_y, dy_model); VJOIN2(pe.corner[2].r_pt, viewbase_model, (a.a_x+1), dx_model, (a.a_y+1), dy_model); VJOIN2(pe.corner[3].r_pt, viewbase_model, a.a_x, dx_model, (a.a_y+1), dy_model); a.a_pixelext = &pe; } if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, point, eye_model); VUNITIZE(a.a_ray.r_dir); VMOVE(a.a_ray.r_pt, eye_model); if (a.a_rt_i->rti_prismtrace) { VSUB2(pe.corner[0].r_dir, pe.corner[0].r_pt, eye_model); VSUB2(pe.corner[1].r_dir, pe.corner[1].r_pt, eye_model); VSUB2(pe.corner[2].r_dir, pe.corner[2].r_pt, eye_model); VSUB2(pe.corner[3].r_dir, pe.corner[3].r_pt, eye_model); } } else { VMOVE(a.a_ray.r_pt, point); VMOVE(a.a_ray.r_dir, APP.a_ray.r_dir); if (a.a_rt_i->rti_prismtrace) { VMOVE(pe.corner[0].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[1].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[2].r_dir, a.a_ray.r_dir); VMOVE(pe.corner[3].r_dir, a.a_ray.r_dir); } } if (report_progress) { report_progress = 0; bu_log("\tframe %d, xy=%d, %d on cpu %d, samp=%d\n", curframe, a.a_x, a.a_y, cpu, samplenum); } a.a_level = 0; /* recursion level */ a.a_purpose = "main ray"; (void)rt_shootray(&a); if (stereo) { fastf_t right, left; right = CRT_BLEND(a.a_color); VSUB2(stereo_point, point, left_eye_delta); if (rt_perspective > 0.0) { VSUB2(a.a_ray.r_dir, stereo_point, eye_model); VUNITIZE(a.a_ray.r_dir); VADD2(a.a_ray.r_pt, eye_model, left_eye_delta); } else { VMOVE(a.a_ray.r_pt, stereo_point); } a.a_level = 0; /* recursion level */ a.a_purpose = "left eye ray"; (void)rt_shootray(&a); left = CRT_BLEND(a.a_color); VSET(a.a_color, left, 0, right); } VADD2(colorsum, colorsum, a.a_color); /********************/ /* END NON-UNROLLED */ /********************/ } /* for samplenum <= hypersample */ { /* scale the hypersampled results */ fastf_t f; f = 1.0 / (hypersample+1); VSCALE(a.a_color, colorsum, f); } } /* end unrolling else case */ /* bu_log("2: [%d, %d] : [%.2f, %.2f, %.2f]\n", pixelnum%width, pixelnum/width, a.a_color[0], a.a_color[1], a.a_color[2]); */ /* FIXME: this should work on windows after the bu_timer() is * created to replace the librt timing mechanism. */ #if !defined(_WIN32) || defined(__CYGWIN__) /* Add get_pixel_timer here to get total time taken to get pixel, when asked */ if (lightmodel == 8) { fastf_t pixelTime; fastf_t **timeTable; pixelTime = rt_get_timer(NULL,NULL); /* bu_log("PixelTime = %lf X:%d Y:%d\n", pixelTime, a.a_x, a.a_y); */ bu_semaphore_acquire(RT_SEM_LAST-2); timeTable = timeTable_init(width, height); timeTable_input(a.a_x, a.a_y, pixelTime, timeTable); bu_semaphore_release(RT_SEM_LAST-2); } #endif /* we're done */ view_pixel(&a); if ((size_t)a.a_x == width-1) { view_eol(&a); /* End of scan line */ } return; }
/* * 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 {
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 */
/* * F _ H I D E L I N E */ int f_hideline(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { FILE *plotfp; char visible; int i, numobjs; char *objname[MAXOBJECTS], title[1]; fastf_t len, u, step; float ratio; vect_t last_move; struct rt_i *rtip; struct resource resource; struct application a; vect_t temp; vect_t last, dir; register struct bn_vlist *vp; CHECK_DBI_NULL; if (argc < 2 || 4 < argc) { struct bu_vls vls; bu_vls_init(&vls); bu_vls_printf(&vls, "help H"); Tcl_Eval(interp, bu_vls_addr(&vls)); bu_vls_free(&vls); return TCL_ERROR; } if ((plotfp = fopen(argv[1], "w")) == NULL) { Tcl_AppendResult(interp, "f_hideline: unable to open \"", argv[1], "\" for writing.\n", (char *)NULL); return TCL_ERROR; } pl_space(plotfp, (int)GED_MIN, (int)GED_MIN, (int)GED_MAX, (int)GED_MAX); /* Build list of objects being viewed */ numobjs = 0; FOR_ALL_SOLIDS(sp) { for (i = 0; i < numobjs; i++) { if ( objname[i] == FIRST_SOLID(sp)->d_namep ) break; } if (i == numobjs) objname[numobjs++] = FIRST_SOLID(sp)->d_namep; } Tcl_AppendResult(interp, "Generating hidden-line drawing of the following regions:\n", (char *)NULL); for (i = 0; i < numobjs; i++) Tcl_AppendResult(interp, "\t", objname[i], "\n", (char *)NULL); /* Initialization for librt */ if ((rtip = rt_dirbuild(dbip->dbi_filename, title, 0)) == RTI_NULL) { Tcl_AppendResult(interp, "f_hideline: unable to open model file \"", dbip->dbi_filename, "\"\n", (char *)NULL); return TCL_ERROR; } a.a_hit = hit_headon; a.a_miss = hit_tangent; a.a_overlap = hit_overlap; a.a_rt_i = rtip; a.a_resource = &resource; a.a_level = 0; a.a_onehit = 1; a.a_diverge = 0; a.a_rbeam = 0; if (argc > 2) { sscanf(argv[2], "%f", &step); step = view_state->vs_Viewscale/step; sscanf(argv[3], "%f", &epsilon); epsilon *= view_state->vs_Viewscale/100; } else { step = view_state->vs_Viewscale/256; epsilon = 0.1*view_state->vs_Viewscale; } for (i = 0; i < numobjs; i++) if (rt_gettree(rtip, objname[i]) == -1) Tcl_AppendResult(interp, "f_hideline: rt_gettree failed on \"", objname[i], "\"\n", (char *)NULL); /* Crawl along the vectors raytracing as we go */ VSET(temp, 0.0, 0.0, -1.0); /* looking at model */ MAT4X3VEC(a.a_ray.r_dir, view_state->vs_view2model, temp); VUNITIZE(a.a_ray.r_dir); FOR_ALL_SOLIDS(sp) { ratio = sp->s_size / VIEWSIZE; /* ignore if small or big */ if (ratio >= dmp->dmr_bound || ratio < 0.001) continue; Tcl_AppendResult(interp, "Primitive\n", (char *)NULL); for ( BU_LIST_FOR( vp, bn_vlist, &(sp->s_vlist) ) ) { register int i; register int nused = vp->nused; register int *cmd = vp->cmd; register point_t *pt = vp->pt; for ( i = 0; i < nused; i++, cmd++, pt++ ) { Tcl_AppendResult(interp, "\tVector\n", (char *)NULL); switch ( *cmd ) { case BN_VLIST_POLY_START: case BN_VLIST_POLY_VERTNORM: break; case BN_VLIST_POLY_MOVE: case BN_VLIST_LINE_MOVE: /* move */ VMOVE(last, *pt); MOVE(last); break; case BN_VLIST_POLY_DRAW: case BN_VLIST_POLY_END: case BN_VLIST_LINE_DRAW: /* setup direction && length */ VSUB2(dir, *pt, last); len = MAGNITUDE(dir); VUNITIZE(dir); visible = FALSE; { struct bu_vls tmp_vls; bu_vls_init(&tmp_vls); bu_vls_printf(&tmp_vls, "\t\tDraw 0 -> %g, step %g\n", len, step); Tcl_AppendResult(interp, bu_vls_addr(&tmp_vls), (char *)NULL); bu_vls_free(&tmp_vls); } for (u = 0; u <= len; u += step) { VJOIN1(aim_point, last, u, dir); MAT4X3PNT(temp, view_state->vs_model2view, aim_point); temp[Z] = 100; /* parallel project */ MAT4X3PNT(a.a_ray.r_pt, view_state->vs_view2model, temp); if (rt_shootray(&a)) { if (!visible) { visible = TRUE; MOVE(aim_point); } } else { if (visible) { visible = FALSE; DRAW(aim_point); } } } if (visible) DRAW(aim_point); VMOVE(last, *pt); /* new last vertex */ } } } } fclose(plotfp); return TCL_OK; }
/* * 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; }
void shoot(char *UNUSED(buffer), com_table *UNUSED(ctp), struct rt_i *rtip) { int i; double bov = 0.0; /* back out value */ extern void init_ovlp(); if (!rtip) return; if (need_prep) { rt_clean(rtip); do_rt_gettrees(rtip, NULL, 0, &need_prep); } if (do_backout) { point_t ray_point; vect_t ray_dir; vect_t center_bsphere; fastf_t dist_to_target; vect_t dvec; fastf_t delta; for (i = 0; i < 3; ++i) { ray_point[i] = target(i); ray_dir[i] = direct(i); } if (bsphere_diameter < 0) set_diameter(rtip); /* * calculate the distance from a plane normal to the ray direction through the center of * the bounding sphere and a plane normal to the ray direction through the aim point. */ VADD2SCALE(center_bsphere, rtip->mdl_max, rtip->mdl_min, 0.5); dist_to_target = DIST_PT_PT(center_bsphere, ray_point); VSUB2(dvec, ray_point, center_bsphere); VUNITIZE(dvec); delta = dist_to_target*VDOT(ray_dir, dvec); /* * this should put us about a bounding sphere radius in front of the bounding sphere */ bov = bsphere_diameter + delta; } for (i = 0; i < 3; ++i) { target(i) = target(i) + (bov * -direct(i)); ap.a_ray.r_pt[i] = target(i); ap.a_ray.r_dir[i] = direct(i); } if (nirt_debug & DEBUG_BACKOUT) { bu_log("Backing out %g units to (%g %g %g), shooting dir is (%g %g %g)\n", bov * base2local, ap.a_ray.r_pt[0] * base2local, ap.a_ray.r_pt[1] * base2local, ap.a_ray.r_pt[2] * base2local, V3ARGS(ap.a_ray.r_dir)); } init_ovlp(); (void) rt_shootray(&ap); /* Restore pre-backout target values */ if (do_backout) { for (i = 0; i < 3; ++i) { target(i) = target(i) - (bov * -direct(i)); } } }
/* * 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); }
/* * R A Y H I T * * Rayhit() is called by rt_shootray() when the ray hits one or more objects. * A per-shotline header record is written, followed by information about * each object hit. * * Note that the GIFT-3 format uses a different convention for the "zero" * distance along the ray. RT has zero at the ray origin (emanation plain), * while GIFT has zero at the screen plain translated so that it contains * the model origin. This difference is compensated for by adding the * 'dcorrection' distance correction factor. * * Also note that the GIFT-3 format requires information about the start * point of the ray in two formats. First, the h, v coordinates of the * grid cell CENTERS (in screen space coordinates) are needed. * Second, the ACTUAL h, v coordinates fired from are needed. * * An optional rtg3.pl UnixPlot file is written, permitting a * color vector display of ray-model intersections. */ int rayhit(struct application *ap, register struct partition *PartHeadp, struct seg *segp) { register struct partition *pp = PartHeadp->pt_forw; int comp_count; /* component count */ fastf_t dfirst, dlast; /* ray distances */ static fastf_t dcorrection = 0; /* RT to GIFT dist corr */ int card_count; /* # comp. on this card */ const char *fmt; /* printf() format string */ struct bu_vls str; char buf[128]; /* temp. sprintf() buffer */ point_t hv; /* GIFT h, v coords, in inches */ point_t hvcen; int prev_id=-1; point_t first_hit; int first; if ( pp == PartHeadp ) return(0); /* nothing was actually hit?? */ if ( ap->a_rt_i->rti_save_overlaps ) rt_rebuild_overlaps( PartHeadp, ap, 1 ); part_compact(ap, PartHeadp, TOL); /* count components in partitions */ comp_count = 0; for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw ) { if ( pp->pt_regionp->reg_regionid > 0 ) { prev_id = pp->pt_regionp->reg_regionid; comp_count++; } else if ( prev_id <= 0 ) { /* normally air would be output along with a solid partition, but this will require a '111' partition */ prev_id = pp->pt_regionp->reg_regionid; comp_count++; } else prev_id = pp->pt_regionp->reg_regionid; } pp = PartHeadp->pt_back; if ( pp!=PartHeadp && pp->pt_regionp->reg_regionid <= 0 ) comp_count++; /* a trailing '111' ident */ if ( comp_count == 0 ) return( 0 ); /* Set up variable length string, to buffer this shotline in. * Note that there is one component per card, and that each card * (line) is 80 characters long. Hence the parameters given to * rt-vls-extend(). */ bu_vls_init( &str ); bu_vls_extend( &str, 80 * (comp_count+1) ); /* * Find the H, V coordinates of the grid cell center. * RT uses the lower left corner of each cell. */ { point_t center; fastf_t dx; fastf_t dy; dx = ap->a_x + 0.5; dy = ap->a_y + 0.5; VJOIN2( center, viewbase_model, dx, dx_model, dy, dy_model ); MAT4X3PNT( hvcen, model2hv, center ); } /* * Find exact h, v coordinates of actual ray start by * projecting start point into GIFT h, v coordinates. */ MAT4X3PNT( hv, model2hv, ap->a_ray.r_pt ); /* * In RT, rays are launched from the plane of the screen, * and ray distances are relative to the start point. * In GIFT-3 output files, ray distances are relative to * the (H, V) plane translated so that it contains the origin. * A distance correction is required to convert between the two. * Since this really should be computed only once, not every time, * the trip_count flag was added. */ { static int trip_count; vect_t tmp; vect_t viewZdir; if ( trip_count == 0) { VSET( tmp, 0, 0, -1 ); /* viewing direction */ MAT4X3VEC( viewZdir, view2model, tmp ); VUNITIZE( viewZdir ); /* dcorrection will typically be negative */ dcorrection = VDOT( ap->a_ray.r_pt, viewZdir ); trip_count = 1; } } /* This code is for diagnostics. * bu_log("dcorrection=%g\n", dcorrection); */ /* dfirst and dlast have been made negative to account for GIFT looking * in the opposite direction of RT. */ dfirst = -(PartHeadp->pt_forw->pt_inhit->hit_dist + dcorrection); dlast = -(PartHeadp->pt_back->pt_outhit->hit_dist + dcorrection); #if 0 /* This code is to note any occurances of negative distances. */ if ( PartHeadp->pt_forw->pt_inhit->hit_dist < 0) { bu_log("ERROR: dfirst=%g at partition x%x\n", dfirst, PartHeadp->pt_forw ); bu_log("\tdcorrection = %f\n", dcorrection ); bu_log("\tray start point is ( %f %f %f ) in direction ( %f %f %f )\n", V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ) ); VJOIN1( PartHeadp->pt_forw->pt_inhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_inhit->hit_dist, ap->a_ray.r_dir ); VJOIN1( PartHeadp->pt_back->pt_outhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_outhit->hit_dist, ap->a_ray.r_dir ); rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:"); } /* End of bug trap. */ #endif /* * Output the ray header. The GIFT statements that * would have generated this are: * 410 write(1, 411) hcen, vcen, h, v, ncomp, dfirst, dlast, a, e * 411 format(2f7.1, 2f9.3, i3, 2f8.2,' A', f6.1,' E', f6.1) */ #define SHOT_FMT "%7.1f%7.1f%9.3f%9.3f%3d%8.2f%8.2f A%6.1f E%6.1f" if ( rt_perspective > 0 ) { bn_ae_vec( &azimuth, &elevation, ap->a_ray.r_dir ); } bu_vls_printf( &str, SHOT_FMT, hvcen[0], hvcen[1], hv[0], hv[1], comp_count, dfirst * MM2IN, dlast * MM2IN, azimuth, elevation ); /* * As an aid to debugging, take advantage of the fact that * there are more than 80 columns on UNIX "cards", and * add debugging information to the end of the line to * allow this shotline to be reproduced offline. * -b gives the shotline x, y coordinates when re-running RTG3, * -p and -d are used with RTSHOT * The easy way to activate this is with the harmless -!1 option * when running RTG3. */ if ( R_DEBUG || bu_debug || RT_G_DEBUG ) { bu_vls_printf( &str, " -b%d,%d -p %26.20e %26.20e %26.20e -d %26.20e %26.20e %26.20e\n", ap->a_x, ap->a_y, V3ARGS(ap->a_ray.r_pt), V3ARGS(ap->a_ray.r_dir) ); } else { bu_vls_putc( &str, '\n' ); } /* loop here to deal with individual components */ card_count = 0; prev_id = -1; first = 1; for ( pp=PartHeadp->pt_forw; pp!=PartHeadp; pp=pp->pt_forw ) { /* * The GIFT statements that would have produced * this output are: * do 632 i=icomp, iend * if (clos(icomp).gt.999.99.or.slos(i).gt.999.9) goto 635 * 632 continue * write(1, 633)(item(i), clos(i), cangi(i), cango(i), * & kspac(i), slos(i), i=icomp, iend) * 633 format(1x, 3(i4, f6.2, 2f5.1, i1, f5.1)) * goto 670 * 635 write(1, 636)(item(i), clos(i), cangi(i), cango(i), * & kspac(i), slos(i), i=icomp, iend) * 636 format(1x, 3(i4, f6.1, 2f5.1, i1, f5.0)) */ fastf_t comp_thickness; /* component line of sight thickness */ fastf_t in_obliq; /* in obliquity angle */ fastf_t out_obliq; /* out obliquity angle */ int region_id; /* solid region's id */ int air_id; /* air id */ fastf_t dot_prod; /* dot product of normal and ray dir */ fastf_t air_thickness; /* air line of sight thickness */ vect_t normal; /* surface normal */ register struct partition *nextpp = pp->pt_forw; region_id = pp->pt_regionp->reg_regionid; if ( region_id <= 0 && prev_id > 0 ) { /* air region output with previous partition */ prev_id = region_id; continue; } comp_thickness = pp->pt_outhit->hit_dist - pp->pt_inhit->hit_dist; /* The below code is meant to catch components with zero or * negative thicknesses. This is not supposed to be possible, * but the condition has been seen. */ #if 0 if ( comp_thickness <= 0 ) { VJOIN1( pp->pt_inhit->hit_point, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir ); VJOIN1( pp->pt_outhit->hit_point, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir ); bu_log("ERROR: comp_thickness=%g for region id = %d at h=%g, v=%g (x=%d, y=%d), partition at x%x\n", comp_thickness, region_id, hv[0], hv[1], ap->a_x, ap->a_y, pp ); rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:"); bu_log("Send this output to the BRL-CAD Developers ([email protected])\n"); if ( ! (RT_G_DEBUG & DEBUG_ARB8)) { rt_g.debug |= DEBUG_ARB8; rt_shootray(ap); rt_g.debug &= ~DEBUG_ARB8; } } #endif if ( nextpp == PartHeadp ) { if ( region_id <= 0 ) { /* last partition is air, need a 111 'phantom armor' before AND after */ bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before and after air region %s\n", pp->pt_regionp->reg_name ); region_id = 111; air_id = pp->pt_regionp->reg_aircode; air_thickness = comp_thickness; comp_thickness = 0.0; } else { /* Last partition, no air follows, use code 9 */ air_id = 9; air_thickness = 0.0; } } else if ( region_id <= 0 ) { /* air region, need a 111 'phantom armor' */ bu_log( "WARNING: adding 'phantom armor' (id=111) with zero thickness before air region %s\n", pp->pt_regionp->reg_name ); prev_id = region_id; region_id = 111; air_id = pp->pt_regionp->reg_aircode; air_thickness = comp_thickness; comp_thickness = 0.0; } else if ( nextpp->pt_regionp->reg_regionid <= 0 && nextpp->pt_regionp->reg_aircode != 0 ) { /* Next partition is air region */ air_id = nextpp->pt_regionp->reg_aircode; air_thickness = nextpp->pt_outhit->hit_dist - nextpp->pt_inhit->hit_dist; prev_id = air_id; } else { /* 2 solid regions, maybe with gap */ air_id = 0; air_thickness = nextpp->pt_inhit->hit_dist - pp->pt_outhit->hit_dist; if ( air_thickness < 0.0 ) air_thickness = 0.0; if ( !NEAR_ZERO( air_thickness, 0.1 ) ) { air_id = 1; /* air gap */ if ( R_DEBUG & RDEBUG_HITS ) bu_log("air gap added\n"); } else { air_thickness = 0.0; } prev_id = region_id; } /* * Compute the obliquity angles in degrees, ie, * the "declension" angle down off the normal vector. * RT normals always point outwards; * the "inhit" normal points opposite the ray direction, * the "outhit" normal points along the ray direction. * Hence the one sign change. * XXX this should probably be done with atan2() */ if ( first ) { first = 0; VJOIN1( first_hit, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir ); } out: RT_HIT_NORMAL( normal, pp->pt_inhit, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip ); dot_prod = VDOT( ap->a_ray.r_dir, normal ); if ( dot_prod > 1.0 ) dot_prod = 1.0; if ( dot_prod < -1.0 ) dot_prod = (-1.0); in_obliq = acos( -dot_prod ) * bn_radtodeg; RT_HIT_NORMAL( normal, pp->pt_outhit, pp->pt_outseg->seg_stp, &(ap->a_ray), pp->pt_outflip ); dot_prod = VDOT( ap->a_ray.r_dir, normal ); if ( dot_prod > 1.0 ) dot_prod = 1.0; if ( dot_prod < -1.0 ) dot_prod = (-1.0); out_obliq = acos( dot_prod ) * bn_radtodeg; /* Check for exit obliquties greater than 90 degrees. */ #if 0 if ( in_obliq > 90 || in_obliq < 0 ) { bu_log("ERROR: in_obliquity=%g\n", in_obliq); rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:"); } if ( out_obliq > 90 || out_obliq < 0 ) { bu_log("ERROR: out_obliquity=%g\n", out_obliq); VPRINT(" r_dir", ap->a_ray.r_dir); VPRINT("normal", normal); bu_log("dot=%g, acos(dot)=%g\n", VDOT( ap->a_ray.r_dir, normal ), acos( VDOT( ap->a_ray.r_dir, normal ) ) ); /* Print the defective one */ rt_pr_pt( ap->a_rt_i, pp ); /* Print the whole ray's partition list */ rt_pr_partitions(ap->a_rt_i, PartHeadp, "Defective partion:"); } #endif if ( in_obliq > 90.0 ) in_obliq = 90.0; if ( in_obliq < 0.0 ) in_obliq = 0.0; if ( out_obliq > 90.0 ) out_obliq = 90.0; if ( out_obliq < 0.0 ) out_obliq = 0.0; /* * Handle 3-components per card output format, with * a leading space in front of the first component. */ if ( card_count == 0 ) { bu_vls_strcat( &str, " " ); } comp_thickness *= MM2IN; /* Check thickness fields for format overflow */ if ( comp_thickness > 999.99 || air_thickness*MM2IN > 999.9 ) fmt = "%4d%6.1f%5.1f%5.1f%1d%5.0f"; else fmt = "%4d%6.2f%5.1f%5.1f%1d%5.1f"; #ifdef SPRINTF_NOT_PARALLEL bu_semaphore_acquire( BU_SEM_SYSCALL ); #endif snprintf(buf, 128, fmt, region_id, comp_thickness, in_obliq, out_obliq, air_id, air_thickness*MM2IN ); #ifdef SPRINTF_NOT_PARALLEL bu_semaphore_release( BU_SEM_SYSCALL ); #endif bu_vls_strcat( &str, buf ); card_count++; if ( card_count >= 3 ) { bu_vls_strcat( &str, "\n" ); card_count = 0; } /* A color rtg3.pl UnixPlot file of output commands * is generated. This is processed by plot(1) * plotting filters such as pl-fb or pl-sgi. * Portions of a ray passing through air within the * model are represented in blue, while portions * passing through a solid are assigned green. * This will always be done single CPU, * to prevent output garbling. (See view_init). */ if (R_DEBUG & RDEBUG_RAYPLOT) { vect_t inpt; vect_t outpt; VJOIN1(inpt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir); VJOIN1(outpt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir); pl_color(plotfp, 0, 255, 0); /* green */ pdv_3line(plotfp, inpt, outpt); if (air_thickness > 0) { vect_t air_end; VJOIN1(air_end, ap->a_ray.r_pt, pp->pt_outhit->hit_dist + air_thickness, ap->a_ray.r_dir); pl_color(plotfp, 0, 0, 255); /* blue */ pdv_3cont(plotfp, air_end); } } if ( nextpp == PartHeadp && air_id != 9 ) { /* need to output a 111 'phantom armor' at end of shotline */ air_id = 9; air_thickness = 0.0; region_id = 111; comp_thickness = 0.0; goto out; } } /* If partway through building the line, add a newline */ if ( card_count > 0 ) { /* * Note that GIFT zero-fills the unused component slots, * but neither COVART II nor COVART III require it, * so just end the line here. */ bu_vls_strcat( &str, "\n" ); } /* Single-thread through file output. * COVART will accept non-sequential ray data provided the * ray header and its associated data are not separated. CAVEAT: * COVART will not accept headers out of sequence. */ bu_semaphore_acquire( BU_SEM_SYSCALL ); fputs( bu_vls_addr( &str ), outfp ); if ( shot_fp ) { fprintf( shot_fp, "%.5f %.5f %.5f %.5f %.5f %.5f %.5f %.5f %ld %.5f %.5f %.5f\n", azimuth, elevation, V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ), line_num, V3ARGS( first_hit) ); line_num += 1 + (comp_count / 3 ); if ( comp_count % 3 ) line_num++; } /* End of single-thread region */ bu_semaphore_release( BU_SEM_SYSCALL ); /* Release vls storage */ bu_vls_free( &str ); return(0); }
static int radhit( struct application *ap, struct partition *PartHeadp ) { register struct partition *pp; register struct hit *hitp; struct application sub_ap; struct rayinfo *rayp; fastf_t f; vect_t to_eye, work; int depth; int cpu_num; for ( pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw ) if ( pp->pt_outhit->hit_dist >= 0.0 ) break; if ( pp == PartHeadp ) { bu_log("radhit: no hit out front?\n"); return 0; } if (R_DEBUG&RDEBUG_HITS) { rt_pr_pt( ap->a_rt_i, pp ); } hitp = pp->pt_inhit; if ( hitp->hit_dist >= INFINITY ) { bu_log("radhit: entry beyond infinity\n"); return 1; } /* Check to see if eye is "inside" the solid */ if ( hitp->hit_dist < 0 ) { /* XXX */ return 0; } if (R_DEBUG&RDEBUG_HITS) { rt_pr_hit( " In", hitp ); } if ( ap->a_resource == RESOURCE_NULL) cpu_num = 0; else cpu_num = ap->a_resource->re_cpu; rayp = &rayinfo[cpu_num][ ap->a_level +1 ]; rayp->x = ap->a_x; rayp->y = ap->a_y; rayp->dist = hitp->hit_dist; rayp->reg = pp->pt_regionp->reg_regionid; rayp->sol = pp->pt_inseg->seg_stp->st_id; rayp->surf = hitp->hit_surfno; RT_HIT_NORMAL( rayp->norm, hitp, pp->pt_inseg->seg_stp, &(ap->a_ray), pp->pt_inflip ); RT_CURVATURE( &(rayp->curvature), hitp, pp->pt_inflip, pp->pt_inseg->seg_stp ); if ( VDOT( hitp->hit_normal, ap->a_ray.r_dir ) < 0 ) { bu_log(" debug: curvature flip\n"); rayp->curvature.crv_c1 = - rayp->curvature.crv_c1; rayp->curvature.crv_c2 = - rayp->curvature.crv_c2; } VMOVE( rayp->ip, hitp->hit_point ); VMOVE( rayp->dir, ap->a_ray.r_dir); /* Compute the specular direction */ VREVERSE( to_eye, ap->a_ray.r_dir ); f = 2 * VDOT( to_eye, rayp->norm ); VSCALE( work, rayp->norm, f ); /* I have been told this has unit length */ VSUB2( rayp->spec, work, to_eye ); VUNITIZE( rayp->spec ); /* Save info for 1st ray */ if ( ap->a_level == 0 ) { firstray[cpu_num] = ap->a_ray; /* struct copy */ rayp->sight = 1; /* the 1st intersect is always visible */ } else { /* Check for visibility */ rayp->sight = isvisible( ap, hitp, rayp->norm ); } /* * Shoot another ray in the specular direction. */ if ( ap->a_level < numreflect-1 ) { sub_ap = *ap; /* struct copy */ sub_ap.a_level = ap->a_level+1; sub_ap.a_purpose = "secondary ray"; VMOVE( sub_ap.a_ray.r_pt, hitp->hit_point ); VMOVE( sub_ap.a_ray.r_dir, rayp->spec ); depth = rt_shootray( &sub_ap ); } else { depth = 0; } if ( ap->a_level == 0 ) { rayinfo[cpu_num][0].x = ap->a_x; rayinfo[cpu_num][0].y = ap->a_y; rayinfo[cpu_num][0].surf = depth+1; rayinfo[cpu_num][0].ip[0] = ap->a_ray.r_pt[0]; rayinfo[cpu_num][0].ip[1] = ap->a_ray.r_pt[1]; rayinfo[cpu_num][0].ip[2] = ap->a_ray.r_pt[2]; radar_physics( cpu_num, depth + 1 ); #ifdef SAR dumpall( ap, cpu_num, depth + 1); #endif } return depth+1; /* report hit to main routine */ }