示例#1
0
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;
}
示例#2
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;
}
示例#3
0
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;
}
示例#4
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(&reg_head.l);
    (void)mk_addmember(nm, &reg_head.l, NULL, WMOP_UNION);
    (void)mk_addmember(s1->s_name, &reg_head.l, NULL, WMOP_SUBTRACT);
    (void)mk_addmember(s2->s_name, &reg_head.l, NULL, WMOP_SUBTRACT);
    sprintf(nm1, "BOND.%d.%d", sp1, sp2);
    mk_lcomb(outfp, nm1, &reg_head, 1, matname, matparm, rgb, 0);
    (void)mk_addmember(nm1, &head.l, NULL, WMOP_UNION);

    return 0;		/* OK */
}
示例#5
0
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);
    }
}
示例#6
0
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(&reg_head.l);
    (void)mk_addmember(nm1, &reg_head.l, NULL, WMOP_UNION);
    sprintf(nm, "SPH.%d", id);
    mk_lcomb(outfp, nm, &reg_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;
    }
}
示例#7
0
文件: proe-g.c 项目: cciechad/brlcad
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);
    }
示例#9
0
文件: lens.c 项目: cogitokat/brlcad
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");
    }
}
示例#10
0
/**
 *	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");
}
示例#11
0
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;
}