int mk_ring(struct rt_wdb *fp, double orbit, double width, double thick, double wallthick, double wallheight) { point_t base = {0, 0, 0}, height = {0, 0, 0}; struct wmember c; /* make 3 rcc's and glue them together */ /* this additive component */ base[Z] = -1000*width/2.0; height[Z] = 1000*width; mk_rcc(fp, "ringadd.s", base, height, 1000*orbit); /* the small cut to make the walls 'n stuff */ base[Z] += 1000*wallthick; height[Z] -= 1000*2.0*wallthick; mk_rcc(fp, "ringsub1.s", base, height, 1000*(orbit-thick)); /* the big cut out of the middle */ base[Z] = -1000*width; height[Z] = 1000*2*width; mk_rcc(fp, "ringsub2.s", base, height, 1000*(orbit - wallheight)); /* and do the CSG */ BU_LIST_INIT(&c.l); mk_addmember("ringadd.s", &c.l, NULL, WMOP_UNION); mk_addmember("ringsub1.s", &c.l, NULL, WMOP_SUBTRACT); mk_addmember("ringsub2.s", &c.l, NULL, WMOP_SUBTRACT); mk_lcomb(fp, "ring.r", &c, 1, "plastic", "", NULL, 0); return 0; }
int main(int argc, char *argv[]) { static const char usage[] = "Usage:\n%s [-o outfile] \n\n -o file \tFile to write out (default: ringworld.g)\n\n"; char outfile[MAXPATHLEN] = "ringworld.g"; int optc; struct rt_wdb *fp; while ((optc = bu_getopt(argc, argv, "o:h?")) != -1) { if (bu_optopt == '?') optc='h'; switch (optc) { case 'o': snprintf(outfile, MAXPATHLEN, "%s", bu_optarg); break; default: fprintf(stderr,usage, *argv); return optc == '?' ? EXIT_FAILURE : EXIT_SUCCESS; } } if (argc == 1) { fprintf(stderr,usage, *argv); fprintf(stderr," Program continues running:\n"); } if (bu_file_exists(outfile, NULL)) bu_exit(EXIT_FAILURE, "ERROR: %s already exists. Remove file and try again.", outfile); bu_log("Writing ringworld out to [%s]\n", outfile); fp = wdb_fopen(outfile); mk_sol(fp, SUN_DIAMETER); mk_ring(fp, RING_ORBIT, RING_WIDTH, RING_FLOOR_THICKNESS, RING_WALL_THICKNESS, RING_WALL_HEIGHT); mk_shadowring(fp, SHADOWRING_ORBIT, SHADOWRING_NUM, SHADOWRING_WIDTH, SHADOWRING_LENGTH, SHADOWRING_THICKNESS); /* generate a comb all.g */ { struct wmember c; BU_LIST_INIT(&c.l); mk_addmember("ring.r", &c.l, NULL, WMOP_UNION); mk_addmember("sun.r", &c.l, NULL, WMOP_UNION); /* mk_addmember("shadowring.r", &c.l, NULL, WMOP_UNION); */ mk_lcomb(fp, "all.g", &c, 0, NULL, NULL, NULL, 0); } wdb_close(fp); bu_log("BRL-CAD geometry database file [%s] created.\nDone.\n", outfile); return EXIT_SUCCESS; }
int mk_sol(struct rt_wdb *fp, double radius) { struct wmember c; point_t p = { 0, 0, 0}; /* make a sphere! tada! */ mk_sph(fp, "sun.s", p, radius * 1000.0); BU_LIST_INIT(&c.l); mk_addmember("sun.s", &c.l, NULL, WMOP_UNION); mk_lcomb(fp, "sun.r", &c, 1, NULL, NULL, NULL, 0); return 0; }
int make_bond(int sp1, int sp2) { struct sphere * s1, *s2, *s_ptr; point_t base; vect_t height; char nm[128], nm1[128]; unsigned char rgb[3]; struct wmember reg_head; s1 = s2 = (struct sphere *) 0; for (s_ptr = s_head; s_ptr != (struct sphere *)0; s_ptr = s_ptr->next) { if (s_ptr->s_id == sp1) s1 = s_ptr; if (s_ptr->s_id == sp2) s2 = s_ptr; } if (s1 == (struct sphere *) 0 || s2 == (struct sphere *)0) return -1; /* error */ VMOVE(base, s1->s_center); VSUB2(height, s2->s_center, s1->s_center); sprintf(nm, "bond.%d.%d", sp1, sp2); rgb[0] = 191; rgb[1] = 142; rgb[2] = 57; #if 1 /* Use this for mol-cube.dat */ mk_rcc(outfp, nm, base, height, s1->s_rad * 0.15); #else /* Use this for chemical molecules */ mk_rcc(outfp, nm, base, height, s1->s_rad * 0.5); #endif BU_LIST_INIT(®_head.l); (void)mk_addmember(nm, ®_head.l, NULL, WMOP_UNION); (void)mk_addmember(s1->s_name, ®_head.l, NULL, WMOP_SUBTRACT); (void)mk_addmember(s2->s_name, ®_head.l, NULL, WMOP_SUBTRACT); sprintf(nm1, "BOND.%d.%d", sp1, sp2); mk_lcomb(outfp, nm1, ®_head, 1, matname, matparm, rgb, 0); (void)mk_addmember(nm1, &head.l, NULL, WMOP_UNION); return 0; /* OK */ }
void do_tree(char *name, char *lname, int level) { int i; char nm[64]; char *leafp; int scale; struct wmember head; struct wmember *wp; BU_LIST_INIT(&head.l); if (level <= 1) leafp = lname; else leafp = nm; scale = 100; for (i=1; i<level; i++) scale *= 2; snprintf(nm, 64, "%sL", name); wp = mk_addmember(leafp, &head.l, NULL, WMOP_UNION); MAT_IDN(wp->wm_mat); snprintf(nm, 64, "%sR", name); wp = mk_addmember(leafp, &head.l, NULL, WMOP_UNION); MAT_DELTAS(wp->wm_mat, 1*scale, 0, 0); snprintf(nm, 64, "%sB", name); wp = mk_addmember(leafp, &head.l, NULL, WMOP_UNION); MAT_DELTAS(wp->wm_mat, 0.5*scale, sin60*scale, 0); snprintf(nm, 64, "%sT", name); wp = mk_addmember(leafp, &head.l, NULL, WMOP_UNION); MAT_DELTAS(wp->wm_mat, 0.5*scale, sin60/3*scale, sin60*scale); /* Set region flag on lowest level */ mk_lcomb(outfp, name, &head, level<=1, NULL, NULL, NULL, 0); /* Loop for children if level > 1 */ if (level <= 1) return; for (i=0; i<4; i++) { snprintf(nm, 64, "%s%c", name, "LRBTx"[i]); do_tree(nm, lname, level-1); } }
void process_sphere(int id, fastf_t *center, double rad, int sph_type) { struct sphere *newsph; char nm[128], nm1[128]; unsigned char rgb[3]; struct wmember reg_head; BU_ALLOC(newsph, struct sphere); rgb[0] = atom_list[sph_type].red; rgb[1] = atom_list[sph_type].green; rgb[2] = atom_list[sph_type].blue; sprintf(nm1, "sph.%d", id); mk_sph(outfp, nm1, center, rad); /* Create a region nm to contain the solid nm1 */ BU_LIST_INIT(®_head.l); (void)mk_addmember(nm1, ®_head.l, NULL, WMOP_UNION); sprintf(nm, "SPH.%d", id); mk_lcomb(outfp, nm, ®_head, 1, matname, matparm, rgb, 0); /* Include this region in the larger group */ (void)mk_addmember(nm, &head.l, NULL, WMOP_UNION); newsph->next = (struct sphere *)0; newsph->s_id = id; bu_strlcpy(newsph->s_name, nm1, sizeof(newsph->s_name)); newsph->s_name[14] = '\0'; VMOVE(newsph->s_center, center); newsph->s_rad = rad; newsph->s_atom_type = sph_type; if (s_head == (struct sphere *) 0) { s_head = s_list = newsph; } else { s_list->next = newsph; s_list = newsph; } }
static void Convert_assy(char *line) { struct wmember head; struct wmember *wmem = NULL; char line1[MAX_LINE_SIZE]; char name[MAX_LINE_SIZE]; unsigned int obj; char memb_name[MAX_LINE_SIZE]; unsigned int memb_obj; char *brlcad_name = NULL; float mat_col[4]; float junk; int start; int i; if ( RT_G_DEBUG & DEBUG_MEM_FULL ) { bu_log( "Barrier check at start of Convert_assy:\n" ); if ( bu_mem_barriercheck() ) bu_exit(EXIT_FAILURE, "Barrier check failed!!!\n" ); } BU_LIST_INIT( &head.l ); start = (-1); /* skip leading blanks */ while ( isspace( line[++start] ) && line[start] != '\0' ); if ( strncmp( &line[start], "assembly", 8 ) && strncmp( &line[start], "ASSEMBLY", 8 ) ) { bu_log( "PROE-G: Convert_assy called for non-assembly:\n%s\n", line ); return; } /* skip blanks before name */ start += 7; while ( isspace( line[++start] ) && line[start] != '\0' ); /* get name */ i = (-1); start--; while ( !isspace( line[++start] ) && line[start] != '\0' && line[start] != '\n' ) name[++i] = line[start]; name[++i] = '\0'; /* get object pointer */ sscanf( &line[start], "%x %f", &obj, &junk ); bu_log( "Converting Assembly: %s\n", name ); if ( debug ) bu_log( "Convert_assy: %s x%x\n", name, obj ); while ( bu_fgets( line1, MAX_LINE_SIZE, fd_in ) ) { /* skip leading blanks */ start = (-1); while ( isspace( line1[++start] ) && line[start] != '\0' ); if ( !strncmp( &line1[start], "endassembly", 11 ) || !strncmp( &line1[start], "ENDASSEMBLY", 11 ) ) { brlcad_name = Get_unique_name( name, obj, ASSEMBLY_TYPE ); if ( debug ) { struct wmember *wp; bu_log( "\tmake assembly ( %s)\n", brlcad_name ); for ( BU_LIST_FOR( wp, wmember, &head.l ) ) bu_log( "\t%c %s\n", wp->wm_op, wp->wm_name ); } else bu_log( "\tUsing name: %s\n", brlcad_name ); mk_lcomb( fd_out, brlcad_name, &head, 0 , (char *)NULL, (char *)NULL, (unsigned char *)NULL, 0 ); break; }
void Do_subfigs() { int i, j; int entity_type; struct wmember head1; struct wmember *wmem; if (RT_G_DEBUG & DEBUG_MEM_FULL) bu_mem_barriercheck(); BU_LIST_INIT(&head1.l); for (i = 0; i < totentities; i++) { int subfigdef_de; int subfigdef_index; int no_of_members; int *members; char *name = NULL; struct wmember head2; double mat_scale[3]; int non_unit; if (dir[i]->type != 408) continue; if (RT_G_DEBUG & DEBUG_MEM_FULL) bu_mem_barriercheck(); if (dir[i]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[i]->direct, dir[i]->name); continue; } Readrec(dir[i]->param); Readint(&entity_type, ""); if (entity_type != 408) { bu_log("Expected Singular Subfigure Instance Entity, found %s\n", iges_type(entity_type)); continue; } Readint(&subfigdef_de, ""); subfigdef_index = (subfigdef_de - 1)/2; if (subfigdef_index >= totentities) { bu_log("Singular Subfigure Instance Entity gives Subfigure Definition"); bu_log("\tEntity DE of %d, largest DE in file is %d\n", subfigdef_de, (totentities * 2) - 1); continue; } if (dir[subfigdef_index]->type != 308) { bu_log("Expected Subfigure Definition Entity, found %s\n", iges_type(dir[subfigdef_index]->type)); continue; } if (dir[subfigdef_index]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[subfigdef_index]->direct, dir[subfigdef_index]->name); continue; } Readrec(dir[subfigdef_index]->param); Readint(&entity_type, ""); if (entity_type != 308) { bu_log("Expected Subfigure Definition Entity, found %s\n", iges_type(entity_type)); continue; } Readint(&j, ""); /* ignore depth */ Readstrg(""); /* ignore subfigure name */ wmem = mk_addmember(dir[subfigdef_index]->name, &head1.l, NULL, WMOP_UNION); non_unit = 0; for (j = 0; j < 3; j++) { double mag_sq; mat_scale[j] = 1.0; mag_sq = MAGSQ(&(*dir[i]->rot)[j*4]); /* FIXME: arbitrary undefined tolerance */ if (!NEAR_EQUAL(mag_sq, 1.0, 100.0*SQRT_SMALL_FASTF)) { mat_scale[j] = 1.0/sqrt(mag_sq); non_unit = 1; } } if (non_unit) { bu_log("Illegal transformation matrix in %s for member %s\n", curr_file->obj_name, wmem->wm_name); bu_log(" row vector magnitudes are %g, %g, and %g\n", 1.0/mat_scale[0], 1.0/mat_scale[1], 1.0/mat_scale[2]); bn_mat_print("", *dir[i]->rot); for (j = 0; j < 11; j++) { if ((j+1)%4 == 0) continue; (*dir[i]->rot)[j] *= mat_scale[0]; } bn_mat_print("After scaling:", *dir[i]->rot); } memcpy(wmem->wm_mat, *dir[i]->rot, sizeof(mat_t)); Readint(&no_of_members, ""); /* get number of members */ members = (int *)bu_calloc(no_of_members, sizeof(int), "Do_subfigs: members"); for (j = 0; j < no_of_members; j++) Readint(&members[j], ""); BU_LIST_INIT(&head2.l); for (j = 0; j < no_of_members; j++) { int idx; idx = (members[j] - 1)/2; if (idx >= totentities) { bu_log("Subfigure Definition Entity gives Member Entity"); bu_log("\tDE of %d, largest DE in file is %d\n", members[j], (totentities * 2) - 1); continue; } if (dir[idx]->param <= pstart) { bu_log("Illegal parameter pointer for entity D%07d (%s)\n" , dir[idx]->direct, dir[idx]->name); continue; } if (dir[idx]->type == 416) { struct file_list *list_ptr; char *file_name; int found = 0; /* external reference */ Readrec(dir[idx]->param); Readint(&entity_type, ""); if (entity_type != 416) { bu_log("Expected External reference Entity, found %s\n", iges_type(entity_type)); continue; } if (dir[idx]->form != 1) { bu_log("External Reference Entity of form #%d found\n", dir[idx]->form); bu_log("\tOnly form #1 is currently handled\n"); continue; } Readname(&file_name, ""); /* Check if this external reference is already on the list */ for (BU_LIST_FOR(list_ptr, file_list, &iges_list.l)) { if (BU_STR_EQUAL(file_name, list_ptr->file_name)) { found = 1; name = list_ptr->obj_name; break; } } if (!found) { /* Need to add this one to the list */ BU_ALLOC(list_ptr, struct file_list); list_ptr->file_name = file_name; if (no_of_members == 1) bu_strlcpy(list_ptr->obj_name, dir[subfigdef_index]->name, NAMESIZE+1); else { bu_strlcpy(list_ptr->obj_name, "subfig", NAMESIZE+1); (void) Make_unique_brl_name(list_ptr->obj_name); } BU_LIST_APPEND(&curr_file->l, &list_ptr->l); name = list_ptr->obj_name; } else bu_free((char *)file_name, "Do_subfigs: file_name"); } else name = dir[idx]->name; if (no_of_members > 1) { wmem = mk_addmember(name, &head2.l, NULL, WMOP_UNION); memcpy(wmem->wm_mat, dir[idx]->rot, sizeof(mat_t)); } } if (no_of_members > 1) (void)mk_lcomb(fdout, dir[subfigdef_index]->name, &head2, 0, (char *)NULL, (char *)NULL, (unsigned char *)NULL, 0); }
void MakeP(struct rt_wdb (*file), char *prefix, fastf_t diameter, fastf_t focal_length, fastf_t ref_ind, fastf_t thickness) { struct wmember lensglass, lens; struct bu_vls str = BU_VLS_INIT_ZERO; fastf_t sph_R, epa_H, epa_R, rcc_h; int lens_type; point_t origin; vect_t height; vect_t breadth; if (focal_length > 0) { lens_type = 1; } else { lens_type = -1; } sph_R = lens_type*focal_length*(ref_ind - 1); bu_log("sph_R = %f\n", sph_R); epa_R = diameter / 2; bu_log("epa_R = %f\n", epa_R); epa_H = sph_R - sqrt(sph_R*sph_R-epa_R*epa_R); bu_log("epa_H = %f\n", epa_H); rcc_h = thickness - lens_type * epa_H; bu_log("rcc_h = %f\n", rcc_h); BU_LIST_INIT(&lensglass.l); BU_LIST_INIT(&lens.l); if (epa_R > 0 && epa_H > 0) { if (rcc_h < 0) bu_log("Warning - specified thickness too thin for lens\n"); if (rcc_h >= 0) { VSET(origin, 0, 0, 0); VSET(height, 0, -rcc_h, 0); bu_vls_trunc(&str, 0); bu_vls_printf(&str, "%s-cyl.s", prefix); mk_rcc(file, bu_vls_addr(&str), origin, height, diameter/2); (void)mk_addmember(bu_vls_addr(&str), &lensglass.l, NULL, WMOP_UNION); } VSET(origin, 0, -rcc_h, 0); VSET(height, 0, -1*lens_type*epa_H, 0); VSET(breadth, 0, 0, 1); bu_vls_trunc(&str, 0); bu_vls_printf(&str, "%s-epa.s", prefix); mk_epa(file, bu_vls_addr(&str), origin, height, breadth, epa_R, epa_R); if (lens_type == 1) { (void)mk_addmember(bu_vls_addr(&str), &lensglass.l, NULL, WMOP_UNION); } else { (void)mk_addmember(bu_vls_addr(&str), &lensglass.l, NULL, WMOP_SUBTRACT); } bu_vls_trunc(&str, 0); bu_vls_printf(&str, "%s.c", prefix); mk_lcomb(file, bu_vls_addr(&str), &lensglass, 0, NULL, NULL, NULL, 0); (void)mk_addmember(bu_vls_addr(&str), &lens.l, NULL, WMOP_UNION); bu_vls_trunc(&str, 0); bu_vls_printf(&str, "%s.r", prefix); mk_lcomb(file, bu_vls_addr(&str), &lens, 1, "glass", "ri=1.5", NULL, 0); } else { bu_log("Error - specified parameters result in non-physical geometry"); } }
/** * P O P _ S P A W N --- spawn a new population * TODO: generalize/modularize somehow to allow adding more shapes and primitives * also use variable/defined rates, intersection with bounding box, etc... */ void pop_spawn (struct population *p) { int i, j; point_t p1/*, p2, p3*/; struct wmember wm_hd; double r1/*, r2, r3*/; char shape[256]; p->db_p = db_create("gen000", 5); p->db_p->dbi_wdbp = wdb_dbopen(p->db_p, RT_WDB_TYPE_DB_DISK); for (i = 0; i < p->size; i++) { p->name[i] = bu_malloc(sizeof(char) * 256, "name"); snprintf(p->name[i], 256, "ind%.3d", i); BU_LIST_INIT(&wm_hd.l); /* VSET(p1, -5, -5, -5); VSET(p2, 5, 5, 5); r1 = r2 = 2.5; */ for (j = 0; j < 6; j++) { /* VSETALL(p1, -10+pop_rand()*10); */ p1[0] = -10*pop_rand()*10; p1[1] = -10*pop_rand()*10; p1[2] = -10*pop_rand()*10; r1 = 1+3*pop_rand(); snprintf(shape, 256, "ind%.3d-%.3d", i, j); mk_sph(p->db_p->dbi_wdbp, shape, p1, r1); mk_addmember(shape, &wm_hd.l, NULL, WMOP_UNION); } p->parent[i].fitness = 0.0; p->parent[i].id = i; /* snprintf(shape, 256, "ind%.3d-%.3d", i, 0); mk_sph(p->db_p->dbi_wdbp, shape, p1, r1); mk_addmember(shape, &wm_hd.l, NULL, WMOP_UNION); snprintf(shape, 256, "ind%.3d-%.3d", i, 1); mk_sph(p->db_p->dbi_wdbp, shape, p2, r2); mk_addmember(shape, &wm_hd.l, NULL, WMOP_UNION); snprintf(shape, 256, "gen%.3dind%.3d-%.3d", 0, i, 2); mk_sph(p->db_p->dbi_wdbp, shape, p3, r3); mk_addmember(shape, &wm_hd.l, NULL, WMOP_UNION); */ mk_lcomb(p->db_p->dbi_wdbp, NL_P(p->parent[i].id), &wm_hd, 1, NULL, NULL, NULL, 0); } /* * reload the db so we dont * have to do any extra checks * in the main loop */ wdb_close(p->db_p->dbi_wdbp); if ((p->db_p = db_open("gen000", "r")) == DBI_NULL) bu_exit(EXIT_FAILURE, "Failed to re-open initial population"); if (db_dirbuild(p->db_p) < 0) bu_exit(EXIT_FAILURE, "Failed to load initial database"); }
int main(int argc, char **argv) { int frame; char name[128]; char gname[128]; vect_t normal; struct wmember head, ghead; matp_t matp; mat_t xlate; mat_t rot1, rot2, rot3; vect_t from, to; vect_t offset; if (argc > 0) { bu_log("Usage: %s\n", argv[0]); bu_log(" (Program expects ./pos.dat file to be present)\n"); bu_log(" (Will generate file tube.g)\n"); if (argc == 2) { if ( BU_STR_EQUAL(argv[1],"-h") || BU_STR_EQUAL(argv[1],"-?")) bu_exit(1,NULL); } else if (argc == 1) bu_log(" Program continues running:\n"); } BU_LIST_INIT(&head.l); BU_LIST_INIT(&ghead.l); outfp = wdb_fopen("tube.g"); if ((pos_fp = fopen("pos.dat", "r")) == NULL) perror("pos.dat"); /* Just warn */ mk_id(outfp, "Procedural Gun Tube with Projectile"); VSET(normal, 0, -1, 0); mk_half(outfp, "cut", normal, 0.0); VSET(normal, 0, 1, 0); mk_half(outfp, "bg.s", normal, -1000.0); (void)mk_addmember("bg.s", &head.l, NULL, WMOP_UNION); /* temp use of "head" */ mk_lcomb(outfp, "bg.r", &head, 1, "texture", "file=movie128bw.pix w=128", (unsigned char *)0, 0); #ifdef never /* Numbers for a 105-mm M68 gun */ oradius = 5 * inches2mm / 2; /* 5" outer diameter */ iradius = 4.134 * inches2mm / 2; /* 5" inner (land) diameter */ #else /* Numbers invented to match 125-mm KE (Erline) round */ iradius = 125.0/2; oradius = iradius + (5-4.134) * inches2mm / 2; /* 5" outer diameter */ #endif fprintf(stderr, "inner radius=%gmm, outer radius=%gmm\n", iradius, oradius); length = 187.0 * inches2mm; #ifdef never spacing = 100.; /* mm per sample */ nsamples = ceil(length/spacing); fprintf(stderr, "length=%gmm, spacing=%gmm\n", length, spacing); fprintf(stderr, "nframes=%d\n", nframes); #endif for (frame=0;; frame++) { cur_time = frame * delta_t; #ifdef never /* Generate some dummy sample data */ if (frame < 16) break; for (i=0; i<nsamples; i++) { sample[i][X] = i * spacing; sample[i][Y] = 0; sample[i][Z] = 4 * oradius * sin( ((double)i*i)/nsamples * M_2PI + frame * M_PI_4); } projectile_pos = ((double)frame)/nframes * (sample[nsamples-1][X] - sample[0][X]); /* length */ #else if (read_frame(stdin) < 0) break; if (pos_fp != NULL) read_pos(pos_fp); #endif #define build_spline build_cyl sprintf(name, "tube%do", frame); build_spline(name, nsamples, oradius); (void)mk_addmember(name, &head.l, NULL, WMOP_UNION); sprintf(name, "tube%di", frame); build_spline(name, nsamples, iradius); mk_addmember(name, &head.l, NULL, WMOP_SUBTRACT); mk_addmember("cut", &head.l, NULL, WMOP_SUBTRACT); sprintf(name, "tube%d", frame); mk_lcomb(outfp, name, &head, 1, "plastic", "", (unsigned char *)0, 0); /* Place the tube region and the ammo together. * The origin of the ammo is expected to be the center * of the rearmost plate. */ mk_addmember(name, &ghead.l, NULL, WMOP_UNION); matp = mk_addmember("ke", &ghead.l, NULL, WMOP_UNION)->wm_mat; VSET(from, 0, -1, 0); VSET(to, 1, 0, 0); /* to X axis */ bn_mat_fromto(rot1, from, to, &outfp->wdb_tol); VSET(from, 1, 0, 0); /* Projectile is 480mm long -- use center pt, not end */ xfinddir(to, projectile_pos + 480.0/2, offset); bn_mat_fromto(rot2, from, to, &outfp->wdb_tol); MAT_IDN(xlate); MAT_DELTAS_VEC(xlate, offset); bn_mat_mul(rot3, rot2, rot1); bn_mat_mul(matp, xlate, rot3); (void)mk_addmember("light.r", &ghead.l, NULL, WMOP_UNION); (void)mk_addmember("bg.r", &ghead.l, NULL, WMOP_UNION); sprintf(gname, "g%d", frame); mk_lcomb(outfp, gname, &ghead, 0, (char *)0, "", (unsigned char *)0, 0); fprintf(stderr, "frame %d\n", frame); fflush(stderr); } wdb_close(outfp); fflush(stderr); return 0; }