HIDDEN int wood_setup(register struct region *rp, struct bu_vls *matparm, void **dpp, const struct mfuncs *UNUSED(mfp), struct rt_i *UNUSED(rtip)) /* New since 4.4 release */ { register int i; register struct wood_specific *wd; register struct resource *resp = &rt_uniresource; /* * Get the impure storage for the control block */ BU_CK_VLS(matparm); BU_GET(wd, struct wood_specific); *dpp = wd; /* * Load the default values */ if (rp->reg_mater.ma_color_valid) { VSCALE(wd->lt_rgb, rp->reg_mater.ma_color, 255); } else { wd->lt_rgb[0] = 255; /* Light yellow */ wd->lt_rgb[1] = 255; wd->lt_rgb[2] = 224; } wd->dk_rgb[0] = 191; /* Brownish-red */ wd->dk_rgb[1] = 97; wd->dk_rgb[2] = 0; wd->ident = 0; wd->forw = WOOD_NULL; wd->rp = rp; wd->flags = 0; wd->overlay = 0; /* Draw only one ring */ wd->ns = 10; wd->jitter = 0.0; wd->scale = 1.0; wd->spacing = 5; /* 5mm space between rings */ wd->dd = 0.0; /* no dither of vertex */ wd->dz = 0.0; /* nor of Z-axis */ wd->qd = 0; wd->qp = 0; wd->phase = 5; wd->depth = 0; wd->dither[0] = bn_rand0to1(resp->re_randptr); wd->dither[1] = bn_rand0to1(resp->re_randptr); wd->dither[2] = bn_rand0to1(resp->re_randptr); VSETALL(wd->rot, 0); VSETALL(wd->vertex, 0); VSETALL(wd->D, 0); VSETALL(wd->V, 0); /* * Parse the MATPARM field */ if (bu_struct_parse(matparm, wood_parse, (char *)wd) < 0) { BU_PUT(wd, struct wood_specific); return -1; } /* * Do some sundry range and misc. checking */ for (i = 0; i < 3; i++) { if (wd->dither[i] < 0 || wd->dither[i] > 1.0) { bu_log("wood_setup(%s): dither is out of range.\n", rp->reg_name); return -1; } } if (wd->flags == EXPLICIT_VERTEX) { bu_log("wood_setup(%s): Explicit vertex specified without direction\n", rp->reg_name); return -1; } if (wd->flags == EXPLICIT_DIRECTION) { bu_log("wood_setup(%s): Explicit direction specified without vertex\n", rp->reg_name); return -1; } /* * Get the bounding RPP */ if (rt_bound_tree(rp->reg_treetop, wd->b_min, wd->b_max) < 0) return -1; /* * Add it to the wood chain */ wd->forw = Wood_Chain; Wood_Chain = wd; /* * See if the user has flagged this region as a member of a larger * combination. If so, go ahead and process it */ if (wd->ident == 0) wood_setup_2(wd); else { register struct wood_specific *wc; vect_t c_min, c_max; /* * First, process the accumulated chain of wood regions and * process all regions which have the specified ident field. */ VSETALL(c_min, 0); VSETALL(c_max, 0); for (wc = Wood_Chain; wc != WOOD_NULL; wc = wc->forw) { if (wc->ident == wd->ident) { VMIN(c_min, wc->b_min); VMAX(c_max, wc->b_max); } } /* * Now, loop through the chain again this time updating the * regions' min/max fields with the new values */ for (wc = Wood_Chain; wc != WOOD_NULL; wc = wc->forw) { if (wc->ident == wd->ident) { VMOVE(wc->b_min, c_min); VMOVE(wc->b_max, c_max); wood_setup_2(wc); } } /* * End of multi-region processing loop */ } /* * Normalize the RGB colors */ for (i = 0; i < 3; i++) { wd->lt_rgb[i] /= 255.0; wd->dk_rgb[i] /= 255.0; } /* * Return to the caller */ return 1; }
/* * Process a space command. * Behavior depends on setting of several flags. * * Implicit Returns - * In all cases, sets space_min and space_max. */ int model_rpp(const fastf_t *min, const fastf_t *max) { if (space_set) { bu_log("plot3rot: additional SPACE command ignored\n"); bu_log("got: space (%g, %g, %g) (%g, %g, %g)\n", V3ARGS(min), V3ARGS(max)); bu_log("still using: space (%g, %g, %g) (%g, %g, %g)\n", V3ARGS(space_min), V3ARGS(space_max)); return 0; } if (rpp) { point_t rot_center; /* center of rotation */ mat_t xlate; mat_t resize; mat_t t1, t2; VADD2SCALE(rot_center, min, max, 0.5); /* Create the matrix which encodes this */ MAT_IDN(xlate); MAT_DELTAS_VEC_NEG(xlate, rot_center); MAT_IDN(resize); resize[15] = 1/scale; bn_mat_mul(t1, resize, xlate); bn_mat_mul(t2, rmat, t1); MAT_COPY(rmat, t2); if (verbose) { bn_mat_print("rmat", rmat); } if (Mflag) { /* Don't rebound, just expand size of space * around center point. * Has advantage of the output space() not being * affected by changes in rotation, * which may be significant for animation scripts. */ vect_t diag; double v; VSUB2(diag, max, min); v = MAGNITUDE(diag)*0.5 + 0.5; VSET(space_min, -v, -v, -v); VSET(space_max, v, v, v); } else { /* re-bound the space() rpp with a tighter one * after rotating & scaling it. */ bn_rotate_bbox(space_min, space_max, rmat, min, max); } space_set = 1; } else { VMOVE(space_min, min); VMOVE(space_max, max); space_set = 1; } if (forced_space) { /* Put forced space back */ VMOVE(space_min, forced_space_min); VMOVE(space_max, forced_space_max); space_set = 1; } if (verbose) { bu_log("got: space (%g, %g, %g) (%g, %g, %g)\n", V3ARGS(min), V3ARGS(max)); bu_log("put: space (%g, %g, %g) (%g, %g, %g)\n", V3ARGS(space_min), V3ARGS(space_max)); } return 1; }
int main(int argc, char **argv) { int faces[15]; fastf_t vertices[36]; fastf_t thickness[4]; struct rt_wdb *outfp = NULL; struct bu_bitv *face_mode = NULL; static const char *filename = "bot-test.g"; if (BU_STR_EQUAL(argv[1], "-h") || BU_STR_EQUAL(argv[1], "-?")) { printusage(); return 0; } if (argc == 1) { printusage(); fprintf(stderr," Program continues running (will create file bot-test.g because 'filename' was blank):\n"); } else if (argc > 1) filename = argv[1]; outfp = wdb_fopen(filename); mk_id(outfp, "BOT test"); VSET(vertices, 0.0, 0.0, 0.0); VSET(&vertices[3], 0.0, 100.0, 0.0); VSET(&vertices[6], 0.0, 100.0, 50.0); VSET(&vertices[9], 200.0, 0.0, 0.0); /* face #1 */ faces[0] = 0; faces[1] = 1; faces[2] = 2; /* face #2 */ faces[3] = 0; faces[4] = 2; faces[5] = 3; /* face #3 */ faces[6] = 0; faces[7] = 1; faces[8] = 3; /* face #4 */ faces[9] = 1; faces[10] = 2; faces[11] = 3; mk_bot(outfp, "bot_u_surf", RT_BOT_SURFACE, RT_BOT_UNORIENTED, 0, 4, 4, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); /* face #1 */ faces[0] = 0; faces[1] = 2; faces[2] = 1; /* face #2 */ faces[3] = 0; faces[4] = 3; faces[5] = 2; /* face #3 */ faces[6] = 0; faces[7] = 1; faces[8] = 3; /* face #4 */ faces[9] = 1; faces[10] = 2; faces[11] = 3; mk_bot(outfp, "bot_ccw_surf", RT_BOT_SURFACE, RT_BOT_CCW, 0, 4, 4, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); /* face #1 */ faces[0] = 1; faces[1] = 2; faces[2] = 0; /* face #2 */ faces[3] = 2; faces[4] = 3; faces[5] = 0; /* face #3 */ faces[6] = 3; faces[7] = 1; faces[8] = 0; /* face #4 */ faces[9] = 3; faces[10] = 2; faces[11] = 1; mk_bot(outfp, "bot_cw_surf", RT_BOT_SURFACE, RT_BOT_CW, 0, 4, 4, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); /* face #1 */ faces[0] = 0; faces[1] = 1; faces[2] = 2; /* face #2 */ faces[3] = 0; faces[4] = 2; faces[5] = 3; /* face #3 */ faces[6] = 0; faces[7] = 1; faces[8] = 3; /* face #4 */ faces[9] = 1; faces[10] = 2; faces[11] = 3; mk_bot(outfp, "bot_u_solid", RT_BOT_SOLID, RT_BOT_UNORIENTED, 0, 4, 4, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); /* face #1 */ faces[0] = 0; faces[1] = 2; faces[2] = 1; /* face #2 */ faces[3] = 0; faces[4] = 3; faces[5] = 2; /* face #3 */ faces[6] = 0; faces[7] = 1; faces[8] = 3; /* face #4 */ faces[9] = 1; faces[10] = 2; faces[11] = 3; mk_bot(outfp, "bot_ccw_solid", RT_BOT_SOLID, RT_BOT_CCW, 0, 4, 4, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); /* face #1 */ faces[0] = 1; faces[1] = 2; faces[2] = 0; /* face #2 */ faces[3] = 2; faces[4] = 3; faces[5] = 0; /* face #3 */ faces[6] = 3; faces[7] = 1; faces[8] = 0; /* face #4 */ faces[9] = 3; faces[10] = 2; faces[11] = 1; mk_bot(outfp, "bot_cw_solid", RT_BOT_SOLID, RT_BOT_CW, 0, 4, 4, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); face_mode = bu_bitv_new(4); BU_BITSET(face_mode, 1); thickness[0] = 2.1; thickness[1] = 2.2; thickness[2] = 2.3; thickness[3] = 2.4; /* face #1 */ faces[0] = 0; faces[1] = 1; faces[2] = 2; /* face #2 */ faces[3] = 0; faces[4] = 2; faces[5] = 3; /* face #3 */ faces[6] = 0; faces[7] = 1; faces[8] = 3; /* face #4 */ faces[9] = 1; faces[10] = 2; faces[11] = 3; mk_bot(outfp, "bot_u_plate", RT_BOT_PLATE, RT_BOT_UNORIENTED, 0, 4, 4, vertices, faces, thickness, face_mode); /* face #1 */ faces[0] = 0; faces[1] = 2; faces[2] = 1; /* face #2 */ faces[3] = 0; faces[4] = 3; faces[5] = 2; /* face #3 */ faces[6] = 0; faces[7] = 1; faces[8] = 3; /* face #4 */ faces[9] = 1; faces[10] = 2; faces[11] = 3; mk_bot(outfp, "bot_ccw_plate", RT_BOT_PLATE, RT_BOT_CCW, 0, 4, 4, vertices, faces, thickness, face_mode); /* face #1 */ faces[0] = 1; faces[1] = 2; faces[2] = 0; /* face #2 */ faces[3] = 2; faces[4] = 3; faces[5] = 0; /* face #3 */ faces[6] = 3; faces[7] = 1; faces[8] = 0; /* face #4 */ faces[9] = 3; faces[10] = 2; faces[11] = 1; mk_bot(outfp, "bot_cw_plate", RT_BOT_PLATE, RT_BOT_CW, 0, 4, 4, vertices, faces, thickness, face_mode); /* Make a bot with duplicate vertices to test the "fuse" and "condense" code */ VSET(vertices, 0.0, 0.0, 0.0); VSET(&vertices[3], 0.0, 100.0, 0.0); VSET(&vertices[6], 0.0, 100.0, 50.0); VMOVE(&vertices[9], &vertices[0]); VMOVE(&vertices[12], &vertices[6]); VSET(&vertices[15], 200.0, 0.0, 0.0); VMOVE(&vertices[18], &vertices[0]); VMOVE(&vertices[21], &vertices[3]); VMOVE(&vertices[24], &vertices[15]); VMOVE(&vertices[27], &vertices[3]); VMOVE(&vertices[30], &vertices[6]); VMOVE(&vertices[33], &vertices[15]); /* face #1 */ faces[0] = 0; faces[1] = 1; faces[2] = 2; /* face #2 */ faces[3] = 3; faces[4] = 4; faces[5] = 5; /* face #3 */ faces[6] = 6; faces[7] = 7; faces[8] = 8; /* face #4 */ faces[9] = 9; faces[10] = 10; faces[11] = 11; mk_bot(outfp, "bot_solid_dup_vs", RT_BOT_SOLID, RT_BOT_UNORIENTED, 0, 12, 4, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); faces[12] = 9; faces[13] = 10; faces[14] = 11; mk_bot(outfp, "bot_solid_dup_fs", RT_BOT_SOLID, RT_BOT_UNORIENTED, 0, 12, 5, vertices, faces, (fastf_t *)NULL, (struct bu_bitv *)NULL); bu_free((char *)face_mode, "bottest: face_mode"); wdb_close(outfp); return 0; }
HIDDEN int nmg_brep_face(ON_Brep **b, const struct faceuse *fu, const struct bn_tol *tol, long *brepi) { const struct face_g_plane *fg = fu->f_p->g.plane_p; struct bu_ptbl vert_table; struct vertex **pt; int ret = 0; int pnt_cnt = 0; int pnt_index = 0; vect_t u_axis, v_axis; point_t obr_center; point_t *points_3d = NULL; point_t *points_obr = NULL; struct loopuse *lu; struct edgeuse *eu; /* Find out how many points we have, set up any uninitialized ON_Brep vertex * structures, and prepare a map of NMG index values to the point array indices */ nmg_tabulate_face_g_verts(&vert_table, fg); for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { if (brepi[(*pt)->vg_p->index] == -INT_MAX) { ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF); brepi[(*pt)->vg_p->index] = vert.m_vertex_index; } pnt_cnt++; } /* Prepare the 3D obr input array */ points_3d = (point_t *)bu_calloc(pnt_cnt + 1, sizeof(point_t), "nmg points"); for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { VSET(points_3d[pnt_index], (*pt)->vg_p->coord[0],(*pt)->vg_p->coord[1],(*pt)->vg_p->coord[2]); pnt_index++; } bu_ptbl_free(&vert_table); /* Calculate the 3D coplanar oriented bounding rectangle (obr) */ ret += bg_3d_coplanar_obr(&obr_center, &u_axis, &v_axis, (const point_t *)points_3d, pnt_cnt); if (ret) { bu_log("Failed to get oriented bounding rectangle for NMG faceuse #%lu\n", fu->index); return -1; } bu_free(points_3d, "done with obr 3d point inputs"); /* Use the obr to define the 3D corner points of the NURBS surface */ points_obr = (point_t *)bu_calloc(3 + 1, sizeof(point_t), "points_3d"); VADD3(points_obr[2], obr_center, u_axis, v_axis); VSCALE(u_axis, u_axis, -1); VADD3(points_obr[3], obr_center, u_axis, v_axis); VSCALE(v_axis, v_axis, -1); VADD3(points_obr[0], obr_center, u_axis, v_axis); VSCALE(u_axis, u_axis, -1); VADD3(points_obr[1], obr_center, u_axis, v_axis); /* We need to orient our surface correctly according to the NMG - using * the openNURBS FlipFace function later does not seem to work very * well. If an outer loop is found in the NMG with a cw orientation, * factor that in in addition to the fu->f_p->flip flag. */ int ccw = 0; vect_t vtmp, uv1, uv2, vnormal; point_t center; VADD2(center, points_obr[0], points_obr[1]); VADD2(center, center, points_obr[2]); VADD2(center, center, points_obr[3]); VSCALE(center, center, 0.25); for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1; } if (ccw != -1) { VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]); } else { VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]); } if (fu->f_p->flip) VSET(vnormal, -vnormal[0], -vnormal[1], -vnormal[2]); VSUB2(uv1, points_obr[0], center); VSUB2(uv2, points_obr[1], center); VCROSS(vtmp, uv1, uv2); if (VDOT(vtmp, vnormal) < 0) { VMOVE(vtmp, points_obr[0]); VMOVE(points_obr[0], points_obr[1]); VMOVE(points_obr[1], vtmp); VMOVE(vtmp, points_obr[3]); VMOVE(points_obr[3], points_obr[2]); VMOVE(points_obr[2], vtmp); } /* Now that we've got our points correctly oriented for * the NURBS surface, proceed to create it. */ ON_3dPoint p1 = ON_3dPoint(points_obr[0]); ON_3dPoint p2 = ON_3dPoint(points_obr[1]); ON_3dPoint p3 = ON_3dPoint(points_obr[2]); ON_3dPoint p4 = ON_3dPoint(points_obr[3]); (*b)->m_S.Append(sideSurface(p1, p2, p3, p4)); ON_Surface *surf = (*(*b)->m_S.Last()); int surfindex = (*b)->m_S.Count(); ON_BrepFace& face = (*b)->NewFace(surfindex - 1); // With the surface and the face defined, make // trimming loops and create faces. To generate UV // coordinates for each from and to for the // edgecurves, the UV origin is defined to be v1, // v1->v2 is defined as the U domain, and v1->v4 is // defined as the V domain. VSUB2(u_axis, points_obr[2], points_obr[1]); VSUB2(v_axis, points_obr[0], points_obr[1]); fastf_t u_axis_dist = MAGNITUDE(u_axis); fastf_t v_axis_dist = MAGNITUDE(v_axis); /* Now that we have the surface and the face, add the loops */ for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex // Check if this is an inner or outer loop ON_BrepLoop::TYPE looptype = (lu->orientation == OT_SAME) ? ON_BrepLoop::outer : ON_BrepLoop::inner; ON_BrepLoop& loop = (*b)->NewLoop(looptype, face); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { vect_t ev1, ev2; struct vertex_g *vg1 = eu->vu_p->v_p->vg_p; struct vertex_g *vg2 = eu->eumate_p->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg1); NMG_CK_VERTEX_G(vg2); VMOVE(ev1, vg1->coord); VMOVE(ev2, vg2->coord); // Add edge if not already added if (brepi[eu->e_p->index] == -INT_MAX) { /* always add edges with the small vertex index as from */ int vert1 = (vg1->index <= vg2->index) ? brepi[vg1->index] : brepi[vg2->index]; int vert2 = (vg1->index > vg2->index) ? brepi[vg1->index] : brepi[vg2->index]; // Create and add 3D curve ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point()); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); // Create and add 3D edge ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1); e.m_tolerance = 0.0; brepi[eu->e_p->index] = e.m_edge_index; } // Regardless of whether the edge existed as an object, it needs to be added to the trimming loop ON_3dPoint vg1pt(vg1->coord); int orientation = ((vg1pt != (*b)->m_V[(*b)->m_E[(int)brepi[eu->e_p->index]].m_vi[0]].Point())) ? 1 : 0; // Make a 2d trimming curve, create a trim, and add the trim to the loop vect_t vect1, vect2, u_component, v_component; double u0, u1, v0, v1; ON_2dPoint from_uv, to_uv; VSUB2(vect1, ev1, points_obr[0]); VSUB2(vect2, ev2, points_obr[0]); surf->GetDomain(0, &u0, &u1); surf->GetDomain(1, &v0, &v1); VPROJECT(vect1, u_axis, u_component, v_component); from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); VPROJECT(vect2, u_axis, u_component, v_component); to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0); to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0); ON_Curve* c2d = new ON_LineCurve(from_uv, to_uv); c2d->SetDomain(0.0, 1.0); int c2i = (*b)->m_C2.Count(); (*b)->m_C2.Append(c2d); ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[(int)brepi[eu->e_p->index]], orientation, loop, c2i); trim.m_type = ON_BrepTrim::mated; trim.m_tolerance[0] = 0.0; trim.m_tolerance[1] = 0.0; } } bu_free(points_obr, "Done with obr"); return 0; }
/** * Convert from "network" doubles to machine specific. * Transform */ int rt_arbn_import4(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip) { union record *rp; struct rt_arbn_internal *aip; size_t i; /* must be double for import and export */ double *scan; if (dbip) RT_CK_DBI(dbip); BU_CK_EXTERNAL(ep); rp = (union record *)ep->ext_buf; if (rp->u_id != DBID_ARBN) { bu_log("rt_arbn_import4: defective record, id=x%x\n", rp->u_id); return -1; } RT_CK_DB_INTERNAL(ip); ip->idb_major_type = DB5_MAJORTYPE_BRLCAD; ip->idb_type = ID_ARBN; ip->idb_meth = &OBJ[ID_ARBN]; BU_ALLOC(ip->idb_ptr, struct rt_arbn_internal); aip = (struct rt_arbn_internal *)ip->idb_ptr; aip->magic = RT_ARBN_INTERNAL_MAGIC; aip->neqn = ntohl(*(uint32_t *)rp->n.n_neqn); if (aip->neqn <= 0) return -1; aip->eqn = (plane_t *)bu_malloc(aip->neqn*sizeof(plane_t), "arbn plane eqn[]"); scan = (double *)bu_malloc(aip->neqn*sizeof(double)*ELEMENTS_PER_PLANE, "scan array"); bu_cv_ntohd((unsigned char *)scan, (unsigned char *)(&rp[1]), aip->neqn*ELEMENTS_PER_PLANE); for (i = 0; i < aip->neqn; i++) { aip->eqn[i][X] = scan[(i*ELEMENTS_PER_PLANE)+0]; /* convert double to fastf_t */ aip->eqn[i][Y] = scan[(i*ELEMENTS_PER_PLANE)+1]; /* convert double to fastf_t */ aip->eqn[i][Z] = scan[(i*ELEMENTS_PER_PLANE)+2]; /* convert double to fastf_t */ aip->eqn[i][W] = scan[(i*ELEMENTS_PER_PLANE)+3]; /* convert double to fastf_t */ } bu_free(scan, "scan array"); /* Transform by the matrix */ if (mat == NULL) mat = bn_mat_identity; for (i = 0; i < aip->neqn; i++) { point_t orig_pt; point_t pt; vect_t norm; fastf_t factor; /* unitize the plane equation first */ factor = 1.0 / MAGNITUDE(aip->eqn[i]); VSCALE(aip->eqn[i], aip->eqn[i], factor); aip->eqn[i][W] = aip->eqn[i][W] * factor; /* Pick a point on the original halfspace */ VSCALE(orig_pt, aip->eqn[i], aip->eqn[i][W]); /* Transform the point, and the normal */ MAT4X3VEC(norm, mat, aip->eqn[i]); MAT4X3PNT(pt, mat, orig_pt); /* Measure new distance from origin to new point */ VUNITIZE(norm); VMOVE(aip->eqn[i], norm); aip->eqn[i][W] = VDOT(pt, norm); } return 0; }
/* 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; }
void bn_vtoh_move(register vect_t h, register const vect_t v) { VMOVE(h, v); h[W] = 1.0; }
int ged_move_botpts(struct ged *gedp, int argc, const char *argv[]) { static const char *usage = "bot vec vertex_1 [vertex_2 ... vertex_n]"; struct directory *dp; struct rt_db_internal intern; struct rt_bot_internal *botip; mat_t mat; register int i; size_t vertex_i; char *last; /* must be double for scanf */ double vec[ELEMENTS_PER_VECT]; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 4) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } if ((last = strrchr(argv[1], '/')) == NULL) last = (char *)argv[1]; else ++last; if (last[0] == '\0') { bu_vls_printf(gedp->ged_result_str, "%s: illegal input - %s", argv[0], argv[1]); return GED_ERROR; } dp = db_lookup(gedp->ged_wdbp->dbip, last, LOOKUP_QUIET); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]); return GED_ERROR; } if (bu_sscanf(argv[2], "%lf %lf %lf", &vec[X], &vec[Y], &vec[Z]) != 3) { bu_vls_printf(gedp->ged_result_str, "%s: bad vector - %s", argv[0], argv[2]); return GED_ERROR; } VSCALE(vec, vec, gedp->ged_wdbp->dbip->dbi_local2base); if (wdb_import_from_path2(gedp->ged_result_str, &intern, argv[1], gedp->ged_wdbp, mat) == GED_ERROR) { bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]); return GED_ERROR; } if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) { bu_vls_printf(gedp->ged_result_str, "Object is not a BOT"); rt_db_free_internal(&intern); return GED_ERROR; } botip = (struct rt_bot_internal *)intern.idb_ptr; for (i = 3; i < argc; ++i) { if (bu_sscanf(argv[i], "%zu", &vertex_i) != 1) { bu_vls_printf(gedp->ged_result_str, "%s: bad bot vertex index - %s\n", argv[0], argv[i]); continue; } if (vertex_i >= botip->num_vertices) { bu_vls_printf(gedp->ged_result_str, "%s: bad bot vertex index - %s\n", argv[0], argv[i]); continue; } VADD2(&botip->vertices[vertex_i*3], vec, &botip->vertices[vertex_i*3]); } { mat_t invmat; point_t curr_pt; size_t idx; bn_mat_inv(invmat, mat); for (idx = 0; idx < botip->num_vertices; idx++) { MAT4X3PNT(curr_pt, invmat, &botip->vertices[idx*3]); VMOVE(&botip->vertices[idx*3], curr_pt); } } GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); rt_db_free_internal(&intern); return GED_OK; }
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]; } }
int ged_bot_face_split(struct ged *gedp, int argc, const char *argv[]) { static const char *usage = "bot face"; struct directory *dp; static fastf_t sf = 1.0 / 3.0; struct rt_db_internal intern; struct rt_bot_internal *botip; mat_t mat; char *last; size_t face_i; size_t last_vi; size_t save_vi; point_t new_pt; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } if ((last = strrchr(argv[1], '/')) == NULL) last = (char *)argv[1]; else ++last; if (last[0] == '\0') { bu_vls_printf(gedp->ged_result_str, "%s: illegal input - %s", argv[0], argv[1]); return GED_ERROR; } dp = db_lookup(gedp->ged_wdbp->dbip, last, LOOKUP_QUIET); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]); return GED_ERROR; } if (bu_sscanf(argv[2], "%zu", &face_i) != 1) { bu_vls_printf(gedp->ged_result_str, "%s: bad bot vertex index - %s", argv[0], argv[2]); return GED_ERROR; } if (wdb_import_from_path2(gedp->ged_result_str, &intern, last, gedp->ged_wdbp, mat) == GED_ERROR) { bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]); return GED_ERROR; } if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) { bu_vls_printf(gedp->ged_result_str, "Object is not a BOT"); rt_db_free_internal(&intern); return GED_ERROR; } botip = (struct rt_bot_internal *)intern.idb_ptr; last_vi = botip->num_vertices; if (face_i >= botip->num_faces) { bu_vls_printf(gedp->ged_result_str, "%s: bad bot face index - %s", argv[0], argv[2]); rt_db_free_internal(&intern); return GED_ERROR; } /* Create the new point, modify face_i and hook in the two extra faces */ /* First, create some space */ botip->num_vertices++; botip->num_faces += 2; botip->vertices = (fastf_t *)bu_realloc((void *)botip->vertices, botip->num_vertices*3*sizeof(fastf_t), "realloc bot vertices"); botip->faces = (int *)bu_realloc((void *)botip->faces, botip->num_faces*3*sizeof(int), "realloc bot faces"); /* Create the new point. For the moment, we're using the average of the face_i's points */ VADD3(new_pt, &botip->vertices[botip->faces[face_i*3]*3], &botip->vertices[botip->faces[face_i*3+1]*3], &botip->vertices[botip->faces[face_i*3+2]*3]); VSCALE(new_pt, new_pt, sf); /* Add the new point to the last position in the list of vertices. */ VMOVE(&botip->vertices[last_vi*3], new_pt); /* Update face_i */ save_vi = botip->faces[face_i*3+2]; botip->faces[face_i*3+2] = last_vi; /* Initialize the two new faces */ botip->faces[(botip->num_faces-2)*3] = botip->faces[face_i*3+1]; botip->faces[(botip->num_faces-2)*3+1] = save_vi; botip->faces[(botip->num_faces-2)*3+2] = last_vi; botip->faces[(botip->num_faces-1)*3] = save_vi; botip->faces[(botip->num_faces-1)*3+1] = botip->faces[face_i*3]; botip->faces[(botip->num_faces-1)*3+2] = last_vi; bu_vls_printf(gedp->ged_result_str, "%zu", last_vi); GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); rt_db_free_internal(&intern); return GED_OK; }
int ged_bot_edge_split(struct ged *gedp, int argc, const char *argv[]) { static const char *usage = "bot edge"; struct directory *dp; struct rt_db_internal intern; struct rt_bot_internal *botip; mat_t mat; char *last; size_t v1_i; size_t v2_i; size_t last_fi; size_t last_vi; size_t save_vi; size_t i; point_t new_pt; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } if ((last = strrchr(argv[1], '/')) == NULL) last = (char *)argv[1]; else ++last; if (last[0] == '\0') { bu_vls_printf(gedp->ged_result_str, "%s: illegal input - %s", argv[0], argv[1]); return GED_ERROR; } dp = db_lookup(gedp->ged_wdbp->dbip, last, LOOKUP_QUIET); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]); return GED_ERROR; } if (bu_sscanf(argv[2], "%zu %zu", &v1_i, &v2_i) != 2) { bu_vls_printf(gedp->ged_result_str, "%s: bad bot edge - %s", argv[0], argv[2]); return GED_ERROR; } if (wdb_import_from_path2(gedp->ged_result_str, &intern, last, gedp->ged_wdbp, mat) == GED_ERROR) { bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]); return GED_ERROR; } if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD || intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) { bu_vls_printf(gedp->ged_result_str, "Object is not a BOT"); rt_db_free_internal(&intern); return GED_ERROR; } botip = (struct rt_bot_internal *)intern.idb_ptr; last_fi = botip->num_faces; last_vi = botip->num_vertices; if (v1_i >= botip->num_vertices || v2_i >= botip->num_vertices) { bu_vls_printf(gedp->ged_result_str, "%s: bad bot edge - %s", argv[0], argv[2]); rt_db_free_internal(&intern); return GED_ERROR; } /* * Create the new point, modify all faces (should only be two) * that share the specified edge and hook in the two extra faces. */ /* First, create some space */ botip->num_vertices++; botip->num_faces += 2; botip->vertices = (fastf_t *)bu_realloc((void *)botip->vertices, botip->num_vertices*3*sizeof(fastf_t), "realloc bot vertices"); botip->faces = (int *)bu_realloc((void *)botip->faces, botip->num_faces*3*sizeof(int), "realloc bot faces"); /* Create the new point. We're using the average of the edge's points */ VADD2(new_pt, &botip->vertices[v1_i*3], &botip->vertices[v2_i*3]); VSCALE(new_pt, new_pt, 0.5); /* Add the new point to the last position in the list of vertices. */ VMOVE(&botip->vertices[last_vi*3], new_pt); /* Update faces associated with the specified edge */ for (i = 0; i < last_fi; ++i) { if (((size_t)botip->faces[i*3] == v1_i && (size_t)botip->faces[i*3+1] == v2_i) || ((size_t)botip->faces[i*3] == v2_i && (size_t)botip->faces[i*3+1] == v1_i)) { save_vi = botip->faces[i*3+1]; botip->faces[i*3+1] = last_vi; /* Initialize a new face */ botip->faces[last_fi*3] = last_vi; botip->faces[last_fi*3+1] = save_vi; botip->faces[last_fi*3+2] = botip->faces[i*3+2]; ++last_fi; } else if (((size_t)botip->faces[i*3] == v1_i && (size_t)botip->faces[i*3+2] == v2_i) || ((size_t)botip->faces[i*3] == v2_i && (size_t)botip->faces[i*3+2] == v1_i)) { save_vi = botip->faces[i*3]; botip->faces[i*3] = last_vi; /* Initialize a new face */ botip->faces[last_fi*3] = last_vi; botip->faces[last_fi*3+1] = save_vi; botip->faces[last_fi*3+2] = botip->faces[i*3+1]; ++last_fi; } else if (((size_t)botip->faces[i*3+1] == v1_i && (size_t)botip->faces[i*3+2] == v2_i) || ((size_t)botip->faces[i*3+1] == v2_i && (size_t)botip->faces[i*3+2] == v1_i)) { save_vi = botip->faces[i*3+2]; botip->faces[i*3+2] = last_vi; /* Initialize a new face */ botip->faces[last_fi*3] = botip->faces[i*3]; botip->faces[last_fi*3+1] = last_vi; botip->faces[last_fi*3+2] = save_vi; ++last_fi; } if (last_fi >= botip->num_faces) break; } GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); rt_db_free_internal(&intern); return GED_OK; }
/** * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_epa_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_epa_internal *epa; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; point_t pt; vect_t h; vect_t au; vect_t n; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); epa = (struct rt_epa_internal *)ip->idb_ptr; RT_EPA_CK_MAGIC(epa); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; VMOVE(pt, epa->epa_V); MAT4X3PNT(epa->epa_V, mirmat, pt); VMOVE(h, epa->epa_H); VMOVE(au, epa->epa_Au); VUNITIZE(h); VUNITIZE(au); VCROSS(n, mirror_dir, epa->epa_H); VUNITIZE(n); ang = M_PI_2 - acos(VDOT(h, mirror_dir)); bn_mat_arb_rot(rmat, origin, n, ang*2); VMOVE(h, epa->epa_H); MAT4X3VEC(epa->epa_H, rmat, h); VCROSS(n, mirror_dir, epa->epa_Au); VUNITIZE(n); ang = M_PI_2 - acos(VDOT(au, mirror_dir)); bn_mat_arb_rot(rmat, origin, n, ang*2); VMOVE(au, epa->epa_Au); MAT4X3VEC(epa->epa_Au, rmat, au); 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 */ }
/* * Given an XYZ hit point, compute the concentric ring structure. We do * this by computing the dot-product of the hit point vs. the ring vertex, * which is then used to compute the distance from the ring center. This * distance is then multiplied by a velocity coefficient that is signed. */ HIDDEN int wood_render(struct application *UNUSED(ap), const struct partition *UNUSED(partp), struct shadework *swp, void *dp) { register struct wood_specific *wd = (struct wood_specific *)dp; vect_t g, h; point_t dprod, lprod; double c, A, B, C; double x, y, z, xd, yd, zd; double mixture, pp, pq, wt; /* * Compute the normalized hit point */ xd = wd->b_max[0] - wd->b_min[0] + 1.0; yd = wd->b_max[1] - wd->b_min[1] + 1.0; zd = wd->b_max[2] - wd->b_min[2] + 1.0; x = wd->dither[X] + ((swp->sw_hit.hit_point[0] - wd->b_min[0]) / xd); y = wd->dither[Y] + ((swp->sw_hit.hit_point[1] - wd->b_min[1]) / yd); z = wd->dither[Z] + ((swp->sw_hit.hit_point[2] - wd->b_min[2]) / zd); /* * Compute the distance from the ring center to the hit * point by formulating a triangle between the hit point, * the ring vertex, and ring's local X-axis. */ VSUB2(h, swp->sw_hit.hit_point, wd->vertex); VMOVE(g, h); VUNITIZE(g); /* xlate to ray */ wt = wood_turb(x, y, z, wd) * wd->depth; /* used in two places */ c = fabs(VDOT(g, wd->dir)); A = MAGNITUDE(h) + wt; B = c * A; /* abscissa */ C = sqrt(pow(A, 2.0) - pow(B, 2.0)); /* ordinate */ /* * Divide the ordinate by the spacing coefficient, and * compute the sine from that product. */ c = fabs(sin((C / wd->spacing) * M_PI)); /* * Dither the "q" control */ pq = cos(((wd->qd * wt) + wd->qp + wd->phase) * DEG2RAD); pp = cos(wd->phase * DEG2RAD); /* * Color the hit point based on the phase of the ring */ if (c < pq) { VMOVE(swp->sw_color, wd->lt_rgb); } else if (c >= pp) { VMOVE(swp->sw_color, wd->dk_rgb); } else { mixture = (c - pq) / (pp - pq); VSCALE(lprod, wd->lt_rgb, (1.0 - mixture)); VSCALE(dprod, wd->dk_rgb, mixture); VADD2(swp->sw_color, lprod, dprod); } /* * All done. Return to the caller */ return 1; }
int negative_polygon(struct subbrep_object_data *data) { int io_state = 0; int all_faces_cnt = 0; std::vector<int> all_faces; int *final_faces = NULL; std::set<int> fol_faces; /* This will get reused for all faces, so make it once */ point_t *all_verts = (point_t *)bu_calloc(data->brep->m_V.Count(), sizeof(point_t), "bot verts"); for (int vi = 0; vi < data->brep->m_V.Count(); vi++) { VMOVE(all_verts[vi], data->brep->m_V[vi].Point()); } array_to_set(&fol_faces, data->fol, data->fol_cnt); // Check each face to see if it is fil or fol - the first fol face, stash its // normal - don't even need the triangle face normal, we can just use the face's normal and // a point from the center of one of the fol triangles on that particular face. ON_3dPoint origin_pnt; ON_3dVector triangle_normal; int have_hit_pnt = 0; /* Get triangles from the faces */ ON_BoundingBox vert_bbox; ON_MinMaxInit(&vert_bbox.m_min, &vert_bbox.m_max); for (int i = 0; i < data->loops_cnt; i++) { const ON_BrepLoop *b_loop = &(data->brep->m_L[data->loops[i]]); int *ffaces = NULL; int num_faces = subbrep_polygon_tri(data->brep, all_verts, (int *)&(b_loop->m_loop_index), 1, &ffaces); if (!num_faces) { bu_log("Error - triangulation failed for loop %d!\n", b_loop->m_loop_index); return 0; } if (!have_hit_pnt) { const ON_BrepFace *b_face = b_loop->Face(); if (fol_faces.find(b_face->m_face_index) != fol_faces.end()) { ON_3dPoint p1 = data->brep->m_V[ffaces[0]].Point(); ON_3dPoint p2 = data->brep->m_V[ffaces[1]].Point(); ON_3dPoint p3 = data->brep->m_V[ffaces[2]].Point(); ON_Plane fp; ON_Surface *ts = b_face->SurfaceOf()->Duplicate(); (void)ts->IsPlanar(&fp, BREP_PLANAR_TOL); delete ts; triangle_normal = fp.Normal(); if (b_face->m_bRev) triangle_normal = triangle_normal * -1; origin_pnt = (p1 + p2 + p3) / 3; have_hit_pnt = 1; } } for (int f_ind = 0; f_ind < num_faces*3; f_ind++) { all_faces.push_back(ffaces[f_ind]); vert_bbox.Set(data->brep->m_V[ffaces[f_ind]].Point(), true); } if (ffaces) bu_free(ffaces, "free polygon face array"); all_faces_cnt += num_faces; } /* Now we can build the final faces array */ final_faces = (int *)bu_calloc(all_faces_cnt * 3, sizeof(int), "final bot verts"); for (int i = 0; i < all_faces_cnt*3; i++) { final_faces[i] = all_faces[i]; } // Scale bounding box to make sure corners are away from the volume vert_bbox.m_min = vert_bbox.m_min * 1.1; vert_bbox.m_max = vert_bbox.m_max * 1.1; // Pick a ray direction ON_3dVector rdir; ON_3dPoint box_corners[8]; vert_bbox.GetCorners(box_corners); int have_dir = 0; int corner = 0; double dotp; while (!have_dir && corner < 8) { rdir = box_corners[corner] - origin_pnt; dotp = ON_DotProduct(triangle_normal, rdir); (NEAR_ZERO(dotp, 0.01)) ? corner++ : have_dir = 1; } if (!have_dir) { bu_log("Error: NONE of the corners worked??\n"); return 0; } point_t origin, dir; VMOVE(origin, origin_pnt); VMOVE(dir, rdir); #if 0 std::cout << "working: " << bu_vls_addr(data->key) << "\n"; bu_log("in origin.s sph %f %f %f 1\n", origin[0], origin[1], origin[2]); bu_log("in triangle_normal.s rcc %f %f %f %f %f %f 1 \n", origin_pnt.x, origin_pnt.y, origin_pnt.z, triangle_normal.x, triangle_normal.y, triangle_normal.z); bu_log("in ray.s rcc %f %f %f %f %f %f 1 \n", origin[0], origin[1], origin[2], dir[0], dir[1], dir[2]); #endif // Test the ray against the triangle set int hit_cnt = 0; point_t p1, p2, p3, isect; ON_3dPointArray hit_pnts; for (int i = 0; i < all_faces_cnt; i++) { ON_3dPoint onp1, onp2, onp3, hit_pnt; VMOVE(p1, all_verts[all_faces[i*3+0]]); VMOVE(p2, all_verts[all_faces[i*3+1]]); VMOVE(p3, all_verts[all_faces[i*3+2]]); onp1.x = p1[0]; onp1.y = p1[1]; onp1.z = p1[2]; onp2.x = p2[0]; onp2.y = p2[1]; onp2.z = p2[2]; onp3.x = p3[0]; onp3.y = p3[1]; onp3.z = p3[2]; ON_Plane fplane(onp1, onp2, onp3); int is_hit = bg_isect_tri_ray(origin, dir, p1, p2, p3, &isect); VMOVE(hit_pnt, isect); // Don't count the point on the ray origin if (hit_pnt.DistanceTo(origin_pnt) < 0.0001) is_hit = 0; if (is_hit) { // No double-counting for (int j = 0; j < hit_pnts.Count(); j++) { if (hit_pnts[j].DistanceTo(hit_pnt) < 0.001) is_hit = 0; } if (is_hit) { //bu_log("in hit_cnt%d.s sph %f %f %f 0.1\n", hit_pnts.Count()+1, isect[0], isect[1], isect[2]); hit_pnts.Append(hit_pnt); } } } hit_cnt = hit_pnts.Count(); //bu_log("hit count: %d\n", hit_cnt); //bu_log("dotp : %f\n", dotp); // Final inside/outside determination if (hit_cnt % 2) { io_state = (dotp > 0) ? -1 : 1; } else { io_state = (dotp < 0) ? -1 : 1; } //bu_log("inside out state: %d\n", io_state); bu_free(all_verts, "free top level vertex array"); bu_free(final_faces, "free face array"); return io_state; }
HIDDEN int _rt_generate_points(int **faces, int *num_faces, point_t **points, int *num_pnts, struct bu_ptbl *hit_pnts, struct db_i *dbip, const char *obj, fastf_t delta) { int i, dir1, j; point_t min, max; int ncpus = bu_avail_cpus(); struct rt_parallel_container *state; struct bu_vls vlsstr; bu_vls_init(&vlsstr); if (!hit_pnts || !dbip || !obj) return -1; BU_GET(state, struct rt_parallel_container); state->rtip = rt_new_rti(dbip); state->delta = delta; if (rt_gettree(state->rtip, obj) < 0) return -1; rt_prep_parallel(state->rtip, 1); state->resp = (struct resource *)bu_calloc(ncpus+1, sizeof(struct resource), "resources"); for (i = 0; i < ncpus+1; i++) { rt_init_resource(&(state->resp[i]), i, state->rtip); } state->npts = (struct rt_point_container *)bu_calloc(ncpus+1, sizeof(struct rt_point_container), "point container arrays"); int n[3]; VMOVE(min, state->rtip->mdl_min); VMOVE(max, state->rtip->mdl_max); for (i = 0; i < 3; i++) { n[i] = (int)((max[i] - min[i])/state->delta) + 2; if(n[i] < 12) n[i] = 12; } int total = 0; for (i = 0; i < 3; i++) total += n[i]*n[(i+1)%3]; if (total > 1e6) total = 1e6; for (i = 0; i < ncpus+1; i++) { state->npts[i].pts = (struct npoints *)bu_calloc(total, sizeof(struct npoints), "npoints arrays"); state->npts[i].pnt_cnt = 0; state->npts[i].capacity = total; } for (dir1 = 0; dir1 < 3; dir1++) { state->ray_dir = dir1; state->ncpus = ncpus; state->delta = delta; bu_parallel(_rt_gen_worker, ncpus, (void *)state); } int out_cnt = 0; for (i = 0; i < ncpus+1; i++) { bu_log("%d, pnt_cnt: %d\n", i, state->npts[i].pnt_cnt); for (j = 0; j < state->npts[i].pnt_cnt; j++) { struct npoints *npt = &(state->npts[i].pts[j]); if (npt->in.is_set) out_cnt++; if (npt->out.is_set) out_cnt++; } } struct rt_vert **rt_verts = (struct rt_vert **)bu_calloc(out_cnt, sizeof(struct rt_vert *), "output array"); int curr_ind = 0; for (i = 0; i < ncpus+1; i++) { for (j = 0; j < state->npts[i].pnt_cnt; j++) { struct npoints *npt = &(state->npts[i].pts[j]); if (npt->in.is_set) { rt_verts[curr_ind] = &(npt->in); curr_ind++; } if (npt->out.is_set) { rt_verts[curr_ind] = &(npt->out); curr_ind++; } } } struct spr_options opts = SPR_OPTIONS_DEFAULT_INIT; (void)spr_surface_build(faces, num_faces, (double **)points, num_pnts, (const struct cvertex **)rt_verts, out_cnt, &opts); return 0; }
int main (int argc, char **argv) { char buf[BUF_LEN]; /* Contents of current input line */ char *bp; /* Pointer into buf */ char *nlp; /* Location of newline in buf */ char rname[BUF_LEN]; /* Name of current region */ char rayname[BUF_LEN]; /* Name of ray */ fastf_t ray_radius = 1.0; /* Thickness of the RCC */ point_t entryp; /* Ray's entry into current region */ point_t exitp; /* Ray's exit from current region */ point_t first_entryp; /* Ray's entry into the entire geometry */ int i; /* Index into rname */ int line_nm = 0; /* Number of current line of input */ int opt; /* Command-line option returned by bu_getopt */ int pid; /* Process ID for unique group name */ extern char *bu_optarg; extern int bu_optind, bu_opterr; int bu_getopt(int, char *const *, const char *); pid = bu_process_id(); *rayname = '\0'; /* Handle command-line options */ while ((opt = bu_getopt(argc, argv, OPT_STRING)) != -1) switch (opt) { case 'n': bu_strlcpy(rayname, bu_optarg, BUF_LEN); break; case 'r': if (sscanf(bu_optarg, "%F", &ray_radius) != 1) { bu_exit(1, "Illegal radius: '%s'\n", bu_optarg); } break; case '?': print_usage(); } /* Ensure proper command-line syntax */ if (bu_optind != argc) { print_usage(); } /* Construct the names of the objects to add to the database */ if (*rayname == '\0') /* Was one given on command line? */ sprintf(rayname, "ray.%d", pid); if (strlen(rayname) > NAMESIZE) { fprintf(stderr, "Name '%s.s' for ray solid may not exceed %d characters\n", rayname, NAMESIZE); bu_exit(1, "Use the '-n name' option to specify a different name\n"); } printf("in %s.s sph 0 0 0 1\n", rayname); printf("r %s.r u %s.s\n", rayname, rayname); printf("mater %s.r\n\n\n%s\n\n", rayname, RAY_COLOR); printf("g %s", rayname); /* Read the input */ while (bu_fgets(buf, BUF_LEN, stdin) != NULL) { ++line_nm; bp = buf; if ((nlp = index(bp, '\n')) != 0) *nlp = '\0'; /* Skip initial white space */ while (isspace(*bp)) ++bp; /* Get region name */ for (i = 0; ! isspace(*bp) && (*bp != '\0'); ++i, ++bp) rname[i] = *bp; rname[i] = '\0'; /* Read entry and exit coordinates for this partition */ if (sscanf(bp, "%F%F%F%F%F%F", &entryp[X], &entryp[Y], &entryp[Z], &exitp[X], &exitp[Y], &exitp[Z]) != 6) { bu_exit(1, "Illegal data on line %d: '%s'\n", line_nm, bp); } printf(" %s", rname); if (line_nm == 1) { VMOVE(first_entryp, entryp); } } if (! feof(stdin)) { bu_exit(1, "Error from bu_fgets(). This shouldn't happen"); } printf("\nkill %s.s\nin %s.s rcc\n\t%f %f %f\n\t%f %f %f\n\t%f\n", rayname, rayname, first_entryp[X], first_entryp[Y], first_entryp[Z], exitp[X] - first_entryp[X], exitp[Y] - first_entryp[Y], exitp[Z] - first_entryp[Z], ray_radius); printf("g %s %s.r\n", rayname, rayname); fprintf(stderr, "Group is '%s'\n", rayname); }
int main(int argc, char **argv) { int c; int i; struct pshell *psh; struct pbar *pb; struct wmember head; struct wmember all_head; char *nastran_file = "Converted from NASTRAN file (stdin)"; fpin = stdin; units = INCHES; /* XXX These need to be improved */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.005; tol.dist_sq = tol.dist * tol.dist; tol.perp = 1e-6; tol.para = 1 - tol.perp; while ( (c=bu_getopt( argc, argv, "x:X:t:ni:o:m")) != EOF ) { switch ( c ) { case 'x': sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.debug ); bu_printb( "librt RT_G_DEBUG", RT_G_DEBUG, DEBUG_FORMAT ); bu_log("\n"); break; case 'X': sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.NMG_debug ); bu_printb( "librt rt_g.NMG_debug", rt_g.NMG_debug, NMG_DEBUG_FORMAT ); bu_log("\n"); break; case 't': /* calculational tolerance */ tol.dist = atof( bu_optarg ); tol.dist_sq = tol.dist * tol.dist; case 'n': polysolids = 0; break; case 'm': units = MM; break; case 'i': nastran_file = bu_optarg; fpin = fopen( bu_optarg, "rb" ); if ( fpin == (FILE *)NULL ) { bu_log( "Cannot open NASTRAN file (%s) for reading!\n", bu_optarg ); bu_exit(1, Usage, argv[0] ); } break; case 'o': output_file = bu_optarg; break; } } fpout = wdb_fopen( output_file ); if ( fpout == NULL ) { bu_log( "Cannot open BRL-CAD file (%s) for writing!\n", output_file ); bu_exit(1, Usage, argv[0] ); } if ( !fpin || !fpout ) { bu_exit(1, Usage, argv[0] ); } line = (char *)bu_malloc( MAX_LINE_SIZE, "line" ); next_line = (char *)bu_malloc( MAX_LINE_SIZE, "next_line" ); prev_line = (char *)bu_malloc( MAX_LINE_SIZE, "prev_line" ); curr_rec = (char **)bu_calloc( NO_OF_FIELDS, sizeof( char *), "curr_rec" ); for ( i=0; i<NO_OF_FIELDS; i++ ) curr_rec[i] = (char *)bu_malloc( sizeof( char )*FIELD_LENGTH, "curr_rec[i]" ); prev_rec = (char **)bu_calloc( NO_OF_FIELDS, sizeof( char *), "prev_rec" ); for ( i=0; i<NO_OF_FIELDS; i++ ) prev_rec[i] = (char *)bu_malloc( sizeof( char )*FIELD_LENGTH, "prev_rec[i]" ); /* first pass, find start of NASTRAN "bulk data" */ start_off = (-1); bulk_data_start_line = 0; while ( bu_fgets( line, MAX_LINE_SIZE, fpin ) ) { bulk_data_start_line++; if ( strncmp( line, "BEGIN BULK", 10 ) ) continue; start_off = ftell( fpin ); break; } if ( start_off < 0 ) { bu_log( "Cannot find start of bulk data in NASTRAN file!\n" ); bu_exit(1, Usage, argv[0] ); } /* convert BULK data deck into something reasonable */ fptmp = bu_temp_file(NULL, 0); if ( fptmp == NULL ) { perror( argv[0] ); bu_exit(1, "Cannot open temporary file\n" ); } convert_input(); /* initialize some lists */ BU_LIST_INIT( &coord_head.l ); BU_LIST_INIT( &pbar_head.l ); BU_LIST_INIT( &pshell_head.l ); BU_LIST_INIT( &all_head.l ); nmg_model = (struct model *)NULL; /* count grid points */ fseek( fptmp, 0, SEEK_SET ); while ( bu_fgets( line, MAX_LINE_SIZE, fptmp ) ) { if ( !strncmp( line, "GRID", 4 ) ) grid_count++; } if ( !grid_count ) { bu_exit(1, "No geometry in this NASTRAN file!\n" ); } /* get default values and properties */ fseek( fptmp, 0, SEEK_SET ); while ( get_next_record( fptmp, 1, 0 ) ) { if ( !strncmp( curr_rec[0], "BAROR", 5 ) ) { /* get BAR defaults */ bar_def_pid = atoi( curr_rec[2] ); } else if ( !strncmp( curr_rec[0], "PBAR", 4 ) ) { struct pbar *pb; BU_GETSTRUCT( pb, pbar ); pb->pid = atoi( curr_rec[1] ); pb->mid = atoi( curr_rec[2] ); pb->area = atof( curr_rec[3] ); BU_LIST_INIT( &pb->head.l ); BU_LIST_INSERT( &pbar_head.l, &pb->l ); } else if ( !strncmp( curr_rec[0], "PSHELL", 6 ) ) { BU_GETSTRUCT( psh, pshell ); psh->s = (struct shell *)NULL; psh->pid = atoi( curr_rec[1] ); psh->mid = atoi( curr_rec[2] ); psh->thick = atof( curr_rec[3] ); BU_LIST_INSERT( &pshell_head.l, &psh->l ); pshell_count++; } } /* allocate storage for grid points */ g_pts = (struct grid_point *)bu_calloc( grid_count, sizeof( struct grid_point ), "grid points" ); /* get all grid points */ fseek( fptmp, 0, SEEK_SET ); while ( get_next_record( fptmp, 1, 0 ) ) { int gid; int cid; double tmp[3]; if ( strncmp( curr_rec[0], "GRID", 4 ) ) continue; gid = atoi( curr_rec[1] ); cid = atoi( curr_rec[2] ); for ( i=0; i<3; i++ ) { tmp[i] = atof( curr_rec[i+3] ); } g_pts[grid_used].gid = gid; g_pts[grid_used].cid = cid; g_pts[grid_used].v = (struct vertex **)bu_calloc( pshell_count + 1, sizeof( struct vertex *), "g_pts vertex array" );; VMOVE( g_pts[grid_used].pt, tmp ); grid_used++; } /* find coordinate systems */ fseek( fptmp, 0, SEEK_SET ); while ( get_next_record( fptmp, 1, 0 ) ) { if ( strncmp( curr_rec[0], "CORD", 4 ) ) continue; get_coord_sys(); } #if 0 bu_log( "Original grid:\n" ); for ( i=0; i<grid_used; i++ ) { bu_log( "Grid point: gid=%d, cid=%d, (%g %g %g)\n", g_pts[i].gid, g_pts[i].cid, V3ARGS( g_pts[i].pt ) ); } bu_log( "\nOriginal coordinate systems:\n" ); for ( BU_LIST_FOR( cs, coord_sys, &coord_head.l ) ) { bu_log( "cid=%d, type=%c, rid=%d\n", cs->cid, cs->type, cs->rid ); bu_log( "\torigin=(%g %g %g)\n", V3ARGS( cs->origin ) ); bu_log( "\tv1=(%g %g %g)\n", V3ARGS( cs->v1 ) ); bu_log( "\tv2=(%g %g %g)\n", V3ARGS( cs->v2 ) ); bu_log( "\tv3=(%g %g %g)\n", V3ARGS( cs->v3 ) ); } #endif /* convert everything to BRL-CAD coordinate system */ i = 0; while ( convert_all_cs() || convert_all_pts() ) { i++; if ( i > 10 ) { bu_exit(1, "Cannot convert to default coordinate system, check for circular definition\n" ); } } #if 0 bu_log( "Converted grid:\n" ); for ( i=0; i<grid_used; i++ ) { bu_log( "Grid point: gid=%d, cid=%d, (%g %g %g)\n", g_pts[i].gid, g_pts[i].cid, V3ARGS( g_pts[i].pt ) ); } bu_log( "\nConverted coordinate systems:\n" ); for ( BU_LIST_FOR( cs, coord_sys, &coord_head.l ) ) { bu_log( "cid=%d, type=%c, rid=%d\n", cs->cid, cs->type, cs->rid ); bu_log( "\torigin=(%g %g %g)\n", V3ARGS( cs->origin ) ); bu_log( "\tv1=(%g %g %g)\n", V3ARGS( cs->v1 ) ); bu_log( "\tv2=(%g %g %g)\n", V3ARGS( cs->v2 ) ); bu_log( "\tv3=(%g %g %g)\n", V3ARGS( cs->v3 ) ); } #endif mk_id( fpout, nastran_file ); /* get elements */ fseek( fptmp, 0, SEEK_SET ); while ( get_next_record( fptmp, 1, 0 ) ) { if ( !strncmp( curr_rec[0], "CBAR", 4 ) ) get_cbar(); else if ( !strncmp( curr_rec[0], "CROD", 4 ) ) get_cbar(); else if ( !strncmp( curr_rec[0], "CTRIA3", 6 ) ) get_ctria3(); else if ( !strncmp( curr_rec[0], "CQUAD4", 6 ) ) get_cquad4(); } if ( nmg_model ) { nmg_rebound( nmg_model, &tol ); if ( polysolids ) mk_bot_from_nmg( fpout, "pshell.0", nmg_shell ); else mk_nmg( fpout, "pshell.0", nmg_model ); } BU_LIST_INIT( &head.l ); for ( BU_LIST_FOR( psh, pshell, &pshell_head.l ) ) { struct model *m; char name[NAMESIZE+1]; if ( !psh->s ) continue; m = nmg_find_model( &psh->s->l.magic ); nmg_rebound( m, &tol ); nmg_fix_normals( psh->s, &tol ); if ( psh->thick > tol.dist ) { nmg_model_face_fuse( m, &tol ); nmg_hollow_shell( psh->s, psh->thick*conv[units], 1, &tol ); } sprintf( name, "pshell.%d", psh->pid ); if ( polysolids ) mk_bot_from_nmg( fpout, name, psh->s ); else mk_nmg( fpout, name, m ); mk_addmember( name, &head.l, NULL, WMOP_UNION ); } if ( BU_LIST_NON_EMPTY( &head.l ) ) { mk_lfcomb( fpout, "shells", &head, 0 ); mk_addmember( "shells", &all_head.l, NULL, WMOP_UNION ); } BU_LIST_INIT( &head.l ); for ( BU_LIST_FOR( pb, pbar, &pbar_head.l ) ) { char name[NAMESIZE+1]; if ( BU_LIST_IS_EMPTY( &pb->head.l ) ) continue; sprintf( name, "pbar_group.%d", pb->pid ); mk_lfcomb( fpout, name, &pb->head, 0 ); mk_addmember( name, &head.l, NULL, WMOP_UNION ); } if ( BU_LIST_NON_EMPTY( &head.l ) ) { mk_lfcomb( fpout, "pbars", &head, 0 ); mk_addmember( "pbars", &all_head.l, NULL, WMOP_UNION ); } if ( BU_LIST_NON_EMPTY( &all_head.l ) ) { mk_lfcomb( fpout, "all", &all_head, 0 ); } wdb_close(fpout); return 0; }
int ged_mirror(struct ged *gedp, int argc, const char *argv[]) { /* trailing x|y|z intentionally not documented */ static const char *usage = "[-h] [-p \"point\"] [-d \"dir\"] [-x|-y|-z] [-o offset] old new"; int k; point_t mirror_pt = {0.0, 0.0, 0.0}; vect_t mirror_dir = {1.0, 0.0, 0.0}; /* intentionally double for scanning */ double scanpt[3]; double scandir[3]; double mirror_offset = 0.0; int ret; struct rt_db_internal *ip; struct rt_db_internal internal; struct directory *dp; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } bu_optind = 1; while ((k = bu_getopt(argc, (char * const *)argv, (const char *)"d:D:hHo:O:p:P:xXyYzZ")) != -1) { switch (k) { case 'p': case 'P': if (sscanf(bu_optarg, "%lf %lf %lf", &scanpt[X], &scanpt[Y], &scanpt[Z]) != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } /* convert from double to fastf_t */ VMOVE(mirror_pt, scanpt); break; case 'd': case 'D': if (sscanf(bu_optarg, "%lf %lf %lf", &scandir[X], &scandir[Y], &scandir[Z]) != 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } /* convert from double to fastf_t */ VMOVE(mirror_dir, scandir); break; case 'o': case 'O': if (sscanf(bu_optarg, "%lf", &mirror_offset) != 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } break; case 'x': case 'X': VSET(mirror_dir, 1.0, 0.0, 0.0); break; case 'y': case 'Y': VSET(mirror_dir, 0.0, 1.0, 0.0); break; case 'z': case 'Z': VSET(mirror_dir, 0.0, 0.0, 1.0); break; case 'h': case 'H': bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; default: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; break; } } argc -= bu_optind; if (argc < 2 || argc > 4) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } else if (argc == 3) { /* support a trailing x|y|z option as classic command * behavior. THIS IS INTENTIONALLY UNDOCUMENTED. if users * have to read the usage, they can learn the new form. */ switch (argv[bu_optind+2][0]) { case 'x': case 'X': VSET(mirror_dir, 1.0, 0.0, 0.0); break; case 'y': case 'Y': VSET(mirror_dir, 0.0, 1.0, 0.0); break; case 'z': case 'Z': VSET(mirror_dir, 0.0, 0.0, 1.0); break; default: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; break; } } /* make sure object mirroring to does not already exist */ if (db_lookup(gedp->ged_wdbp->dbip, argv[bu_optind+1], LOOKUP_QUIET) != RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "%s already exists\n", argv[bu_optind+1]); return GED_ERROR; } /* look up the object being mirrored */ if ((dp = db_lookup(gedp->ged_wdbp->dbip, argv[bu_optind], LOOKUP_NOISY)) == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "Unable to find solid [%s]\n", argv[bu_optind]); return GED_ERROR; } /* get object being mirrored */ ret = rt_db_get_internal(&internal, dp, gedp->ged_wdbp->dbip, NULL, gedp->ged_wdbp->wdb_resp); if (ret < 0) { bu_vls_printf(gedp->ged_result_str, "Unable to load solid [%s]\n", argv[bu_optind]); return GED_ERROR; } mirror_offset *= gedp->ged_wdbp->dbip->dbi_local2base; VUNITIZE(mirror_dir); VJOIN1(mirror_pt, mirror_pt, mirror_offset, mirror_dir); /* mirror the object */ ip = rt_mirror(gedp->ged_wdbp->dbip, &internal, mirror_pt, mirror_dir, gedp->ged_wdbp->wdb_resp); if (ip == NULL) { bu_vls_printf(gedp->ged_result_str, "Unable to mirror [%s]", argv[bu_optind]); return GED_ERROR; } /* add the mirrored object to the directory */ dp = db_diradd(gedp->ged_wdbp->dbip, argv[bu_optind+1], RT_DIR_PHONY_ADDR, 0, dp->d_flags, (void *)&ip->idb_type); if (dp == RT_DIR_NULL) { bu_vls_printf(gedp->ged_result_str, "Unable to add [%s] to the database directory", argv[bu_optind+1]); return GED_ERROR; } /* save the mirrored object to disk */ if (rt_db_put_internal(dp, gedp->ged_wdbp->dbip, ip, gedp->ged_wdbp->wdb_resp) < 0) { bu_vls_printf(gedp->ged_result_str, "Unable to store [%s] to the database", argv[bu_optind+1]); return GED_ERROR; } { /* draw the new object */ const char *object = (const char *)argv[bu_optind+1]; const char *e_argv[3] = {0, 0, 0}; e_argv[0] = "draw"; e_argv[1] = object; e_argv[2] = NULL; (void)ged_draw(gedp, 2, e_argv); ged_view_update(gedp->ged_gvp); } return GED_OK; }
HIDDEN void get_coord_sys(void) { int form; char type; char *ptr; struct coord_sys *cs; int i, gid; double tmp[3]; point_t tmp_pt; form = atoi( &curr_rec[0][4] ); if ( form != 1 && form != 2 ) { bu_log( "unrecognized form for coordinate system definition (%d):\n", form ); bu_log( "%s\n", line ); return; } type = curr_rec[0][5]; if ( type != CORD_CYL && type != CORD_RECT && type != CORD_SPH ) { bu_log( "unrecognized coordinate system type (%c):\n", type ); bu_log( "%s\n", line ); return; } ptr = strtok( line, delims ); ptr = strtok( (char *)NULL, delims ); if ( !ptr ) { log_line( "Incomplete coordinate system definition" ); return; } BU_GETSTRUCT( cs, coord_sys ); switch ( form ) { case 1: cs->type = type; cs->cid = atoi( curr_rec[1] ); gid = atoi( curr_rec[2] ); get_grid( gid, cs->origin ); gid = atoi( curr_rec[3] ); get_grid( gid, tmp_pt ); VSUB2( cs->v3, tmp_pt, cs->origin ); VUNITIZE( cs->v3 ); gid = atoi( curr_rec[4] ); get_grid( gid, tmp_pt ); VSUB2( cs->v1, tmp_pt, cs->origin ); VCROSS( cs->v2, cs->v3, cs->v1 ); VUNITIZE( cs->v2 ); VCROSS( cs->v1, cs->v2, cs->v3 ); BU_LIST_INSERT( &coord_head.l, &cs->l ); if ( !strlen( curr_rec[5] ) ) break; BU_GETSTRUCT( cs, coord_sys ); cs->type = type; cs->cid = atoi( curr_rec[5] ); gid = atoi( curr_rec[6] ); get_grid( gid, cs->origin ); gid = atoi( curr_rec[7] ); get_grid( gid, tmp_pt ); VSUB2( cs->v3, tmp_pt, cs->origin ); VUNITIZE( cs->v3 ); gid = atoi( curr_rec[8] ); get_grid( gid, tmp_pt ); VSUB2( cs->v1, tmp_pt, cs->origin ); VCROSS( cs->v2, cs->v3, cs->v1 ); VUNITIZE( cs->v2 ); VCROSS( cs->v1, cs->v2, cs->v3 ); BU_LIST_INSERT( &coord_head.l, &cs->l ); break; case 2: cs->type = type; cs->cid = atoi( curr_rec[1] ); cs->rid = atoi( curr_rec[2] ); for ( i=0; i<3; i++ ) tmp[i] = atof( curr_rec[3+i] ); VMOVE( cs->origin, tmp ); for ( i=0; i<3; i++ ) tmp[i] = atof( curr_rec[6+i] ); VMOVE( cs->v1, tmp ); for ( i=0; i<3; i++ ) tmp[i] = atof( curr_rec[9+i] ); VMOVE( cs->v2, tmp ); if ( !cs->rid ) { point_t tmp_pt1, tmp_pt2; /* this coordinate system is defined in terms of the default */ VMOVE( tmp_pt1, cs->v1 ); VMOVE( tmp_pt2, cs->v2 ); VSUB2( cs->v3, tmp_pt1, cs->origin ); VUNITIZE( cs->v3 ); VSUB2( cs->v1, tmp_pt2, cs->origin ); VCROSS( cs->v2, cs->v3, cs->v1 ); VUNITIZE( cs->v2 ); VCROSS( cs->v1, cs->v3, cs->v2 ); } BU_LIST_INSERT( &coord_head.l, &cs->l ); break; } }
void bn_mat_fromto( mat_t m, const fastf_t *from, const fastf_t *to, const struct bn_tol *tol) { vect_t test_to; vect_t unit_from, unit_to; fastf_t dot; point_t origin = VINIT_ZERO; /** * The method used here is from Graphics Gems, A. Glassner, ed. * page 531, "The Use of Coordinate Frames in Computer Graphics", * by Ken Turkowski, Example 6. */ mat_t Q, Qt; mat_t R; mat_t A; mat_t temp; vect_t N, M; vect_t w_prime; /* image of "to" ("w") in Qt */ VMOVE(unit_from, from); VUNITIZE(unit_from); /* aka "v" */ VMOVE(unit_to, to); VUNITIZE(unit_to); /* aka "w" */ /* If from and to are the same or opposite, special handling is * needed, because the cross product isn't defined. asin(0.00001) * = 0.0005729 degrees (1/2000 degree) */ if (bn_lseg3_lseg3_parallel(origin, from, origin, to, tol)) { dot = VDOT(from, to); if (dot > SMALL_FASTF) { MAT_IDN(m); return; } else { bn_vec_perp(N, unit_from); } } else { VCROSS(N, unit_from, unit_to); VUNITIZE(N); /* should be unnecessary */ } VCROSS(M, N, unit_from); VUNITIZE(M); /* should be unnecessary */ /* Almost everything here is done with pre-multiplys: vector * mat */ MAT_IDN(Q); VMOVE(&Q[0], unit_from); VMOVE(&Q[4], M); VMOVE(&Q[8], N); bn_mat_trn(Qt, Q); /* w_prime = w * Qt */ MAT4X3VEC(w_prime, Q, unit_to); /* post-multiply by transpose */ MAT_IDN(R); VMOVE(&R[0], w_prime); VSET(&R[4], -w_prime[Y], w_prime[X], w_prime[Z]); VSET(&R[8], 0, 0, 1); /* is unnecessary */ bn_mat_mul(temp, R, Q); bn_mat_mul(A, Qt, temp); bn_mat_trn(m, A); /* back to post-multiply style */ /* Verify that it worked */ MAT4X3VEC(test_to, m, unit_from); if (UNLIKELY(!bn_lseg3_lseg3_parallel(origin, unit_to, origin, test_to, tol))) { dot = VDOT(unit_to, test_to); bu_log("bn_mat_fromto() ERROR! from (%g, %g, %g) to (%g, %g, %g) went to (%g, %g, %g), dot=%g?\n", V3ARGS(from), V3ARGS(to), V3ARGS(test_to), dot); } }
/* * P L O T _ O B J E C T * * Set up for an object, transformed as indicated, and with an * object center as specified. The ratio of object to screen size * is passed in as a convienience. * * Returns 0 if object could be drawn, !0 if object was omitted. */ static int plot_drawVList(struct dm *dmp, register struct bn_vlist *vp) { static vect_t last; register struct bn_vlist *tvp; register point_t *pt_prev=NULL; register fastf_t dist_prev=1.0; register fastf_t dist; fastf_t delta; int useful = 0; if (((struct plot_vars *)dmp->dm_vars.priv_vars)->floating) { rt_vlist_to_uplot(((struct plot_vars *)dmp->dm_vars.priv_vars)->up_fp, &vp->l); return TCL_OK; } /* delta is used in clipping to insure clipped endpoint is slightly * in front of eye plane (perspective mode only). * This value is a SWAG that seems to work OK. */ delta = plotmat[15]*0.0001; if (delta < 0.0) delta = -delta; if (delta < SQRT_SMALL_FASTF) delta = SQRT_SMALL_FASTF; for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) { register int i; register int nused = tvp->nused; register int *cmd = tvp->cmd; register point_t *pt = tvp->pt; for (i = 0; i < nused; i++, cmd++, pt++) { static vect_t start, fin; switch (*cmd) { case BN_VLIST_POLY_START: case BN_VLIST_POLY_VERTNORM: continue; case BN_VLIST_POLY_MOVE: case BN_VLIST_LINE_MOVE: /* Move, not draw */ if (dmp->dm_perspective > 0) { /* cannot apply perspective transformation to * points behind eye plane!!!! */ dist = VDOT( *pt, &plotmat[12] ) + plotmat[15]; if (dist <= 0.0) { pt_prev = pt; dist_prev = dist; continue; } else { MAT4X3PNT(last, plotmat, *pt); dist_prev = dist; pt_prev = pt; } } else MAT4X3PNT(last, plotmat, *pt); continue; case BN_VLIST_POLY_DRAW: case BN_VLIST_POLY_END: case BN_VLIST_LINE_DRAW: /* draw */ if (dmp->dm_perspective > 0) { /* cannot apply perspective transformation to * points behind eye plane!!!! */ dist = VDOT( *pt, &plotmat[12] ) + plotmat[15]; if (dist <= 0.0) { if (dist_prev <= 0.0) { /* nothing to plot */ dist_prev = dist; pt_prev = pt; continue; } else { fastf_t alpha; vect_t diff; point_t tmp_pt; /* clip this end */ VSUB2( diff, *pt, *pt_prev ); alpha = (dist_prev - delta) / (dist_prev - dist); VJOIN1(tmp_pt, *pt_prev, alpha, diff); MAT4X3PNT(fin, plotmat, tmp_pt); } } else { if (dist_prev <= 0.0) { fastf_t alpha; vect_t diff; point_t tmp_pt; /* clip other end */ VSUB2( diff, *pt, *pt_prev ); alpha = (-dist_prev + delta) / ( dist - dist_prev ); VJOIN1( tmp_pt, *pt_prev, alpha, diff ); MAT4X3PNT( last, plotmat, tmp_pt ); MAT4X3PNT( fin, plotmat, *pt ); } else { MAT4X3PNT( fin, plotmat, *pt ); } } } else MAT4X3PNT( fin, plotmat, *pt ); VMOVE( start, last ); VMOVE( last, fin ); break; } if (vclip(start, fin, dmp->dm_clipmin, dmp->dm_clipmax) == 0) continue; if (((struct plot_vars *)dmp->dm_vars.priv_vars)->is_3D) pl_3line(((struct plot_vars *)dmp->dm_vars.priv_vars)->up_fp, (int)(start[X] * 2047), (int)(start[Y] * 2047), (int)(start[Z] * 2047), (int)(fin[X] * 2047), (int)(fin[Y] * 2047), (int)(fin[Z] * 2047)); else pl_line(((struct plot_vars *)dmp->dm_vars.priv_vars)->up_fp, (int)(start[X] * 2047), (int)(start[Y] * 2047), (int)(fin[X] * 2047), (int)(fin[Y] * 2047)); useful = 1; } } if (useful) return TCL_OK; return TCL_ERROR; }
/** * Brute force through all possible plane intersections. * Generate all edge lines, then intersect the line with all * the other faces to find the vertices on that line. * If the geometry is correct, there will be no more than two. * While not the fastest strategy, this will produce an accurate * plot without requiring extra bookkeeping. * Note that the vectors will be drawn in no special order. */ int rt_arbn_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol, const struct rt_view_info *UNUSED(info)) { struct rt_arbn_internal *aip; size_t i; size_t j; size_t k; BU_CK_LIST_HEAD(vhead); RT_CK_DB_INTERNAL(ip); aip = (struct rt_arbn_internal *)ip->idb_ptr; RT_ARBN_CK_MAGIC(aip); for (i = 0; i < aip->neqn - 1; i++) { for (j = i + 1; j < aip->neqn; j++) { double dot; int point_count; /* # points on this line */ point_t a, b; /* start and end points */ vect_t dist; VSETALL(a, 0); VSETALL(b, 0); /* If normals are parallel, no intersection */ dot = VDOT(aip->eqn[i], aip->eqn[j]); if (BN_VECT_ARE_PARALLEL(dot, tol)) continue; /* Have an edge line, isect with all other planes */ point_count = 0; for (k = 0; k < aip->neqn; k++) { size_t m; point_t pt; size_t next_k; next_k = 0; if (k == i || k == j) continue; if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue; /* See if point is outside arb */ for (m = 0; m < aip->neqn; m++) { if (i == m || j == m || k == m) continue; if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) { next_k = 1; break; } } if (next_k != 0) continue; if (point_count <= 0) { RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE); VMOVE(a, pt); } else if (point_count == 1) { VSUB2(dist, pt, a); if (MAGSQ(dist) < tol->dist_sq) continue; RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW); VMOVE(b, pt); } else { VSUB2(dist, pt, a); if (MAGSQ(dist) < tol->dist_sq) continue; VSUB2(dist, pt, b); if (MAGSQ(dist) < tol->dist_sq) continue; bu_log("rt_arbn_plot() error, point_count=%d (>2) on edge %zu/%zu, non-convex\n", point_count+1, i, j); VPRINT(" a", a); VPRINT(" b", b); VPRINT("pt", pt); RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW); /* draw it */ } point_count++; } /* Point counts of 1 are (generally) not harmful, * occurring on pyramid peaks and the like. */ } } 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 */ }
/** * Convert from "network" doubles to machine specific. * Transform */ int rt_arbn_import5(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip) { struct rt_arbn_internal *aip; size_t i; unsigned long neqn; int double_count; size_t byte_count; /* must be double for import and export */ double *eqn; RT_CK_DB_INTERNAL(ip); BU_CK_EXTERNAL(ep); if (dbip) RT_CK_DBI(dbip); neqn = ntohl(*(uint32_t *)ep->ext_buf); double_count = neqn * ELEMENTS_PER_PLANE; byte_count = double_count * SIZEOF_NETWORK_DOUBLE; BU_ASSERT_LONG(ep->ext_nbytes, ==, 4+ byte_count); ip->idb_major_type = DB5_MAJORTYPE_BRLCAD; ip->idb_type = ID_ARBN; ip->idb_meth = &OBJ[ID_ARBN]; BU_ALLOC(ip->idb_ptr, struct rt_arbn_internal); aip = (struct rt_arbn_internal *)ip->idb_ptr; aip->magic = RT_ARBN_INTERNAL_MAGIC; aip->neqn = neqn; if (aip->neqn <= 0) return -1; eqn = (double *)bu_malloc(byte_count, "arbn plane eqn[] temp buf"); bu_cv_ntohd((unsigned char *)eqn, (unsigned char *)ep->ext_buf + ELEMENTS_PER_PLANE, double_count); aip->eqn = (plane_t *)bu_malloc(double_count * sizeof(fastf_t), "arbn plane eqn[]"); for (i = 0; i < aip->neqn; i++) { HMOVE(aip->eqn[i], &eqn[i*ELEMENTS_PER_PLANE]); } bu_free(eqn, "arbn plane eqn[] temp buf"); /* Transform by the matrix, if we have one that is not the identity */ if (mat && !bn_mat_is_identity(mat)) { for (i = 0; i < aip->neqn; i++) { point_t orig_pt; point_t pt; vect_t norm; fastf_t factor; /* unitize the plane equation first */ factor = 1.0 / MAGNITUDE(aip->eqn[i]); VSCALE(aip->eqn[i], aip->eqn[i], factor); aip->eqn[i][W] = aip->eqn[i][W] * factor; /* Pick a point on the original halfspace */ VSCALE(orig_pt, aip->eqn[i], aip->eqn[i][W]); /* Transform the point, and the normal */ MAT4X3VEC(norm, mat, aip->eqn[i]); MAT4X3PNT(pt, mat, orig_pt); /* Measure new distance from origin to new point */ VUNITIZE(norm); VMOVE(aip->eqn[i], norm); aip->eqn[i][W] = VDOT(pt, norm); } } return 0; }
void do_pixel(int cpu, int pat_num, int pixelnum) { int i; 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; register RGBpixel pixel = {0, 0, 0}; const int pindex = (pixelnum * sizeof(RGBpixel)); /* Obtain fresh copy of global application struct */ a = ap; /* 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; rt_g.debug = query_debug; } else { rt_g.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 ( 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, ap.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, ap.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]); */ /* we're done */ view_pixel( &a ); if ( a.a_x == width-1 ) { view_eol( &a ); /* End of scan line */ } return; }
/* * 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. */ int fire_render(struct application *ap, const struct partition *pp, struct shadework *swp, void *dp) /* defined in material.h */ /* ptr to the shader-specific struct */ { #define DEBUG_SPACE_PRINT(str, i_pt, o_pt) \ if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) { \ bu_log("fire_render() %s space \n", str); \ bu_log("fire_render() i_pt(%g %g %g)\n", V3ARGS(i_pt)); \ bu_log("fire_render() o_pt(%g %g %g)\n", V3ARGS(o_pt)); \ } #define SHADER_TO_NOISE(n_pt, sh_pt, fire_sp, zdelta) { \ point_t tmp_pt; \ tmp_pt[X] = sh_pt[X]; \ tmp_pt[Y] = sh_pt[Y]; \ if (! NEAR_ZERO(fire_sp->fire_stretch, SQRT_SMALL_FASTF)) \ tmp_pt[Z] = exp((sh_pt[Z]+0.125) * -fire_sp->fire_stretch); \ else \ tmp_pt[Z] = sh_pt[Z]; \ MAT4X3PNT(n_pt, fire_sp->fire_sh_to_noise, tmp_pt); \ n_pt[Z] += zdelta; \ } register struct fire_specific *fire_sp = (struct fire_specific *)dp; point_t m_i_pt, m_o_pt; /* model space in/out points */ point_t sh_i_pt, sh_o_pt; /* shader space in/out points */ point_t noise_i_pt, noise_o_pt; /* shader space in/out points */ point_t noise_pt; double color[3]; vect_t noise_r_dir; double noise_r_thick; int i; double samples_per_unit_noise; double noise_dist_per_sample; point_t shader_pt; vect_t shader_r_dir; double shader_r_thick; double shader_dist_per_sample; double noise_zdelta; int samples; double dist; double noise_val; double lumens; /* check the validity of the arguments we got */ RT_AP_CHECK(ap); RT_CHECK_PT(pp); CK_fire_SP(fire_sp); if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) { /* bu_struct_print("fire_render Parameters:", fire_print_tab, (char *)fire_sp); */ bu_log("fire_render()\n"); } /* If we are performing the shading in "region" space, we must * transform the hit point from "model" space to "region" space. * See the call to db_region_mat in fire_setup(). */ /* * Compute the ray/solid in and out points, */ VMOVE(m_i_pt, swp->sw_hit.hit_point); VJOIN1(m_o_pt, ap->a_ray.r_pt, pp->pt_outhit->hit_dist, ap->a_ray.r_dir); DEBUG_SPACE_PRINT("model", m_i_pt, m_o_pt); /* map points into shader space */ MAT4X3PNT(sh_i_pt, fire_sp->fire_m_to_sh, m_i_pt); MAT4X3PNT(sh_o_pt, fire_sp->fire_m_to_sh, m_o_pt); DEBUG_SPACE_PRINT("shader", sh_i_pt, sh_o_pt); noise_zdelta = fire_sp->fire_flicker * swp->sw_frametime; SHADER_TO_NOISE(noise_i_pt, sh_i_pt, fire_sp, noise_zdelta); SHADER_TO_NOISE(noise_o_pt, sh_o_pt, fire_sp, noise_zdelta); VSUB2(noise_r_dir, noise_o_pt, noise_i_pt); noise_r_thick = MAGNITUDE(noise_r_dir); if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) { bu_log("fire_render() noise_r_dir (%g %g %g)\n", V3ARGS(noise_r_dir)); bu_log("fire_render() noise_r_thick %g\n", noise_r_thick); } /* compute number of samples per unit length in noise space. * * 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, nyquist * tells us we need at least 4 samples/cycle at the highest octave * rate. */ samples_per_unit_noise = pow(fire_sp->noise_lacunarity, fire_sp->noise_octaves-1) * 4.0; noise_dist_per_sample = 1.0 / samples_per_unit_noise; samples = samples_per_unit_noise * noise_r_thick; if (samples < 1) samples = 1; if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) { bu_log("samples:%d\n", samples); bu_log("samples_per_unit_noise %g\n", samples_per_unit_noise); bu_log("noise_dist_per_sample %g\n", noise_dist_per_sample); } /* To do the exponential stretch and decay properly we need to * do the computations in shader space, and convert the points * to noise space. Performance pig. */ VSUB2(shader_r_dir, sh_o_pt, sh_i_pt); shader_r_thick = MAGNITUDE(shader_r_dir); VUNITIZE(shader_r_dir); shader_dist_per_sample = shader_r_thick / samples; lumens = 0.0; for (i = 0; i < samples; i++) { dist = (double)i * shader_dist_per_sample; VJOIN1(shader_pt, sh_i_pt, dist, shader_r_dir); SHADER_TO_NOISE(noise_pt, shader_pt, fire_sp, noise_zdelta); noise_val = bn_noise_turb(noise_pt, fire_sp->noise_h_val, fire_sp->noise_lacunarity, fire_sp->noise_octaves); if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) bu_log("bn_noise_turb(%g %g %g) = %g\n", V3ARGS(noise_pt), noise_val); /* XXX * When doing the exponential stretch, we scale the noise * value by the height in shader space */ if (NEAR_ZERO(fire_sp->fire_stretch, SQRT_SMALL_FASTF)) lumens += noise_val * 0.025; else { register double t; t = lumens; lumens += noise_val * 0.025 * (1.0 -shader_pt[Z]); if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) bu_log("lumens:%g = %g + %g * %g\n", lumens, t, noise_val, 0.025 * (1.0 - shader_pt[Z])); } if (lumens >= 1.0) { lumens = 1.0; if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) bu_log("early exit from lumens loop\n"); break; } } if (rdebug&RDEBUG_SHADE || fire_sp->fire_debug) bu_log("lumens = %g\n", lumens); if (lumens < 0.0) lumens = 0.0; else if (lumens > 1.0) lumens = 1.0; rt_dspline_n(color, fire_sp->fire_colorspline_mat, (double *)flame_colors, 18, 3, lumens); VMOVE(swp->sw_color, color); /* VSETALL(swp->sw_basecolor, 1.0);*/ swp->sw_transmit = 1.0 - (lumens * 4.0); if (swp->sw_reflect > 0 || swp->sw_transmit > 0) (void)rr_render(ap, pp, swp); return 1; }
int read_Trie(FILE *fp) { static char name_buf[MAX_TRIE_LEVEL+1]; Trie *triep; F_Hdr_Ptlist hdr_ptlist; int min, max; /* Read temperature range information. */ if ( fread( (char *) &min, (int) sizeof(int), 1, fp ) != 1 || fread( (char *) &max, (int) sizeof(int), 1, fp ) != 1 ) { bu_log( "Could not read min/max info.\n" ); rewind( fp ); } else { bu_log( "IR data base temperature range is %d to %d\n", min, max ); if ( ir_min == ABSOLUTE_ZERO ) { /* Temperature range not set. */ ir_min = min; ir_max = max; } else { /* Merge with existing range. */ V_MIN( ir_min, min ); V_MAX( ir_max, max ); bu_log( "Global temperature range is %d to %d\n", ir_min, ir_max ); (void) fflush( stdout ); } } if ( ! init_Temp_To_RGB() ) { return 0; } while ( bu_fgets( name_buf, MAX_TRIE_LEVEL, fp ) != NULL ) { name_buf[strlen(name_buf)-1] = '\0'; /* Clobber new-line.*/ triep = add_Trie( name_buf, ®_triep ); if ( fread( (char *) &hdr_ptlist, (int) sizeof(F_Hdr_Ptlist), 1, fp ) != 1 ) { bu_log( "\"%s\"(%d) Read failed!\n", __FILE__, __LINE__ ); return 0; } for (; hdr_ptlist.f_length > 0; hdr_ptlist.f_length-- ) { fastf_t point[3]; float c_point[3]; Octree *octreep; if ( fread( (char *) c_point, (int) sizeof(c_point), 1, fp ) != 1 ) { bu_log( "\"%s\"(%d) Read failed.\n", __FILE__, __LINE__ ); return 0; } VMOVE( point, c_point ); if ( (octreep = add_Region_Octree( &ir_octree, point, triep, hdr_ptlist.f_temp, 0 ) ) != OCTREE_NULL ) append_Octp( triep, octreep ); } } return 1; }
static void make_bot_object(const char *name, struct rt_wdb *wdbp) { int i; int max_pt=0, min_pt=999999; int num_vertices; struct bu_bitv *bv=NULL; int bot_mode; int count; struct rt_bot_internal bot_ip; bot_ip.magic = RT_BOT_INTERNAL_MAGIC; for (i = 0; i < face_count; i++) { V_MIN(min_pt, faces[i*3]); V_MAX(max_pt, faces[i*3]); V_MIN(min_pt, faces[i*3+1]); V_MAX(max_pt, faces[i*3+1]); V_MIN(min_pt, faces[i*3+2]); V_MAX(max_pt, faces[i*3+2]); } num_vertices = max_pt - min_pt + 1; bot_ip.num_vertices = num_vertices; bot_ip.vertices = (fastf_t *)bu_calloc(num_vertices*3, sizeof(fastf_t), "BOT vertices"); for (i = 0; i < num_vertices; i++) VMOVE(&bot_ip.vertices[i*3], grid_pts[min_pt+i]); for (i = 0; i < face_count * 3; i++) faces[i] -= min_pt; bot_ip.num_faces = face_count; bot_ip.faces = bu_calloc(face_count*3, sizeof(int), "BOT faces"); for (i = 0; i < face_count*3; i++) bot_ip.faces[i] = faces[i]; bot_ip.face_mode = (struct bu_bitv *)NULL; bot_ip.thickness = (fastf_t *)NULL; if (mode == PLATE_MODE) { bot_mode = RT_BOT_PLATE; bv = bu_bitv_new(face_count); for (i = 0; i < face_count; i++) { if (facemode[i] == POS_FRONT) BU_BITSET(bv, i); } bot_ip.face_mode = bv; bot_ip.thickness = (fastf_t *)bu_calloc(face_count, sizeof(fastf_t), "BOT thickness"); for (i = 0; i < face_count; i++) bot_ip.thickness[i] = thickness[i]; } else bot_mode = RT_BOT_SOLID; bot_ip.mode = bot_mode; bot_ip.orientation = RT_BOT_UNORIENTED; bot_ip.bot_flags = 0; count = rt_bot_vertex_fuse(&bot_ip, &wdbp->wdb_tol); count = rt_bot_face_fuse(&bot_ip); if (count) bu_log("WARNING: %d duplicate faces eliminated from group %d component %d\n", count, group_id, comp_id); rt_mk_bot(wdbp, name, bot_mode, RT_BOT_UNORIENTED, 0, bot_ip.num_vertices, bot_ip.num_faces, bot_ip.vertices, bot_ip.faces, bot_ip.thickness, bot_ip.face_mode); if (mode == PLATE_MODE) { bu_free((char *)bot_ip.thickness, "BOT thickness"); bu_free((char *)bot_ip.face_mode, "BOT face_mode"); } bu_free((char *)bot_ip.vertices, "BOT vertices"); bu_free((char *)bot_ip.faces, "BOT faces"); }
int bn_tri_tri_isect_with_line(point_t V0, point_t V1, point_t V2, point_t U0, point_t U1, point_t U2, int *coplanar, point_t *isectpt1, point_t *isectpt2) { point_t E1, E2; point_t N1, N2; fastf_t d1, d2; fastf_t du0, du1, du2, dv0, dv1, dv2; fastf_t D[3]; fastf_t isect1[2] = {0, 0}; fastf_t isect2[2] = {0, 0}; point_t isectpointA1 = VINIT_ZERO; point_t isectpointA2 = VINIT_ZERO; point_t isectpointB1 = VINIT_ZERO; point_t isectpointB2 = VINIT_ZERO; fastf_t du0du1, du0du2, dv0dv1, dv0dv2; short index; fastf_t vp0, vp1, vp2; fastf_t up0, up1, up2; fastf_t b, c, max; int smallest1, smallest2; /* compute plane equation of triangle(V0, V1, V2) */ VSUB2(E1, V1, V0); VSUB2(E2, V2, V0); VCROSS(N1, E1, E2); d1=-VDOT(N1, V0); /* plane equation 1: N1.X+d1=0 */ /* put U0, U1, U2 into plane equation 1 to compute signed distances to the plane*/ du0=VDOT(N1, U0)+d1; du1=VDOT(N1, U1)+d1; du2=VDOT(N1, U2)+d1; /* coplanarity robustness check */ #if USE_EPSILON_TEST if (fabs(du0)<EPSILON) du0=0.0; if (fabs(du1)<EPSILON) du1=0.0; if (fabs(du2)<EPSILON) du2=0.0; #endif du0du1=du0*du1; du0du2=du0*du2; if (du0du1>0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute plane of triangle (U0, U1, U2) */ VSUB2(E1, U1, U0); VSUB2(E2, U2, U0); VCROSS(N2, E1, E2); d2=-VDOT(N2, U0); /* plane equation 2: N2.X+d2=0 */ /* put V0, V1, V2 into plane equation 2 */ dv0=VDOT(N2, V0)+d2; dv1=VDOT(N2, V1)+d2; dv2=VDOT(N2, V2)+d2; #if USE_EPSILON_TEST if (fabs(dv0)<EPSILON) dv0=0.0; if (fabs(dv1)<EPSILON) dv1=0.0; if (fabs(dv2)<EPSILON) dv2=0.0; #endif dv0dv1=dv0*dv1; dv0dv2=dv0*dv2; if (dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute direction of intersection line */ VCROSS(D, N1, N2); /* compute and index to the largest component of D */ max=fabs(D[0]); index=0; b=fabs(D[1]); c=fabs(D[2]); if (b>max) max=b, index=1; if (c>max) index=2; /* this is the simplified projection onto L*/ vp0=V0[index]; vp1=V1[index]; vp2=V2[index]; up0=U0[index]; up1=U1[index]; up2=U2[index]; /* compute interval for triangle 1 */ *coplanar=compute_intervals_isectline(V0, V1, V2, vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2, &isect1[0], &isect1[1], isectpointA1, isectpointA2); if (*coplanar) return coplanar_tri_tri(N1, V0, V1, V2, U0, U1, U2); /* compute interval for triangle 2 */ compute_intervals_isectline(U0, U1, U2, up0, up1, up2, du0, du1, du2, du0du1, du0du2, &isect2[0], &isect2[1], isectpointB1, isectpointB2); SORT2(isect1[0], isect1[1], smallest1); SORT2(isect2[0], isect2[1], smallest2); if (isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0; /* at this point, we know that the triangles intersect */ if (isect2[0]<isect1[0]) { if (smallest1==0) { VMOVE(*isectpt1, isectpointA1); } else { VMOVE(*isectpt1, isectpointA2); } if (isect2[1]<isect1[1]) { if (smallest2==0) { VMOVE(*isectpt2, isectpointB2); } else { VMOVE(*isectpt2, isectpointB1); } } else { if (smallest1==0) { VMOVE(*isectpt2, isectpointA2); } else { VMOVE(*isectpt2, isectpointA1); } } } else { if (smallest2==0) { VMOVE(*isectpt1, isectpointB1); } else { VMOVE(*isectpt1, isectpointB2); } if (isect2[1]>isect1[1]) { if (smallest1==0) { VMOVE(*isectpt2, isectpointA2); } else { VMOVE(*isectpt2, isectpointA1); } } else { if (smallest2==0) { VMOVE(*isectpt2, isectpointB2); } else { VMOVE(*isectpt2, isectpointB1); } } } return 1; }