/* * Sort of a surface spot transparency shader. Picks transparency * based upon noise value of surface spot. */ int tsplat_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp) { register struct scloud_specific *scloud_sp = (struct scloud_specific *)dp; point_t in_pt; /* point where ray enters scloud solid */ double val; RT_CHECK_PT(pp); RT_AP_CHECK(ap); RT_CK_REGION(pp->pt_regionp); /* just shade the surface with a transparency */ MAT4X3PNT(in_pt, scloud_sp->mtos, swp->sw_hit.hit_point); val = bn_noise_fbm(in_pt, scloud_sp->h_val, scloud_sp->lacunarity, scloud_sp->octaves); CLAMP(val, 0.0, 1.0); swp->sw_transmit = 1.0 - val; if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; }
HIDDEN void _rt_tree_region_assign(union tree *tp, const struct region *regionp) { RT_CK_TREE(tp); RT_CK_REGION(regionp); switch (tp->tr_op) { case OP_NOP: return; case OP_SOLID: tp->tr_a.tu_regionp = (struct region *)regionp; return; case OP_NOT: case OP_GUARD: case OP_XNOP: tp->tr_b.tb_regionp = (struct region *)regionp; _rt_tree_region_assign(tp->tr_b.tb_left, regionp); return; case OP_UNION: case OP_INTERSECT: case OP_SUBTRACT: case OP_XOR: tp->tr_b.tb_regionp = (struct region *)regionp; _rt_tree_region_assign(tp->tr_b.tb_left, regionp); _rt_tree_region_assign(tp->tr_b.tb_right, regionp); return; default: bu_bomb("_rt_tree_region_assign: bad op\n"); } }
/* * This routine is called (at prep time) * once for each region which uses this shader. * Any shader-specific initialization should be done here. * * Returns: * 1 success * 0 success, but delete region * -1 failure */ HIDDEN int toon_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip) /* pointer to reg_udata in *rp */ /* New since 4.4 release */ { register struct toon_specific *toon_sp; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("toon_setup(%s)\n", rp->reg_name); /* Get memory for the shader parameters and shader-specific data */ BU_GET(toon_sp, struct toon_specific); *dpp = toon_sp; /* initialize the default values for the shader */ memcpy(toon_sp, &toon_defaults, sizeof(struct toon_specific)); /* parse the user's arguments for this use of the shader. */ if (bu_struct_parse(matparm, toon_parse_tab, (char *)toon_sp, NULL) < 0) return -1; if (rdebug&RDEBUG_SHADE) { bu_struct_print(" Parameters:", toon_print_tab, (char *)toon_sp); } return 1; }
void rt_pr_region(register const struct region *rp) { struct bu_vls v = BU_VLS_INIT_ZERO; RT_CK_REGION(rp); bu_log("REGION %s (bit %d)\n", rp->reg_name, rp->reg_bit); bu_log("instnum=%ld, id=%d, air=%d, gift_material=%d, los=%d\n", rp->reg_instnum, rp->reg_regionid, rp->reg_aircode, rp->reg_gmater, rp->reg_los); if (rp->reg_is_fastgen != REGION_NON_FASTGEN) { bu_log("reg_is_fastgen = %s mode\n", rp->reg_is_fastgen == REGION_FASTGEN_PLATE ? "plate" : "volume"); } if (rp->reg_mater.ma_color_valid) bu_log("Color %d %d %d\n", (int)rp->reg_mater.ma_color[0]*255, (int)rp->reg_mater.ma_color[1]*255, (int)rp->reg_mater.ma_color[2]*255); if (rp->reg_mater.ma_temperature > 0) bu_log("Temperature %g degrees K\n", INTCLAMP(rp->reg_mater.ma_temperature)); if (rp->reg_mater.ma_shader && rp->reg_mater.ma_shader[0] != '\0') bu_log("Shader '%s'\n", rp->reg_mater.ma_shader); rt_pr_tree_vls(&v, rp->reg_treetop); bu_log("%s %ld %s\n", rp->reg_name, rp->reg_instnum, bu_vls_addr(&v)); bu_vls_free(&v); }
void rt_pr_pt_vls(struct bu_vls *v, const struct rt_i *rtip, register const struct partition *pp) { register const struct soltab *stp; register struct seg **segpp; RT_CHECK_RTI(rtip); RT_CHECK_PT(pp); BU_CK_VLS(v); bu_log_indent_vls(v); bu_vls_printf(v, "%p: PT ", (void *)pp); stp = pp->pt_inseg->seg_stp; bu_vls_printf(v, "%s (%s#%ld) ", stp->st_dp->d_namep, OBJ[stp->st_id].ft_name+3, stp->st_bit); stp = pp->pt_outseg->seg_stp; bu_vls_printf(v, "%s (%s#%ld) ", stp->st_dp->d_namep, OBJ[stp->st_id].ft_name+3, stp->st_bit); bu_vls_printf(v, "(%g, %g)", pp->pt_inhit->hit_dist, pp->pt_outhit->hit_dist); if (pp->pt_inflip) bu_vls_strcat(v, " Iflip"); if (pp->pt_outflip) bu_vls_strcat(v, " Oflip"); bu_vls_strcat(v, "\n"); rt_pr_hit_vls(v, " In", pp->pt_inhit); rt_pr_hit_vls(v, " Out", pp->pt_outhit); bu_log_indent_vls(v); bu_vls_strcat(v, " Primitives: "); for (BU_PTBL_FOR(segpp, (struct seg **), &pp->pt_seglist)) { stp = (*segpp)->seg_stp; RT_CK_SOLTAB(stp); bu_vls_strcat(v, stp->st_dp->d_namep); bu_vls_strcat(v, ", "); } bu_vls_strcat(v, "\n"); bu_log_indent_vls(v); bu_vls_strcat(v, " Untrimmed Segments spanning this interval:\n"); bu_log_indent_delta(4); for (BU_PTBL_FOR(segpp, (struct seg **), &pp->pt_seglist)) { RT_CK_SEG(*segpp); rt_pr_seg_vls(v, *segpp); } bu_log_indent_delta(-4); if (pp->pt_regionp) { RT_CK_REGION(pp->pt_regionp); bu_log_indent_vls(v); bu_vls_printf(v, " Region: %s\n", pp->pt_regionp->reg_name); } }
HIDDEN int osl_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip) { register struct osl_specific *osl_sp; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("osl_setup(%s)\n", rp->reg_name); /* Get memory for the shader parameters and shader-specific data */ BU_GET(osl_sp, struct osl_specific); *dpp = (char *)osl_sp; /* ----------------------------------- * Initialize the osl specific values * ----------------------------------- */ osl_sp->magic = OSL_MAGIC; /* Parse the user's arguments to fill osl specifics */ ShaderGroupInfo group_info; if (osl_parse(matparm, group_info) < 0) { return -1; } /* ----------------------------------- * Initialize osl render system * ----------------------------------- */ /* If OSL system was not initialized yet, do it */ if (oslr == NULL) { oslr = new OSLRenderer(); } /* Add this shader to OSL system */ osl_sp->shader_ref = oslr->AddShader(group_info); if (rdebug&RDEBUG_SHADE) { bu_struct_print(" Parameters:", osl_print_tab, (char *)osl_sp); } return 1; }
/* * This routine is called (at prep time) once for each region which uses this * shader. The shader specific flat_specific structure is allocated and * default values are set. Then any user-given values override. */ HIDDEN int flat_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip) { register struct flat_specific *flat_sp; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("flat_setup(%s)\n", rp->reg_name); /* Get memory for the shader parameters and shader-specific data */ BU_GET(flat_sp, struct flat_specific); *dpp = flat_sp; /* color priority: * * priority goes first to the flat shader's color parameter * second priority is to the material color value * third priority is to the flat shader's default color (white) */ /* initialize the default values for the shader */ memcpy(flat_sp, &flat_defaults, sizeof(struct flat_specific)); /* load the material color if it was set */ if (rp->reg_mater.ma_color_valid) { VMOVE(flat_sp->color, rp->reg_mater.ma_color); } /* parse the user's arguments for this use of the shader. */ if (bu_struct_parse(matparm, flat_parse_tab, (char *)flat_sp) < 0) return -1; if (rdebug&RDEBUG_SHADE) { bu_struct_print(" Parameters:", flat_parse_tab, (char *)flat_sp); } return 1; }
/* * E X T _ S E T U P * * Returns 0 on failure, 1 on success. */ HIDDEN int ext_setup(register struct region *rp, struct bu_vls *matparm, char **dpp, struct mfuncs *mf_p, struct rt_i *rtip, struct mfuncs **headp) /* parameter string */ /* pointer to user data pointer */ { struct bu_mapped_file *parameter_file; struct bu_vls parameter_data; char *filename; int status; RT_CHECK_RTI(rtip); BU_CK_VLS( matparm ); RT_CK_REGION(rp); filename = bu_vls_addr(matparm); parameter_file = bu_open_mapped_file( filename, (char *)NULL ); if (!parameter_file) { bu_log("cannot open external shader file \"%s\"\n", filename); bu_bomb("ext_setup()\n"); } bu_vls_init(¶meter_data); bu_vls_strncpy( ¶meter_data, (char *)parameter_file->buf, parameter_file->buflen ); if (rdebug&RDEBUG_SHADE ) { bu_log("ext_setup(%s): {%s}\n", filename, bu_vls_addr(¶meter_data)); } bu_close_mapped_file( parameter_file ); status = sh_stk_setup(rp, ¶meter_data, dpp, mf_p, rtip, headp); bu_vls_free( ¶meter_data ); return status; }
int scloud_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp) { register struct scloud_specific *scloud_sp = (struct scloud_specific *)dp; point_t in_pt; /* point where ray enters scloud solid */ point_t out_pt; /* point where ray leaves scloud solid */ point_t pt; vect_t v_cloud;/* vector representing ray/solid intersection */ double thickness; /* magnitude of v_cloud (distance through solid) */ int steps; /* # of samples along ray/solid intersection */ double step_delta;/* distance between sample points, texture space */ int i; double val; double trans; point_t incident_light = VINIT_ZERO; double delta_dpmm; double density; struct shadework sub_sw; struct light_specific *lp; RT_CHECK_PT(pp); RT_AP_CHECK(ap); RT_CK_REGION(pp->pt_regionp); /* compute the ray/solid in and out points, * and transform them into "shader space" coordinates */ VJOIN1(pt, ap->a_ray.r_pt, pp->pt_inhit->hit_dist, ap->a_ray.r_dir); MAT4X3PNT(in_pt, scloud_sp->mtos, pt); VJOIN1(pt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir); MAT4X3PNT(out_pt, scloud_sp->mtos, pt); /* get ray/solid intersection vector (in noise space) * and compute thickness of solid (in noise space) along ray path */ VSUB2(v_cloud, out_pt, in_pt); thickness = MAGNITUDE(v_cloud); /* The noise field used by the bn_noise_turb and bn_noise_fbm routines * has a maximum frequency of about 1 cycle per integer step in * noise space. Each octave increases this frequency by the * "lacunarity" factor. To sample this space adequately we need * * 4 samples per integer step for the first octave, * lacunarity * 4 samples/step for the second octave, * lacunarity^2 * 4 samples/step for the third octave, * lacunarity^3 * 4 samples/step for the forth octave, * * so for a computation with 4 octaves we need something on the * order of lacunarity^3 * 4 samples per integer step in noise space. */ steps = pow(scloud_sp->lacunarity, scloud_sp->octaves-1) * 4; step_delta = thickness / (double)steps; if (rdebug&RDEBUG_SHADE) bu_log("steps=%d delta=%g thickness=%g\n", steps, step_delta, thickness); VUNITIZE(v_cloud); VMOVE(pt, in_pt); trans = 1.0; delta_dpmm = scloud_sp->max_d_p_mm - scloud_sp->min_d_p_mm; sub_sw = *swp; /* struct copy */ sub_sw.sw_inputs = MFI_HIT; for (i=0; i < steps; i++) { /* compute the next point in the cloud space */ VJOIN1(pt, in_pt, i*step_delta, v_cloud); /* get turbulence value (0 .. 1) */ val = bn_noise_turb(pt, scloud_sp->h_val, scloud_sp->lacunarity, scloud_sp->octaves); density = scloud_sp->min_d_p_mm + val * delta_dpmm; val = exp(- density * step_delta); trans *= val; if (swp->sw_xmitonly) continue; /* need to set the hit in our fake shadework structure */ MAT4X3PNT(sub_sw.sw_hit.hit_point, scloud_sp->stom, pt); sub_sw.sw_transmit = trans; sub_sw.sw_inputs = MFI_HIT; light_obs(ap, &sub_sw, swp->sw_inputs); /* now we know how much light has arrived from each * light source to this point */ for (i=ap->a_rt_i->rti_nlights-1; i >= 0; i--) { lp = (struct light_specific *)swp->sw_visible[i]; if (lp == LIGHT_NULL) continue; /* compute how much light has arrived at * this location */ incident_light[0] += sub_sw.sw_intensity[3*i+0] * lp->lt_color[0] * sub_sw.sw_lightfract[i]; incident_light[1] += sub_sw.sw_intensity[3*i+1] * lp->lt_color[1] * sub_sw.sw_lightfract[i]; incident_light[2] += sub_sw.sw_intensity[3*i+2] * lp->lt_color[2] * sub_sw.sw_lightfract[i]; } VSCALE(incident_light, incident_light, trans); } /* scloud is basically a white object with partial transparency */ swp->sw_transmit = trans; if (swp->sw_xmitonly) return 1; /* * At the point of maximum opacity, check light visibility * for light color and cloud shadowing. * OOPS: Don't use an interior point, or light_visibility() * will see an attenuated light source. */ swp->sw_hit.hit_dist = pp->pt_inhit->hit_dist; VJOIN1(swp->sw_hit.hit_point, ap->a_ray.r_pt, swp->sw_hit.hit_dist, ap->a_ray.r_dir); VREVERSE(swp->sw_hit.hit_normal, ap->a_ray.r_dir); swp->sw_inputs |= MFI_HIT | MFI_NORMAL; light_obs(ap, swp, swp->sw_inputs); VSETALL(incident_light, 0); for (i=ap->a_rt_i->rti_nlights-1; i>=0; i--) { struct light_specific *lp2; if ((lp2 = (struct light_specific *)swp->sw_visible[i]) == LIGHT_NULL) continue; /* XXX don't have a macro for this */ incident_light[0] += swp->sw_intensity[3*i+0] * lp2->lt_color[0]; incident_light[1] += swp->sw_intensity[3*i+1] * lp2->lt_color[1]; incident_light[2] += swp->sw_intensity[3*i+2] * lp2->lt_color[2]; } VELMUL(swp->sw_color, swp->sw_color, incident_light); if (rdebug&RDEBUG_SHADE) { pr_shadework("scloud: after light vis, before rr_render", swp); } if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; }
/* F I R E _ S E T U P * * This routine is called (at prep time) * once for each region which uses this shader. * Any shader-specific initialization should be done here. */ HIDDEN int fire_setup(register struct region *rp, struct bu_vls *matparm, char **dpp, struct mfuncs *mfp, struct rt_i *rtip) /* pointer to reg_udata in *rp */ /* New since 4.4 release */ { register struct fire_specific *fire_sp; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS( matparm ); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("fire_setup(%s)\n", rp->reg_name); /* Get memory for the shader parameters and shader-specific data */ BU_GETSTRUCT( fire_sp, fire_specific ); *dpp = (char *)fire_sp; /* initialize the default values for the shader */ memcpy(fire_sp, &fire_defaults, sizeof(struct fire_specific)); /* parse the user's arguments for this use of the shader. */ if (bu_struct_parse( matparm, fire_parse_tab, (char *)fire_sp ) < 0 ) return(-1); if (fire_sp->noise_size != -1.0) { VSETALL(fire_sp->noise_vscale, fire_sp->noise_size); } /* * The shader needs to operate in a coordinate system which stays * fixed on the region when the region is moved (as in animation). * We need to get a matrix to perform the appropriate transform(s). */ db_shader_mat(fire_sp->fire_m_to_sh, rtip, rp, fire_sp->fire_min, fire_sp->fire_max, &rt_uniresource); /* Build matrix to map shader space to noise space. * XXX If only we could get the frametime at this point * we could factor the flicker of flames into this matrix * rather than having to recompute it on a pixel-by-pixel basis. */ MAT_IDN(fire_sp->fire_sh_to_noise); MAT_DELTAS_VEC(fire_sp->fire_sh_to_noise, fire_sp->noise_delta); MAT_SCALE_VEC(fire_sp->fire_sh_to_noise, fire_sp->noise_vscale); /* get matrix for performing spline of fire colors */ rt_dspline_matrix(fire_sp->fire_colorspline_mat, "Catmull", 0.5, 0.0); if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug ) { bu_struct_print( " FIRE Parameters:", fire_print_tab, (char *)fire_sp ); bn_mat_print( "m_to_sh", fire_sp->fire_m_to_sh ); bn_mat_print( "sh_to_noise", fire_sp->fire_sh_to_noise ); bn_mat_print( "colorspline", fire_sp->fire_colorspline_mat ); } return(1); }
int make_hole_in_prepped_regions(struct rt_wdb *wdbp, /* database to be modified */ struct rt_i *rtip, /* rt_i pointer for the same database */ point_t hole_start, /* center of start of hole */ vect_t hole_depth, /* depth and direction of hole */ fastf_t radius, /* radius of hole */ struct bu_ptbl *regions) /* list of region structures to which this hole * is to be applied */ { struct bu_vls tmp_name = BU_VLS_INIT_ZERO; size_t i, base_len, count=0; struct directory *dp; struct rt_db_internal intern; struct soltab *stp; RT_CHECK_WDB(wdbp); /* make a unique name for the RCC we will use (of the form "make_hole_%d") */ bu_vls_strcat(&tmp_name, "make_hole_"); base_len = bu_vls_strlen(&tmp_name); bu_vls_strcat(&tmp_name, "0"); while ((db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET)) != RT_DIR_NULL) { count++; bu_vls_trunc(&tmp_name, base_len); bu_vls_printf(&tmp_name, "%zu", count); } /* build the RCC based on parameters passed in */ if (mk_rcc(wdbp, bu_vls_addr(&tmp_name), hole_start, hole_depth, radius)) { bu_log("Failed to create hole cylinder!!!\n"); bu_vls_free(&tmp_name); return 2; } /* lookup the newly created RCC */ dp=db_lookup(wdbp->dbip, bu_vls_addr(&tmp_name), LOOKUP_QUIET); if (dp == RT_DIR_NULL) { bu_log("Failed to lookup RCC (%s) just made by make_hole_in_prepped_regions()!!!\n", bu_vls_addr(&tmp_name)); bu_bomb("Failed to lookup RCC just made by make_hole_in_prepped_regions()!!!\n"); } /* get the internal form of the new RCC */ if (rt_db_get_internal(&intern, dp, wdbp->dbip, NULL, wdbp->wdb_resp) < 0) { bu_log("Failed to get internal form of RCC (%s) just made by make_hole_in_prepped_regions()!!!\n", bu_vls_addr(&tmp_name)); bu_bomb("Failed to get internal form of RCC just made by make_hole_in_prepped_regions()!!!\n"); } /* Build a soltab structure for the new RCC */ BU_ALLOC(stp, struct soltab); stp->l.magic = RT_SOLTAB_MAGIC; stp->l2.magic = RT_SOLTAB2_MAGIC; stp->st_uses = 1; stp->st_dp = dp; stp->st_bit = rtip->nsolids++; /* Add the new soltab structure to the rt_i structure */ rtip->rti_Solids = (struct soltab **)bu_realloc(rtip->rti_Solids, rtip->nsolids * sizeof(struct soltab *), "new rti_Solids"); rtip->rti_Solids[stp->st_bit] = stp; /* actually prep the new RCC */ if (intern.idb_meth->ft_prep(stp, &intern, rtip)) { bu_log("Failed to prep RCC (%s) just made by make_hole_in_prepped_regions()!!!\n", bu_vls_addr(&tmp_name)); bu_bomb("Failed to prep RCC just made by make_hole_in_prepped_regions()!!!\n"); } /* initialize the soltabs list of containing regions */ bu_ptbl_init(&stp->st_regions, BU_PTBL_LEN(regions), "stp->st_regions"); /* Subtract the new RCC from each region structure in the list provided */ for (i=0; i<BU_PTBL_LEN(regions); i++) { struct region *rp; union tree *treep; /* get the next region structure */ rp = (struct region *)BU_PTBL_GET(regions, i); RT_CK_REGION(rp); /* create a tree node for the subtraction operation, this will be the new tree root */ BU_ALLOC(treep, union tree); RT_TREE_INIT(treep); treep->tr_b.tb_op = OP_SUBTRACT; treep->tr_b.tb_left = rp->reg_treetop; /* subtract from the old treetop */ treep->tr_b.tb_regionp = rp; /* make the new node the new treetop */ rp->reg_treetop = treep; /* create a tree node for the new RCC */ BU_ALLOC(treep, union tree); RT_TREE_INIT(treep); treep->tr_a.tu_op = OP_SOLID; treep->tr_a.tu_stp = stp; treep->tr_a.tu_regionp = rp; /* the new RCC gets hung on the right of the subtract node */ rp->reg_treetop->tr_b.tb_right = treep; /* make sure the "all unions" flag is not set on this region */ rp->reg_all_unions = 0; /* Add this region to the list of containing regions for the new RCC */ bu_ptbl_ins(&stp->st_regions, (long *)rp); } /* insert the new RCC soltab structure into the already existing space partitioning tree */ insert_in_bsp(stp, &rtip->rti_CutHead); return 0; }
/* * This routine is called (at prep time) * once for each region which uses this shader. * Any shader-specific initialization should be done here. */ HIDDEN int gauss_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip) /* pointer to reg_udata in *rp */ /* New since 4.4 release */ { register struct gauss_specific *gauss_sp; struct tree_bark tb; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("gauss_setup(%s)\n", rp->reg_name); if (! rtip->useair) bu_bomb("gauss shader used and useair not set\n"); /* Get memory for the shader parameters and shader-specific data */ BU_GET(gauss_sp, struct gauss_specific); *dpp = gauss_sp; /* initialize the default values for the shader */ memcpy(gauss_sp, &gauss_defaults, sizeof(struct gauss_specific)); /* parse the user's arguments for this use of the shader. */ if (bu_struct_parse(matparm, gauss_parse_tab, (char *)gauss_sp, NULL) < 0) return -1; /* We have to pick up the parameters for the gaussian puff now. * They won't be available later. So what we do is sneak a peak * inside the region, make sure the first item in it is an ellipsoid * solid, and if it is go steal a peek at its balls ... er ... make * that definition/parameters. */ BU_LIST_INIT(&gauss_sp->dbil); tb.l = &gauss_sp->dbil; tb.dbip = rtip->rti_dbip; tb.name = rp->reg_name; tb.gs = gauss_sp; tree_solids (rp->reg_treetop, &tb, OP_UNION, &rt_uniresource); /* XXX If this puppy isn't axis-aligned, we should come up with a * matrix to rotate it into alignment. We're going to have to do * computation in the space defined by this ellipsoid. */ if (rdebug&RDEBUG_SHADE) { bu_struct_print(" Parameters:", gauss_print_tab, (char *)gauss_sp); bn_mat_print("m_to_sh", gauss_sp->gauss_m_to_sh); } return 1; }
/* * This routine is called (at prep time) * once for each region which uses this shader. * Any shader-specific initialization should be done here. * * Returns: * 1 success * 0 success, but delete region * -1 failure */ HIDDEN int bbd_setup(struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *mfp, struct rt_i *rtip) { register struct bbd_specific *bbd_sp; struct rt_db_internal intern; struct rt_tgc_internal *tgc; int s; mat_t mat; struct bbd_img *bi; double angle; vect_t vtmp; int img_num; vect_t vv; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("bbd_setup(%s)\n", rp->reg_name); RT_CK_TREE(rp->reg_treetop); if (rp->reg_treetop->tr_a.tu_op != OP_SOLID) { bu_log("--- Warning: Region %s shader %s", rp->reg_name, mfp->mf_name); bu_bomb("Shader should be used on region of single (rec/rcc) primitive\n"); } RT_CK_SOLTAB(rp->reg_treetop->tr_a.tu_stp); if (rp->reg_treetop->tr_a.tu_stp->st_id != ID_REC) { bu_log("--- Warning: Region %s shader %s", rp->reg_name, mfp->mf_name); bu_log("Shader should be used on region of single REC/RCC primitive %d\n", rp->reg_treetop->tr_a.tu_stp->st_id); bu_bomb("oops\n"); } /* Get memory for the shader parameters and shader-specific data */ BU_GET(bbd_sp, struct bbd_specific); *dpp = bbd_sp; /* initialize the default values for the shader */ memcpy(bbd_sp, &bbd_defaults, sizeof(struct bbd_specific)); bu_vls_init(&bbd_sp->img_filename); BU_LIST_INIT(&bbd_sp->imgs); bbd_sp->rtip = rtip; /* because new_image() needs this */ bbd_sp->img_count = 0; /* parse the user's arguments for this use of the shader. */ if (bu_struct_parse(matparm, bbd_parse_tab, (char *)bbd_sp, NULL) < 0) return -1; if (bbd_sp->img_count > MAX_IMAGES) { bu_log("too many images (%zu) in shader for %s sb < %d\n", bbd_sp->img_count, rp->reg_name, MAX_IMAGES); bu_bomb("excessive image count\n"); } MAT_IDN(mat); RT_DB_INTERNAL_INIT(&intern); s = rt_db_get_internal(&intern, rp->reg_treetop->tr_a.tu_stp->st_dp, rtip->rti_dbip, mat, &rt_uniresource); if (intern.idb_minor_type != ID_TGC && intern.idb_minor_type != ID_REC) { bu_log("What did I get? %d\n", intern.idb_minor_type); } if (s < 0) { bu_log("%s:%d didn't get internal", __FILE__, __LINE__); bu_bomb(""); } tgc = (struct rt_tgc_internal *)intern.idb_ptr; RT_TGC_CK_MAGIC(tgc); angle = M_PI / (double)bbd_sp->img_count; img_num = 0; VMOVE(vv, tgc->h); VUNITIZE(vv); for (BU_LIST_FOR(bi, bbd_img, &bbd_sp->imgs)) { static const point_t o = VINIT_ZERO; bn_mat_arb_rot(mat, o, vv, angle*img_num); /* compute plane equation */ MAT4X3VEC(bi->img_plane, mat, tgc->a); VUNITIZE(bi->img_plane); bi->img_plane[H] = VDOT(tgc->v, bi->img_plane); MAT4X3VEC(vtmp, mat, tgc->b); VADD2(bi->img_origin, tgc->v, vtmp); /* image origin in 3d space */ /* calculate image u vector */ VREVERSE(bi->img_x, vtmp); VUNITIZE(bi->img_x); bi->img_xlen = MAGNITUDE(vtmp) * 2; /* calculate image v vector */ VMOVE(bi->img_y, tgc->h); VUNITIZE(bi->img_y); bi->img_ylen = MAGNITUDE(tgc->h); if (rdebug&RDEBUG_SHADE) { HPRINT("\nimg_plane", bi->img_plane); VPRINT("vtmp", vtmp); VPRINT("img_origin", bi->img_origin); bu_log("img_xlen:%g ", bi->img_xlen); VPRINT("img_x", bi->img_x); bu_log("img_ylen:%g ", bi->img_ylen); VPRINT("img_y", bi->img_y); } img_num++; } rt_db_free_internal(&intern); if (rdebug&RDEBUG_SHADE) { bu_struct_print(" Parameters:", bbd_print_tab, (char *)bbd_sp); } return 1; }
/* T R E E T H E R M _ S E T U P * * This routine is called (at prep time) * once for each region which uses this shader. * Any shader-specific initialization should be done here. */ HIDDEN int tthrm_setup(register struct region *rp, struct bu_vls *matparm, genptr_t *dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *rtip) /* pointer to reg_udata in *rp */ /* New since 4.4 release */ { register struct tthrm_specific *tthrm_sp; struct bu_mapped_file *tt_file; char *tt_data; long cyl_tot = 0; long tseg; float *fp; float fv[4]; double min_temp; double max_temp; point_t center; point_t pt; vect_t dir; static const double inv_nodes = 1.0/8.0; int node; int i; int long_size = 0; size_t file_size_long; size_t file_size_int; /* check the arguments */ RT_CHECK_RTI(rtip); BU_CK_VLS(matparm); RT_CK_REGION(rp); if (rdebug&RDEBUG_SHADE) bu_log("tthrm_setup(Region:\"%s\", tthrm(%s))\n", rp->reg_name, bu_vls_addr(matparm)); /* Get memory for the shader parameters and shader-specific data */ BU_GET(tthrm_sp, struct tthrm_specific); *dpp = tthrm_sp; tthrm_sp->magic = tthrm_MAGIC; tthrm_sp->tt_name[0] = '\0'; tthrm_sp->tt_min_temp = tthrm_sp->tt_max_temp = 0.0; if (rdebug&RDEBUG_SHADE) bu_log("Parsing: (%s)\n", bu_vls_addr(matparm)); if (bu_struct_parse(matparm, tthrm_parse, (char *)tthrm_sp) < 0) { bu_bomb(__FILE__); } if (tthrm_sp->tt_name[0] == '\0') { bu_log("Must specify file for tthrm shader on %s (got \"%s\"\n", rp->reg_name, bu_vls_addr(matparm)); bu_bomb(__FILE__); } tt_file = bu_open_mapped_file(tthrm_sp->tt_name, (char *)NULL); if (!tt_file) { bu_log("Error mapping \"%s\"\n", tthrm_sp->tt_name); bu_bomb("shader tthrm: can't get thermal data"); } tt_data = tt_file->buf; if (rdebug&RDEBUG_SHADE) bu_log("tthrm_setup() data: %p total\n", (void *)tt_data); /* Compute how big the file should be, so that we can guess * at the size of the integer at the front of the file */ file_size_int = sizeof(int) + *((int *)tt_data) * (sizeof(short) + sizeof(float) * 4 * NUM_NODES); file_size_long = sizeof(long) + *((long *)tt_data) * (sizeof(short) + sizeof(float) * 4 * NUM_NODES); switch (sizeof(long)) { case 8: if (tt_file->buflen == file_size_long) { /* 64bit data on 64bit host */ long_size = sizeof(long); tthrm_sp->tt_max_seg = cyl_tot = *((long *)tt_data); } else if (tt_file->buflen == file_size_int) { /* 32bit data on 32bit host */ long_size = sizeof(int); tthrm_sp->tt_max_seg = cyl_tot = *((int *)tt_data); } break; case 4: if (tt_file->buflen == file_size_long) { /* 32bit data on 32bit host */ long_size = sizeof(long); tthrm_sp->tt_max_seg = cyl_tot = *((long *)tt_data); } else if (tt_file->buflen == (file_size_long+4)) { /* 64bit data on 32bit host */ cyl_tot = *((int *)tt_data); if (cyl_tot != 0) { bu_log("%s:%d thermal data written on 64bit machine with more that 2^32 segs\n", __FILE__, __LINE__); bu_bomb(""); } long_size = sizeof(long) + 4; tthrm_sp->tt_max_seg = cyl_tot = ((int *)tt_data)[1]; } break; default: bu_log("a long int is %d bytes on this machine\n", sizeof(long)); bu_bomb("I can only handle 4 or 8 byte longs\n"); break; } if (rdebug&RDEBUG_SHADE) bu_log("cyl_tot = %ld\n", cyl_tot); tthrm_sp->tt_segs = (struct thrm_seg *) bu_calloc(cyl_tot, sizeof(struct thrm_seg), "thermal segs"); min_temp = MAX_FASTF; max_temp = -MAX_FASTF; #define CYL_DATA(_n) ((float *) (&tt_data[ \ long_size + \ (_n) * (sizeof(short) + sizeof(float) * 4 * NUM_NODES) + \ sizeof(short) \ ])) for (tseg = 0; tseg < cyl_tot; tseg++) { /* compute centerpoint, min/max temperature values */ fp = CYL_DATA(tseg); VSETALL(center, 0.0); for (node=0; node < NUM_NODES; node++, fp+=4) { /* this is necessary to assure that all float * values are aligned on 4-byte boundaries */ memcpy(fv, fp, sizeof(float)*4); if (rdebug&RDEBUG_SHADE) bu_log("tthrm_setup() node %d (%g %g %g) %g\n", node, fv[0], fv[1], fv[2], fv[3]); /* make sure we don't have any "infinity" values */ for (i=0; i < 4; i++) { if (fv[i] > MAX_FASTF || fv[i] < -MAX_FASTF) { bu_log("%s:%d seg %ld node %d coord %d out of bounds: %g\n", __FILE__, __LINE__, tseg, node, i, fv[i]); bu_bomb("choke, gasp, *croak*\n"); } } /* copy the values to the segment list, converting * from Meters to Millimeters in the process */ VSCALE(tthrm_sp->tt_segs[tseg].node[node], fv, 1000.0); tthrm_sp->tt_segs[tseg].temperature[node] = fv[3]; VADD2(center, center, fv); if (fv[3] > max_temp) max_temp = fv[3]; if (fv[3] < min_temp) min_temp = fv[3]; } VSCALE(center, center, 1000.0); VSCALE(tthrm_sp->tt_segs[tseg].pt, center, inv_nodes); if (rdebug&RDEBUG_SHADE) { bu_log("Center: (%g %g %g) (now in mm, not m)\n", V3ARGS(tthrm_sp->tt_segs[tseg].pt)); } /* compute vectors from center pt for each node */ fp = CYL_DATA(tseg); for (node=0; node < NUM_NODES; node++, fp+=4) { /* this is necessary to assure that all float * values are aligned on 4-byte boundaries */ memcpy(fv, fp, sizeof(float)*4); VSCALE(pt, fv, 1000.0); VSUB2(tthrm_sp->tt_segs[tseg].vect[node], pt, tthrm_sp->tt_segs[tseg].pt ); } /* compute a direction vector for the thermal segment */ VCROSS(dir, tthrm_sp->tt_segs[tseg].vect[0], tthrm_sp->tt_segs[tseg].vect[2]); VUNITIZE(dir); VMOVE(tthrm_sp->tt_segs[tseg].dir, dir); tthrm_sp->tt_segs[tseg].magic = THRM_SEG_MAGIC; } bu_close_mapped_file(tt_file); if (ZERO(tthrm_sp->tt_min_temp) && EQUAL(tthrm_sp->tt_max_temp, SMALL_FASTF)) { tthrm_sp->tt_min_temp = min_temp; tthrm_sp->tt_max_temp = max_temp; bu_log("computed temp min/max on %s: %g/%g\n", rp->reg_name, min_temp, max_temp); } else { min_temp =tthrm_sp->tt_min_temp; max_temp = tthrm_sp->tt_max_temp; bu_log("taking user specified on %s: min/max %g/%g\n", rp->reg_name, min_temp, max_temp); } if (!EQUAL(max_temp, min_temp)) { tthrm_sp->tt_temp_scale = 1.0 / (max_temp - min_temp); } else { /* min and max are equal, maybe zero */ if (ZERO(max_temp)) tthrm_sp->tt_temp_scale = 0.0; else tthrm_sp->tt_temp_scale = 255.0/max_temp; } /* The shader needs to operate in a coordinate system which stays * fixed on the region when the region is moved (as in animation) * we need to get a matrix to perform the appropriate transform(s). * * Shading is done in "region coordinates": */ db_region_mat(tthrm_sp->tthrm_m_to_sh, rtip->rti_dbip, rp->reg_name, &rt_uniresource); if (rdebug&RDEBUG_SHADE) { bu_log("min_temp: %17.14e max_temp %17.14e temp_scale: %17.14e\n", tthrm_sp->tt_min_temp, tthrm_sp->tt_max_temp, tthrm_sp->tt_temp_scale); bu_log("tthrm_setup(%s, %s)done\n", rp->reg_name, bu_vls_addr(matparm)); tthrm_print(rp, *dpp); } return 1; }
/** * R T _ G E T T R E E S _ M U V E S * * User-called function to add a set of tree hierarchies to the active * set. Includes getting the indicated list of attributes and a * Tcl_HashTable for use with the ORCA man regions. (stashed in the * rt_i structure). * * This function may run in parallel, but is not multiply re-entrant * itself, because db_walk_tree() isn't multiply re-entrant. * * Semaphores used for critical sections in parallel mode: * RT_SEM_TREE* protects rti_solidheads[] lists, d_uses(solids) * RT_SEM_RESULTS protects HeadRegion, mdl_min/max, d_uses(reg), nregions * RT_SEM_WORKER (db_walk_dispatcher, from db_walk_tree) * RT_SEM_STATS nsolids * * INPUTS * rtip - RT instance pointer * attrs - array of pointers (NULL terminated) to strings (attribute names). A corresponding * array of "bu_mro" objects containing the attribute values will be attached to region * structures ("attr_values") * argc - number of trees to get * argv - array of char pointers to the names of the tree tops * ncpus - number of cpus to use * * Returns - * 0 Ordinarily * -1 On major error */ int rt_gettrees_muves(struct rt_i *rtip, const char **attrs, int argc, const char **argv, int ncpus) { register struct soltab *stp; register struct region *regp; Tcl_HashTable *tbl; int prev_sol_count; int i; int num_attrs=0; point_t region_min, region_max; RT_CHECK_RTI(rtip); RT_CK_DBI(rtip->rti_dbip); if (!rtip->needprep) { bu_log("ERROR: rt_gettree() called again after rt_prep!\n"); return(-1); /* FAIL */ } if ( argc <= 0 ) return(-1); /* FAIL */ tbl = (Tcl_HashTable *)bu_malloc( sizeof( Tcl_HashTable ), "rtip->Orca_hash_tbl" ); Tcl_InitHashTable( tbl, TCL_ONE_WORD_KEYS ); rtip->Orca_hash_tbl = (genptr_t)tbl; prev_sol_count = rtip->nsolids; { struct db_tree_state tree_state; tree_state = rt_initial_tree_state; /* struct copy */ tree_state.ts_dbip = rtip->rti_dbip; tree_state.ts_rtip = rtip; tree_state.ts_resp = NULL; /* sanity. Needs to be updated */ if ( attrs ) { if ( rtip->rti_dbip->dbi_version < 5 ) { bu_log( "WARNING: requesting attributes from an old database version (ignored)\n" ); bu_avs_init_empty( &tree_state.ts_attrs ); } else { while ( attrs[num_attrs] ) { num_attrs++; } if ( num_attrs ) { bu_avs_init( &tree_state.ts_attrs, num_attrs, "avs in tree_state" ); num_attrs = 0; while ( attrs[num_attrs] ) { bu_avs_add( &tree_state.ts_attrs, attrs[num_attrs], NULL ); num_attrs++; } } else { bu_avs_init_empty( &tree_state.ts_attrs ); } } } else { bu_avs_init_empty( &tree_state.ts_attrs ); } /* ifdef this out for now, it is only using memory. perhaps a * better way of initiating ORCA stuff can be found. */ #if 0 bu_avs_add( &tree_state.ts_attrs, "ORCA_Comp", (char *)NULL ); #endif i = db_walk_tree( rtip->rti_dbip, argc, argv, ncpus, &tree_state, rt_gettree_region_start, rt_gettree_region_end, rt_gettree_leaf, (genptr_t)tbl ); bu_avs_free( &tree_state.ts_attrs ); } /* DEBUG: Ensure that all region trees are valid */ for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) { RT_CK_REGION(regp); db_ck_tree(regp->reg_treetop); } /* * Eliminate any "dead" solids that parallel code couldn't change. * First remove any references from the region tree, then remove * actual soltab structs from the soltab list. */ for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) ) { RT_CK_REGION(regp); rt_tree_kill_dead_solid_refs( regp->reg_treetop ); (void)rt_tree_elim_nops( regp->reg_treetop, &rt_uniresource ); } again: RT_VISIT_ALL_SOLTABS_START( stp, rtip ) { RT_CK_SOLTAB(stp); if ( stp->st_aradius <= 0 ) { bu_log("rt_gettrees() cleaning up dead solid '%s'\n", stp->st_dp->d_namep ); rt_free_soltab(stp); /* Can't do rtip->nsolids--, that doubles as max bit number! */ /* The macro makes it hard to regain place, punt */ goto again; } } RT_VISIT_ALL_SOLTABS_END